Coverage Report

Created: 2026-04-12 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libdwarf/fuzz/fuzz_set_frame_all.c
Line
Count
Source
1
/* Copyright 2021 Google LLC
2
Licensed under the Apache License, Version 2.0 (the "License");
3
you may not use this file except in compliance with the License.
4
You may obtain a copy of the License at
5
      http://www.apache.org/licenses/LICENSE-2.0
6
Unless required by applicable law or agreed to in writing, software
7
distributed under the License is distributed on an "AS IS" BASIS,
8
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9
See the License for the specific language governing permissions and
10
limitations under the License.
11
*/
12
#include <fcntl.h> /* open() O_RDONLY O_BINARY */
13
#include <limits.h>
14
#include <stdint.h>
15
#include <stdio.h>
16
#include <stdlib.h>
17
#include <string.h>
18
#include <sys/types.h>
19
#include <unistd.h>
20
#include "dwarf.h"
21
#include "libdwarf.h"
22
23
#ifndef O_BINARY
24
13.6k
#define O_BINARY 0 /* So it does nothing in Linux/Unix */
25
#endif
26
645k
#define DW_PR_DUx "llx"
27
#define DW_PR_DSx "llx"
28
104k
#define DW_PR_DUu "llu"
29
61.1k
#define DW_PR_DSd "lld"
30
31
static void read_frame_data(Dwarf_Debug dbg, const char *sec);
32
static void print_fde_instrs(Dwarf_Debug dbg, Dwarf_Fde fde,
33
                             Dwarf_Error *error);
34
static void print_regtable(Dwarf_Regtable3 *tab3);
35
static void print_cie_instrs(Dwarf_Cie cie, Dwarf_Error *error);
36
static void print_fde_selected_regs(Dwarf_Fde fde);
37
static void print_reg(int r);
38
static void dump_block(char *prefix, Dwarf_Small *data, Dwarf_Unsigned len);
39
40
319k
#define UNDEF_VAL 2000
41
319k
#define SAME_VAL 2001
42
31.8k
#define CFA_VAL 2002
43
319k
#define INITIAL_VAL UNDEF_VAL
44
45
/*  Because this code does exit() without
46
    calling dwarf_finish() in case of certain
47
    errors in corrupted objects, executing the program is
48
    guaranteed to leak memory when that class
49
    of errors is found in the object file being read.
50
51
    David Anderson
52
53
    As of 30 May 2023 all the exit() calls (other
54
    than the open() call) are changed to
55
    return; instead so we do not leak memory.
56
    In addition the tab3.rt3_rules the code mallocs
57
    here is always freed here now. */
58
59
13.6k
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
60
13.6k
  char filename[256];
61
62
#ifdef DWREGRESSIONTEMP
63
  /*  Under msys2, the /tmp/ results in an open fail,
64
      so we discard the /tmp/ here */
65
  sprintf(filename, "junklibfuzzer.%d", getpid());
66
#else
67
13.6k
  sprintf(filename, "/tmp/libfuzzer.%d", getpid());
68
13.6k
#endif
69
13.6k
  FILE *fp = fopen(filename, "wb");
70
13.6k
  if (!fp) {
71
0
    printf("FAIL libfuzzer cannot open temp as writeable %s\n",
72
0
        filename);
73
0
    return 0;
74
0
  }
75
13.6k
  fwrite(data, size, 1, fp);
76
13.6k
  fclose(fp);
77
78
13.6k
  Dwarf_Debug dbg = 0;
79
13.6k
  int res = DW_DLV_ERROR;
80
13.6k
  Dwarf_Error error = 0;
81
13.6k
  Dwarf_Handler errhand = 0;
82
13.6k
  Dwarf_Ptr errarg = 0;
83
13.6k
  int regtabrulecount = 0;
84
13.6k
  int curopt = 0;
85
86
13.6k
  int fd = open(filename, O_RDONLY | O_BINARY);
87
13.6k
  if (fd < 0) {
88
0
    printf("Unable to open %s, giving up.\n", filename);
89
0
    exit(EXIT_FAILURE);
90
0
  }
91
92
13.6k
  res = dwarf_init_b(fd, DW_GROUPNUMBER_ANY, errhand, errarg, &dbg, &error);
93
94
13.6k
  if (res != DW_DLV_OK) {
95
7.37k
    printf("Giving up, dwarf_init failed, "
96
7.37k
           "cannot do DWARF processing\n");
97
7.37k
    if (res == DW_DLV_ERROR) {
98
5.36k
      printf("Error code %s\n", dwarf_errmsg(error));
99
5.36k
    }
100
7.37k
    dwarf_dealloc_error(dbg, error);
101
7.37k
  } else {
102
6.24k
    Dwarf_Half frame_values[] = {SHRT_MIN, SHRT_MAX, 0};
103
24.9k
    for (int i = 0; i < 3; i++) {
104
18.7k
      dwarf_set_frame_undefined_value(dbg, frame_values[i]);
105
18.7k
      read_frame_data(dbg, ".debug_frame");
106
18.7k
      read_frame_data(dbg, ".eh_frame");
107
18.7k
    }
108
24.9k
    for (int i = 0; i < 3; i++) {
109
18.7k
      dwarf_set_frame_rule_initial_value(dbg, frame_values[i]);
110
18.7k
      read_frame_data(dbg, ".debug_frame");
111
18.7k
      read_frame_data(dbg, ".eh_frame");
112
18.7k
    }
113
24.9k
    for (int i = 0; i < 3; i++) {
114
18.7k
      dwarf_set_frame_same_value(dbg, frame_values[i]);
115
18.7k
      read_frame_data(dbg, ".debug_frame");
116
18.7k
      read_frame_data(dbg, ".eh_frame");
117
18.7k
    }
118
24.9k
    for (int i = 0; i < 3; i++) {
119
18.7k
      dwarf_set_frame_cfa_value(dbg, frame_values[i]);
120
18.7k
      read_frame_data(dbg, ".debug_frame");
121
18.7k
      read_frame_data(dbg, ".eh_frame");
122
18.7k
    }
123
24.9k
    for (int i = 0; i < 3; i++) {
124
18.7k
      dwarf_set_frame_rule_table_size(dbg, frame_values[i]);
125
18.7k
      read_frame_data(dbg, ".debug_frame");
126
18.7k
      read_frame_data(dbg, ".eh_frame");
127
18.7k
    }
128
6.24k
  }
129
130
13.6k
  res = dwarf_finish(dbg);
131
13.6k
  close(fd);
132
13.6k
  unlink(filename);
133
13.6k
  return 0;
134
13.6k
}
135
136
3.25k
static void dump_block(char *prefix, Dwarf_Small *data, Dwarf_Unsigned len) {
137
3.25k
  Dwarf_Small *end_data = data + len;
138
3.25k
  Dwarf_Small *cur = data;
139
3.25k
  int i = 0;
140
141
3.25k
  printf("%s", prefix);
142
16.6k
  for (; cur < end_data; ++cur, ++i) {
143
13.4k
    if (i > 0 && i % 4 == 0)
144
1.35k
      printf(" ");
145
13.4k
    printf("%02x", 0xff & *cur);
146
13.4k
  }
147
3.25k
}
148
149
187k
static void read_frame_data(Dwarf_Debug dbg, const char *sect) {
150
187k
  Dwarf_Error error;
151
187k
  Dwarf_Signed cie_element_count = 0;
152
187k
  Dwarf_Signed fde_element_count = 0;
153
187k
  Dwarf_Cie *cie_data = 0;
154
187k
  Dwarf_Fde *fde_data = 0;
155
187k
  int res = DW_DLV_ERROR;
156
187k
  Dwarf_Signed fdenum = 0;
157
158
187k
  printf(" Print %s\n", sect);
159
187k
  if (!strcmp(sect, ".eh_frame")) {
160
93.6k
    res = dwarf_get_fde_list_eh(dbg, &cie_data, &cie_element_count, &fde_data,
161
93.6k
                                &fde_element_count, &error);
162
93.6k
  } else {
163
93.6k
    res = dwarf_get_fde_list(dbg, &cie_data, &cie_element_count, &fde_data,
164
93.6k
                             &fde_element_count, &error);
165
93.6k
  }
166
187k
  if (res == DW_DLV_NO_ENTRY) {
167
94.8k
    printf("No %s data present\n", sect);
168
94.8k
    return;
169
94.8k
  }
170
92.4k
  if (res == DW_DLV_ERROR) {
171
86.2k
    printf("Error reading frame data \n");
172
86.2k
    return;
173
86.2k
  }
174
6.23k
  printf("%" DW_PR_DSd " cies present. "
175
6.23k
         "%" DW_PR_DSd " fdes present. \n",
176
6.23k
         cie_element_count, fde_element_count);
177
42.9k
  for (fdenum = 0; fdenum < fde_element_count; ++fdenum) {
178
36.7k
    Dwarf_Cie cie = 0;
179
180
36.7k
    Dwarf_Fde fde;
181
36.7k
    dwarf_get_fde_n(fde_data, fdenum, &fde, &error);
182
183
36.7k
    res = dwarf_get_cie_of_fde(fde, &cie, &error);
184
36.7k
    if (res != DW_DLV_OK) {
185
0
      printf("Error accessing cie of fdenum %" DW_PR_DSd " to get its cie\n",
186
0
             fdenum);
187
0
      return;
188
0
    }
189
36.7k
    printf("Print cie of fde %" DW_PR_DSd "\n", fdenum);
190
36.7k
    print_cie_instrs(cie, &error);
191
36.7k
    printf("Print fde %" DW_PR_DSd "\n", fdenum);
192
36.7k
    print_fde_selected_regs(fde_data[fdenum]);
193
36.7k
    print_fde_instrs(dbg, fde_data[fdenum], &error);
194
195
36.7k
    Dwarf_Signed dw_offset_into_exception_tables;
196
36.7k
    Dwarf_Signed dw_idx;
197
198
36.7k
    dwarf_get_fde_exception_info(fde_data[fdenum],
199
36.7k
                                 &dw_offset_into_exception_tables, &error);
200
36.7k
    dwarf_get_cie_index(cie, &dw_idx, &error);
201
202
36.7k
    Dwarf_Small *dw_augdata;
203
36.7k
    Dwarf_Unsigned dw_augdata_len;
204
36.7k
    dwarf_get_cie_augmentation_data(cie, &dw_augdata, &dw_augdata_len, &error);
205
206
36.7k
    Dwarf_Small *fde_augdata;
207
36.7k
    Dwarf_Unsigned fde_augdata_len;
208
36.7k
    dwarf_get_fde_augmentation_data(fde, &fde_augdata, &fde_augdata_len,
209
36.7k
                                    &error);
210
211
36.7k
    Dwarf_Off dw_fde_off;
212
36.7k
    Dwarf_Off dw_cie_off;
213
214
36.7k
    dwarf_fde_section_offset(dbg, fde, &dw_fde_off, &dw_cie_off, &error);
215
36.7k
    dwarf_cie_section_offset(dbg, cie, &dw_cie_off, &error);
216
36.7k
  }
217
218
6.23k
  dwarf_dealloc_fde_cie_list(dbg, cie_data, cie_element_count, fde_data,
219
6.23k
                             fde_element_count);
220
6.23k
  return;
221
6.23k
}
222
223
36.7k
static void print_cie_instrs(Dwarf_Cie cie, Dwarf_Error *error) {
224
36.7k
  int res = DW_DLV_ERROR;
225
36.7k
  Dwarf_Unsigned bytes_in_cie = 0;
226
36.7k
  Dwarf_Small version = 0;
227
36.7k
  char *augmentation = 0;
228
36.7k
  Dwarf_Unsigned code_alignment_factor = 0;
229
36.7k
  Dwarf_Signed data_alignment_factor = 0;
230
36.7k
  Dwarf_Half return_address_register_rule = 0;
231
36.7k
  Dwarf_Small *instrp = 0;
232
36.7k
  Dwarf_Unsigned instr_len = 0;
233
36.7k
  Dwarf_Half offset_size = 0;
234
235
36.7k
  res = dwarf_get_cie_info_b(cie, &bytes_in_cie, &version, &augmentation,
236
36.7k
                             &code_alignment_factor, &data_alignment_factor,
237
36.7k
                             &return_address_register_rule, &instrp, &instr_len,
238
36.7k
                             &offset_size, error);
239
36.7k
  if (res != DW_DLV_OK) {
240
0
    printf("Unable to get cie info!\n");
241
0
    return;
242
0
  }
243
36.7k
}
244
245
static void print_fde_col(Dwarf_Signed k, Dwarf_Addr jsave,
246
                          Dwarf_Small value_type, Dwarf_Signed offset_relevant,
247
                          Dwarf_Signed reg_used, Dwarf_Signed offset,
248
                          Dwarf_Block *block, Dwarf_Addr row_pc,
249
322k
                          Dwarf_Bool has_more_rows, Dwarf_Addr subsequent_pc) {
250
322k
  char *type_title = "";
251
322k
  Dwarf_Unsigned rule_id = k;
252
253
322k
  printf(" pc=0x%" DW_PR_DUx, jsave);
254
322k
  if (row_pc != jsave) {
255
1.24k
    printf(" row_pc=0x%" DW_PR_DUx, row_pc);
256
1.24k
  }
257
322k
  printf(" col=%" DW_PR_DSd " ", k);
258
322k
  switch (value_type) {
259
319k
  case DW_EXPR_OFFSET:
260
319k
    type_title = "off";
261
319k
    goto preg2;
262
372
  case DW_EXPR_VAL_OFFSET:
263
372
    type_title = "valoff";
264
265
319k
  preg2:
266
319k
    printf("<%s ", type_title);
267
319k
    if (reg_used == SAME_VAL) {
268
0
      printf(" SAME_VAL");
269
0
      break;
270
319k
    } else if (reg_used == INITIAL_VAL) {
271
0
      printf(" INITIAL_VAL");
272
0
      break;
273
0
    }
274
319k
    print_reg(rule_id);
275
276
319k
    printf("=");
277
319k
    if (offset_relevant == 0) {
278
260k
      print_reg(reg_used);
279
260k
      printf(" ");
280
260k
    } else {
281
59.5k
      printf("%02" DW_PR_DSd, offset);
282
59.5k
      printf("(");
283
59.5k
      print_reg(reg_used);
284
59.5k
      printf(") ");
285
59.5k
    }
286
319k
    break;
287
2.13k
  case DW_EXPR_EXPRESSION:
288
2.13k
    type_title = "expr";
289
2.13k
    goto pexp2;
290
531
  case DW_EXPR_VAL_EXPRESSION:
291
531
    type_title = "valexpr";
292
293
2.67k
  pexp2:
294
2.67k
    printf("<%s ", type_title);
295
2.67k
    print_reg(rule_id);
296
2.67k
    printf("=");
297
2.67k
    printf("expr-block-len=%" DW_PR_DUu, block->bl_len);
298
2.67k
    {
299
2.67k
      char pref[40];
300
301
2.67k
      strcpy(pref, "<");
302
2.67k
      strcat(pref, type_title);
303
2.67k
      strcat(pref, "bytes:");
304
2.67k
      dump_block(pref, block->bl_data, block->bl_len);
305
2.67k
      printf("%s", "> \n");
306
#if 0
307
            if (glflags.verbose) {
308
                struct esb_s exprstring;
309
                esb_constructor(&exprstring);
310
                get_string_from_locs(dbg,
311
                    block_ptr,offset,addr_size,
312
                    offset_size,version,&exprstring);
313
                printf("<expr:%s>",esb_get_string(&exprstring));
314
                esb_destructor(&exprstring);
315
            }
316
#endif
317
2.67k
    }
318
2.67k
    break;
319
0
  default:
320
0
    printf("Internal error in libdwarf, value type %d\n", value_type);
321
0
    return;
322
322k
  }
323
322k
  printf(" more=%d", has_more_rows);
324
322k
  printf(" next=0x%" DW_PR_DUx, subsequent_pc);
325
322k
  printf("%s", "> ");
326
322k
  printf("\n");
327
322k
}
328
329
static const Dwarf_Block dwblockzero;
330
36.7k
static void print_fde_selected_regs(Dwarf_Fde fde) {
331
36.7k
  Dwarf_Error oneferr = 0;
332
36.7k
  static int selected_cols[] = {1, 3, 5};
333
36.7k
  static int selected_cols_count =
334
36.7k
      sizeof(selected_cols) / sizeof(selected_cols[0]);
335
36.7k
  Dwarf_Signed k = 0;
336
36.7k
  int fres = 0;
337
338
36.7k
  Dwarf_Addr low_pc = 0;
339
36.7k
  Dwarf_Unsigned func_length = 0;
340
36.7k
  Dwarf_Small *fde_bytes = NULL;
341
36.7k
  Dwarf_Unsigned fde_bytes_length = 0;
342
36.7k
  Dwarf_Off cie_offset = 0;
343
36.7k
  Dwarf_Signed cie_index = 0;
344
36.7k
  Dwarf_Off fde_offset = 0;
345
36.7k
  Dwarf_Fde curfde = fde;
346
36.7k
  Dwarf_Cie cie = 0;
347
36.7k
  Dwarf_Addr jsave = 0;
348
36.7k
  Dwarf_Addr high_addr = 0;
349
36.7k
  Dwarf_Addr next_jsave = 0;
350
36.7k
  Dwarf_Bool has_more_rows = 0;
351
36.7k
  Dwarf_Addr subsequent_pc = 0;
352
36.7k
  Dwarf_Error error = 0;
353
36.7k
  int res = 0;
354
355
36.7k
  fres = dwarf_get_fde_range(curfde, &low_pc, &func_length, &fde_bytes,
356
36.7k
                             &fde_bytes_length, &cie_offset, &cie_index,
357
36.7k
                             &fde_offset, &oneferr);
358
359
36.7k
  if (fres == DW_DLV_ERROR) {
360
0
    printf("FAIL: dwarf_get_fde_range err %" DW_PR_DUu " line %d\n",
361
0
           dwarf_errno(oneferr), __LINE__);
362
0
    return;
363
0
  }
364
36.7k
  if (fres == DW_DLV_NO_ENTRY) {
365
0
    printf("No fde range data available\n");
366
0
    return;
367
0
  }
368
36.7k
  res = dwarf_get_cie_of_fde(fde, &cie, &error);
369
36.7k
  if (res != DW_DLV_OK) {
370
0
    printf("Error getting cie from fde\n");
371
0
    return;
372
0
  }
373
374
36.7k
  high_addr = low_pc + func_length;
375
144k
  for (jsave = low_pc; next_jsave < high_addr; jsave = next_jsave) {
376
129k
    next_jsave = jsave + 1;
377
129k
    printf("\n");
378
451k
    for (k = 0; k < selected_cols_count; ++k) {
379
344k
      Dwarf_Unsigned reg = 0;
380
344k
      Dwarf_Unsigned offset_relevant = 0;
381
344k
      int fires = 0;
382
344k
      Dwarf_Small value_type = 0;
383
344k
      Dwarf_Block block;
384
344k
      Dwarf_Unsigned offset;
385
344k
      Dwarf_Addr row_pc = 0;
386
387
344k
      block = dwblockzero;
388
344k
      fires = dwarf_get_fde_info_for_reg3_b(
389
344k
          curfde, selected_cols[k], jsave, &value_type, &offset_relevant, &reg,
390
344k
          &offset, &block, &row_pc, &has_more_rows, &subsequent_pc, &oneferr);
391
344k
      if (fires == DW_DLV_ERROR) {
392
22.1k
        printf("FAIL: dwarf_get_fde_info_for_reg3_b, "
393
22.1k
            "reading reg err %s line %d\n",
394
22.1k
            dwarf_errmsg(oneferr), __LINE__);
395
22.1k
        return;
396
22.1k
      }
397
322k
      if (fires == DW_DLV_NO_ENTRY) {
398
0
        continue;
399
0
      }
400
322k
      print_fde_col(selected_cols[k], jsave, value_type, offset_relevant, reg,
401
322k
                    offset, &block, row_pc, has_more_rows, subsequent_pc);
402
322k
      if (has_more_rows) {
403
288k
        next_jsave = subsequent_pc;
404
288k
      } else {
405
33.7k
        next_jsave = high_addr;
406
33.7k
      }
407
322k
    }
408
129k
  }
409
36.7k
}
410
411
static int print_frame_instrs(Dwarf_Debug dbg,
412
                              Dwarf_Frame_Instr_Head frame_instr_head,
413
                              Dwarf_Unsigned frame_instr_count,
414
11.5k
                              Dwarf_Error *error) {
415
11.5k
  Dwarf_Unsigned i = 0;
416
417
11.5k
  printf("\nPrint %" DW_PR_DUu " frame instructions\n", frame_instr_count);
418
229k
  for (; i < frame_instr_count; ++i) {
419
217k
    int res = 0;
420
217k
    Dwarf_Unsigned instr_offset_in_instrs = 0;
421
217k
    Dwarf_Small cfa_operation = 0;
422
217k
    const char *fields = 0;
423
217k
    Dwarf_Unsigned u0 = 0;
424
217k
    Dwarf_Unsigned u1 = 0;
425
217k
    Dwarf_Unsigned u2 = 0;
426
217k
    Dwarf_Signed s0 = 0;
427
217k
    Dwarf_Signed s1 = 0;
428
217k
    Dwarf_Block expression_block;
429
217k
    Dwarf_Unsigned code_alignment_factor = 0;
430
217k
    Dwarf_Signed data_alignment_factor = 0;
431
217k
    const char *op_name = 0;
432
433
217k
    expression_block = dwblockzero;
434
217k
    res = dwarf_get_frame_instruction_a(
435
217k
        frame_instr_head, i, &instr_offset_in_instrs, &cfa_operation, &fields,
436
217k
        &u0, &u1, &u2, &s0, &s1, &code_alignment_factor, &data_alignment_factor,
437
217k
        &expression_block, error);
438
217k
    res = dwarf_get_frame_instruction(
439
217k
        frame_instr_head, i, &instr_offset_in_instrs, &cfa_operation, &fields,
440
217k
        &u0, &u1, &s0, &s1, &code_alignment_factor, &data_alignment_factor,
441
217k
        &expression_block, error);
442
443
217k
    if (res != DW_DLV_OK) {
444
0
      if (res == DW_DLV_ERROR) {
445
0
        printf("ERROR reading frame instruction "
446
0
               "%" DW_PR_DUu "\n",
447
0
               frame_instr_count);
448
0
        if(error) {
449
0
          dwarf_dealloc_error(dbg, *error);
450
0
          *error = 0;
451
0
        }
452
0
      } else {
453
0
        printf("NO ENTRY reading frame instruction "
454
0
               " %" DW_PR_DUu "\n",
455
0
               frame_instr_count);
456
0
      }
457
0
      break;
458
0
    }
459
217k
    dwarf_get_CFA_name(cfa_operation, &op_name);
460
217k
    printf("[%2" DW_PR_DUu "]  %" DW_PR_DUu " %s ", i, instr_offset_in_instrs,
461
217k
           op_name);
462
217k
    switch (fields[0]) {
463
89.1k
    case 'u': {
464
89.1k
      if (!fields[1]) {
465
22.4k
        printf("%" DW_PR_DUu "\n", u0);
466
22.4k
      }
467
89.1k
      if (fields[1] == 'c') {
468
66.6k
        Dwarf_Unsigned final = u0 * code_alignment_factor;
469
66.6k
        printf("%" DW_PR_DUu, final);
470
#if 0
471
                if (glflags.verbose) {
472
                    printf("  (%" DW_PR_DUu " * %" DW_PR_DUu,
473
                        u0,code_alignment_factor);
474
475
                }
476
#endif
477
66.6k
        printf("\n");
478
66.6k
      }
479
89.1k
    } break;
480
76.7k
    case 'r': {
481
76.7k
      if (!fields[1]) {
482
39.4k
        printf("r%" DW_PR_DUu "\n", u0);
483
39.4k
        break;
484
39.4k
      }
485
37.3k
      if (fields[1] == 'u') {
486
34.9k
        if (!fields[2]) {
487
5.86k
          printf("%" DW_PR_DUu, u1);
488
5.86k
          printf("\n");
489
5.86k
          break;
490
5.86k
        }
491
29.0k
        if (fields[2] == 'd') {
492
28.8k
          Dwarf_Signed final = (Dwarf_Signed)u0 * data_alignment_factor;
493
28.8k
          printf("%" DW_PR_DUu, final);
494
28.8k
          printf("\n");
495
28.8k
        }
496
29.0k
      }
497
31.4k
      if (fields[1] == 'r') {
498
746
        printf("r%" DW_PR_DUu "\n", u0);
499
746
        printf(" ");
500
746
        printf("r%" DW_PR_DUu "\n", u1);
501
746
        printf("\n");
502
746
      }
503
31.4k
      if (fields[1] == 's') {
504
1.24k
        if (fields[2] == 'd') {
505
1.24k
          Dwarf_Signed final = 0;
506
1.24k
          printf("r%" DW_PR_DUu "\n", u0);
507
1.24k
          final = s1 * data_alignment_factor;
508
1.24k
          printf("%" DW_PR_DSd, final);
509
          /*  The original did not do this check for 'a'
510
              but it's harmless to the testing, so added. 2023-06-10 */
511
1.24k
          if (fields[3] == 'a') {
512
217
            printf(" addrspace %" DW_PR_DUu ,u2);
513
217
          }
514
#if 0
515
                    if (glflags.verbose) {
516
                        printf("  (%" DW_PR_DSd " * %" DW_PR_DSd,
517
                            s1,data_alignment_factor);
518
                    }
519
#endif
520
1.24k
          printf("\n");
521
1.24k
        }
522
1.24k
      }
523
31.4k
      if (fields[1] == 'b') {
524
        /* rb */
525
410
        printf("r%" DW_PR_DUu "\n", u0);
526
410
        printf("%" DW_PR_DUu, u0);
527
410
        printf(" expr block len %" DW_PR_DUu "\n", expression_block.bl_len);
528
410
        dump_block("    ", expression_block.bl_data,
529
410
                   (Dwarf_Signed)expression_block.bl_len);
530
410
        printf("\n");
531
#if 0
532
                if (glflags.verbose) {
533
                    print_expression(dbg,die,&expression_block,
534
                        addr_size,offset_size,
535
                        version);
536
                }
537
#endif
538
410
      }
539
31.4k
    } break;
540
373
    case 's': {
541
373
      if (fields[1] == 'd') {
542
373
        Dwarf_Signed final = s0 * data_alignment_factor;
543
544
373
        printf(" %" DW_PR_DSd, final);
545
#if 0
546
                if (glflags.verbose) {
547
                    printf("  (%" DW_PR_DSd " * %" DW_PR_DSd,
548
                        s0,data_alignment_factor);
549
                }
550
#endif
551
373
        printf("\n");
552
373
      }
553
373
    } break;
554
170
    case 'b': {
555
170
      if (!fields[1]) {
556
170
        printf(" expr block len %" DW_PR_DUu "\n", expression_block.bl_len);
557
170
        dump_block("    ", expression_block.bl_data,
558
170
                   (Dwarf_Signed)expression_block.bl_len);
559
170
        printf("\n");
560
#if 0
561
                if (glflags.verbose) {
562
                    print_expression(dbg,die,&expression_block,
563
                        addr_size,offset_size,
564
                        version);
565
                }
566
#endif
567
170
      }
568
170
    } break;
569
51.4k
    case 0:
570
51.4k
      printf("\n");
571
51.4k
      break;
572
0
    default:
573
0
      printf("UNKNOWN FIELD 0x%x\n", fields[0]);
574
217k
    }
575
217k
  }
576
11.5k
  return DW_DLV_OK;
577
11.5k
}
578
579
static void print_fde_instrs(Dwarf_Debug dbg, Dwarf_Fde fde,
580
36.7k
                             Dwarf_Error *error) {
581
36.7k
  int res;
582
36.7k
  Dwarf_Addr lowpc = 0;
583
36.7k
  Dwarf_Unsigned func_length = 0;
584
36.7k
  Dwarf_Small *fde_bytes;
585
36.7k
  Dwarf_Unsigned fde_byte_length = 0;
586
36.7k
  Dwarf_Off cie_offset = 0;
587
36.7k
  Dwarf_Signed cie_index = 0;
588
36.7k
  Dwarf_Off fde_offset = 0;
589
36.7k
  Dwarf_Addr arbitrary_addr = 0;
590
36.7k
  Dwarf_Addr actual_pc = 0;
591
36.7k
  Dwarf_Regtable3 tab3;
592
36.7k
  int oldrulecount = 0;
593
36.7k
  Dwarf_Small *outinstrs = 0;
594
36.7k
  Dwarf_Unsigned instrslen = 0;
595
36.7k
  Dwarf_Cie cie = 0;
596
597
36.7k
  res = dwarf_get_fde_range(fde, &lowpc, &func_length, &fde_bytes,
598
36.7k
                            &fde_byte_length, &cie_offset, &cie_index,
599
36.7k
                            &fde_offset, error);
600
36.7k
  if (res != DW_DLV_OK) {
601
    /*  So nothing clears the error record here,
602
        the caller does not know the call failed.
603
        Terrible code, but interesting testcase. */
604
0
    printf("Problem getting fde range \n");
605
0
    return;
606
0
  }
607
608
36.7k
  arbitrary_addr = lowpc + (func_length / 2);
609
36.7k
  printf("function low pc 0x%" DW_PR_DUx "  and length 0x%" DW_PR_DUx
610
36.7k
         "  and midpoint addr we choose 0x%" DW_PR_DUx "\n",
611
36.7k
         lowpc, func_length, arbitrary_addr);
612
613
36.7k
  oldrulecount = dwarf_set_frame_rule_table_size(dbg, 1);
614
36.7k
  dwarf_set_frame_rule_table_size(dbg, oldrulecount);
615
616
36.7k
  tab3.rt3_reg_table_size = oldrulecount;
617
36.7k
  tab3.rt3_rules = (struct Dwarf_Regtable_Entry3_s *)malloc(
618
36.7k
      sizeof(struct Dwarf_Regtable_Entry3_s) * oldrulecount);
619
36.7k
  if (!tab3.rt3_rules) {
620
0
    printf("Unable to malloc for %d rules\n", oldrulecount);
621
0
    return;
622
0
  }
623
624
36.7k
  res = dwarf_get_fde_info_for_all_regs3(fde, arbitrary_addr, &tab3, &actual_pc,
625
36.7k
                                         error);
626
36.7k
  printf("function actual addr of row 0x%" DW_PR_DUx "\n", actual_pc);
627
628
36.7k
  if (res != DW_DLV_OK) {
629
21.1k
    printf("dwarf_get_fde_info_for_all_regs3 failed!\n");
630
21.1k
    free(tab3.rt3_rules);
631
21.1k
    return;
632
21.1k
  }
633
15.6k
  print_regtable(&tab3);
634
635
15.6k
  res = dwarf_get_fde_instr_bytes(fde, &outinstrs, &instrslen, error);
636
15.6k
  if (res != DW_DLV_OK) {
637
0
    free(tab3.rt3_rules);
638
0
    printf("dwarf_get_fde_instr_bytes failed!\n");
639
0
    return;
640
0
  }
641
15.6k
  res = dwarf_get_cie_of_fde(fde, &cie, error);
642
15.6k
  if (res != DW_DLV_OK) {
643
0
    free(tab3.rt3_rules);
644
0
    printf("Error getting cie from fde\n");
645
0
    return;
646
0
  }
647
648
15.6k
  {
649
15.6k
    Dwarf_Frame_Instr_Head frame_instr_head = 0;
650
15.6k
    Dwarf_Unsigned frame_instr_count = 0;
651
15.6k
    res = dwarf_expand_frame_instructions(cie, outinstrs, instrslen,
652
15.6k
                                          &frame_instr_head, &frame_instr_count,
653
15.6k
                                          error);
654
15.6k
    if (res != DW_DLV_OK) {
655
4.07k
      free(tab3.rt3_rules);
656
4.07k
      printf("dwarf_expand_frame_instructions failed!\n");
657
4.07k
      return;
658
4.07k
    }
659
11.5k
    printf("Frame op count: %" DW_PR_DUu "\n", frame_instr_count);
660
11.5k
    print_frame_instrs(dbg, frame_instr_head, frame_instr_count, error);
661
662
11.5k
    dwarf_dealloc_frame_instr_head(frame_instr_head);
663
11.5k
  }
664
0
  free(tab3.rt3_rules);
665
11.5k
}
666
667
813k
static void print_reg(int r) {
668
813k
  switch (r) {
669
0
  case SAME_VAL:
670
0
    printf(" %d SAME_VAL ", r);
671
0
    break;
672
0
  case UNDEF_VAL:
673
0
    printf(" %d UNDEF_VAL ", r);
674
0
    break;
675
0
  case CFA_VAL:
676
0
    printf(" %d (CFA) ", r);
677
0
    break;
678
813k
  default:
679
813k
    printf(" r%d ", r);
680
813k
    break;
681
813k
  }
682
813k
}
683
684
static void print_one_regentry(const char *prefix,
685
171k
                               struct Dwarf_Regtable_Entry3_s *entry) {
686
171k
  int is_cfa = !strcmp("cfa", prefix);
687
171k
  printf("%s ", prefix);
688
171k
  printf("type: %d %s ", entry->dw_value_type,
689
171k
         (entry->dw_value_type == DW_EXPR_OFFSET)       ? "DW_EXPR_OFFSET"
690
171k
         : (entry->dw_value_type == DW_EXPR_VAL_OFFSET) ? "DW_EXPR_VAL_OFFSET"
691
905
         : (entry->dw_value_type == DW_EXPR_EXPRESSION) ? "DW_EXPR_EXPRESSION"
692
661
         : (entry->dw_value_type == DW_EXPR_VAL_EXPRESSION)
693
114
             ? "DW_EXPR_VAL_EXPRESSION"
694
114
             : "Unknown");
695
171k
  switch (entry->dw_value_type) {
696
170k
  case DW_EXPR_OFFSET:
697
170k
    print_reg(entry->dw_regnum);
698
170k
    printf(" offset_rel? %d ", entry->dw_offset_relevant);
699
170k
    if (entry->dw_offset_relevant) {
700
42.5k
      printf(" offset  %" DW_PR_DSd " ", entry->dw_offset);
701
42.5k
      if (is_cfa) {
702
10.9k
        printf("defines cfa value");
703
31.6k
      } else {
704
31.6k
        printf("address of value is CFA plus signed offset");
705
31.6k
      }
706
42.5k
      if (!is_cfa && entry->dw_regnum != CFA_VAL) {
707
31.6k
        printf(" compiler botch, regnum != CFA_VAL");
708
31.6k
      }
709
128k
    } else {
710
128k
      printf("value in register");
711
128k
    }
712
170k
    break;
713
244
  case DW_EXPR_VAL_OFFSET:
714
244
    print_reg(entry->dw_regnum);
715
244
    printf(" offset  %" DW_PR_DSd " ", entry->dw_offset);
716
244
    if (is_cfa) {
717
0
      printf("does this make sense? No?");
718
244
    } else {
719
244
      printf("value at CFA plus signed offset");
720
244
    }
721
244
    if (!is_cfa && entry->dw_regnum != CFA_VAL) {
722
244
      printf(" compiler botch, regnum != CFA_VAL");
723
244
    }
724
244
    break;
725
547
  case DW_EXPR_EXPRESSION:
726
547
    print_reg(entry->dw_regnum);
727
547
    printf(" offset_rel? %d ", entry->dw_offset_relevant);
728
547
    printf(" offset  %" DW_PR_DUu " ", entry->dw_offset);
729
547
    printf("Block ptr set? %s ", entry->dw_block.bl_data ? "yes" : "no");
730
547
    printf(" Value is at address given by expr val ");
731
547
    break;
732
114
  case DW_EXPR_VAL_EXPRESSION:
733
114
    printf(" expression byte len  %" DW_PR_DUu " ", entry->dw_block.bl_len);
734
114
    printf("Block ptr set? %s ", entry->dw_block.bl_data ? "yes" : "no");
735
114
    printf(" Value is expr val ");
736
114
    if (!entry->dw_block.bl_data) {
737
0
      printf("Compiler or libdwarf botch, "
738
0
             "NULL block data pointer. ");
739
0
    }
740
114
    break;
741
0
  default:
742
0
    break;
743
171k
  }
744
171k
  printf("\n");
745
171k
}
746
747
15.6k
static void print_regtable(Dwarf_Regtable3 *tab3) {
748
15.6k
  int r;
749
15.6k
  int max = 10;
750
15.6k
  if (max > tab3->rt3_reg_table_size) {
751
0
    max = tab3->rt3_reg_table_size;
752
0
  }
753
15.6k
  print_one_regentry("cfa", &tab3->rt3_cfa_rule);
754
755
171k
  for (r = 0; r < max; r++) {
756
156k
    char rn[30];
757
156k
    snprintf(rn, sizeof(rn), "reg %d", r);
758
156k
    print_one_regentry(rn, tab3->rt3_rules + r);
759
156k
  }
760
15.6k
}