Coverage Report

Created: 2026-08-30 07:07

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
14.1k
#define O_BINARY 0 /* So it does nothing in Linux/Unix */
25
#endif
26
595k
#define DW_PR_DUx "llx"
27
#define DW_PR_DSx "llx"
28
102k
#define DW_PR_DUu "llu"
29
58.9k
#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
295k
#define UNDEF_VAL 2000
41
295k
#define SAME_VAL 2001
42
31.5k
#define CFA_VAL 2002
43
295k
#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
14.1k
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
60
14.1k
  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
14.1k
  sprintf(filename, "/tmp/libfuzzer.%d", getpid());
68
14.1k
#endif
69
14.1k
  FILE *fp = fopen(filename, "wb");
70
14.1k
  if (!fp) {
71
0
    printf("FAIL libfuzzer cannot open temp as writeable %s\n",
72
0
        filename);
73
0
    return 0;
74
0
  }
75
14.1k
  fwrite(data, size, 1, fp);
76
14.1k
  fclose(fp);
77
78
14.1k
  Dwarf_Debug dbg = 0;
79
14.1k
  int res = DW_DLV_ERROR;
80
14.1k
  Dwarf_Error error = 0;
81
14.1k
  Dwarf_Handler errhand = 0;
82
14.1k
  Dwarf_Ptr errarg = 0;
83
14.1k
  int regtabrulecount = 0;
84
14.1k
  int curopt = 0;
85
86
14.1k
  int fd = open(filename, O_RDONLY | O_BINARY);
87
14.1k
  if (fd < 0) {
88
0
    printf("Unable to open %s, giving up.\n", filename);
89
0
    exit(EXIT_FAILURE);
90
0
  }
91
92
14.1k
  res = dwarf_init_b(fd, DW_GROUPNUMBER_ANY, errhand, errarg, &dbg, &error);
93
94
14.1k
  if (res != DW_DLV_OK) {
95
6.98k
    printf("Giving up, dwarf_init failed, "
96
6.98k
           "cannot do DWARF processing\n");
97
6.98k
    if (res == DW_DLV_ERROR) {
98
5.12k
      printf("Error code %s\n", dwarf_errmsg(error));
99
5.12k
    }
100
6.98k
    dwarf_dealloc_error(dbg, error);
101
7.17k
  } else {
102
7.17k
    Dwarf_Half frame_values[] = {SHRT_MIN, SHRT_MAX, 0};
103
28.6k
    for (int i = 0; i < 3; i++) {
104
21.5k
      dwarf_set_frame_undefined_value(dbg, frame_values[i]);
105
21.5k
      read_frame_data(dbg, ".debug_frame");
106
21.5k
      read_frame_data(dbg, ".eh_frame");
107
21.5k
    }
108
28.6k
    for (int i = 0; i < 3; i++) {
109
21.5k
      dwarf_set_frame_rule_initial_value(dbg, frame_values[i]);
110
21.5k
      read_frame_data(dbg, ".debug_frame");
111
21.5k
      read_frame_data(dbg, ".eh_frame");
112
21.5k
    }
113
28.6k
    for (int i = 0; i < 3; i++) {
114
21.5k
      dwarf_set_frame_same_value(dbg, frame_values[i]);
115
21.5k
      read_frame_data(dbg, ".debug_frame");
116
21.5k
      read_frame_data(dbg, ".eh_frame");
117
21.5k
    }
118
28.6k
    for (int i = 0; i < 3; i++) {
119
21.5k
      dwarf_set_frame_cfa_value(dbg, frame_values[i]);
120
21.5k
      read_frame_data(dbg, ".debug_frame");
121
21.5k
      read_frame_data(dbg, ".eh_frame");
122
21.5k
    }
123
28.6k
    for (int i = 0; i < 3; i++) {
124
21.5k
      dwarf_set_frame_rule_table_size(dbg, frame_values[i]);
125
21.5k
      read_frame_data(dbg, ".debug_frame");
126
21.5k
      read_frame_data(dbg, ".eh_frame");
127
21.5k
    }
128
7.17k
  }
129
130
14.1k
  res = dwarf_finish(dbg);
131
14.1k
  close(fd);
132
14.1k
  unlink(filename);
133
14.1k
  return 0;
134
14.1k
}
135
136
2.29k
static void dump_block(char *prefix, Dwarf_Small *data, Dwarf_Unsigned len) {
137
2.29k
  Dwarf_Small *end_data = data + len;
138
2.29k
  Dwarf_Small *cur = data;
139
2.29k
  int i = 0;
140
141
2.29k
  printf("%s", prefix);
142
31.9k
  for (; cur < end_data; ++cur, ++i) {
143
29.6k
    if (i > 0 && i % 4 == 0)
144
6.54k
      printf(" ");
145
29.6k
    printf("%02x", 0xff & *cur);
146
29.6k
  }
147
2.29k
}
148
149
215k
static void read_frame_data(Dwarf_Debug dbg, const char *sect) {
150
215k
  Dwarf_Error error;
151
215k
  Dwarf_Signed cie_element_count = 0;
152
215k
  Dwarf_Signed fde_element_count = 0;
153
215k
  Dwarf_Cie *cie_data = 0;
154
215k
  Dwarf_Fde *fde_data = 0;
155
215k
  int res = DW_DLV_ERROR;
156
215k
  Dwarf_Signed fdenum = 0;
157
158
215k
  printf(" Print %s\n", sect);
159
215k
  if (!strcmp(sect, ".eh_frame")) {
160
107k
    res = dwarf_get_fde_list_eh(dbg, &cie_data, &cie_element_count, &fde_data,
161
107k
                                &fde_element_count, &error);
162
107k
  } else {
163
107k
    res = dwarf_get_fde_list(dbg, &cie_data, &cie_element_count, &fde_data,
164
107k
                             &fde_element_count, &error);
165
107k
  }
166
215k
  if (res == DW_DLV_NO_ENTRY) {
167
108k
    printf("No %s data present\n", sect);
168
108k
    return;
169
108k
  }
170
106k
  if (res == DW_DLV_ERROR) {
171
98.9k
    printf("Error reading frame data \n");
172
98.9k
    return;
173
98.9k
  }
174
7.67k
  printf("%" DW_PR_DSd " cies present. "
175
7.67k
         "%" DW_PR_DSd " fdes present. \n",
176
7.67k
         cie_element_count, fde_element_count);
177
44.6k
  for (fdenum = 0; fdenum < fde_element_count; ++fdenum) {
178
36.9k
    Dwarf_Cie cie = 0;
179
180
36.9k
    Dwarf_Fde fde;
181
36.9k
    dwarf_get_fde_n(fde_data, fdenum, &fde, &error);
182
183
36.9k
    res = dwarf_get_cie_of_fde(fde, &cie, &error);
184
36.9k
    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.9k
    printf("Print cie of fde %" DW_PR_DSd "\n", fdenum);
190
36.9k
    print_cie_instrs(cie, &error);
191
36.9k
    printf("Print fde %" DW_PR_DSd "\n", fdenum);
192
36.9k
    print_fde_selected_regs(fde_data[fdenum]);
193
36.9k
    print_fde_instrs(dbg, fde_data[fdenum], &error);
194
195
36.9k
    Dwarf_Signed dw_offset_into_exception_tables;
196
36.9k
    Dwarf_Signed dw_idx;
197
198
36.9k
    dwarf_get_fde_exception_info(fde_data[fdenum],
199
36.9k
                                 &dw_offset_into_exception_tables, &error);
200
36.9k
    dwarf_get_cie_index(cie, &dw_idx, &error);
201
202
36.9k
    Dwarf_Small *dw_augdata;
203
36.9k
    Dwarf_Unsigned dw_augdata_len;
204
36.9k
    dwarf_get_cie_augmentation_data(cie, &dw_augdata, &dw_augdata_len, &error);
205
206
36.9k
    Dwarf_Small *fde_augdata;
207
36.9k
    Dwarf_Unsigned fde_augdata_len;
208
36.9k
    dwarf_get_fde_augmentation_data(fde, &fde_augdata, &fde_augdata_len,
209
36.9k
                                    &error);
210
211
36.9k
    Dwarf_Off dw_fde_off;
212
36.9k
    Dwarf_Off dw_cie_off;
213
214
36.9k
    dwarf_fde_section_offset(dbg, fde, &dw_fde_off, &dw_cie_off, &error);
215
36.9k
    dwarf_cie_section_offset(dbg, cie, &dw_cie_off, &error);
216
36.9k
  }
217
218
7.67k
  dwarf_dealloc_fde_cie_list(dbg, cie_data, cie_element_count, fde_data,
219
7.67k
                             fde_element_count);
220
7.67k
  return;
221
7.67k
}
222
223
36.9k
static void print_cie_instrs(Dwarf_Cie cie, Dwarf_Error *error) {
224
36.9k
  int res = DW_DLV_ERROR;
225
36.9k
  Dwarf_Unsigned bytes_in_cie = 0;
226
36.9k
  Dwarf_Small version = 0;
227
36.9k
  char *augmentation = 0;
228
36.9k
  Dwarf_Unsigned code_alignment_factor = 0;
229
36.9k
  Dwarf_Signed data_alignment_factor = 0;
230
36.9k
  Dwarf_Half return_address_register_rule = 0;
231
36.9k
  Dwarf_Small *instrp = 0;
232
36.9k
  Dwarf_Unsigned instr_len = 0;
233
36.9k
  Dwarf_Half offset_size = 0;
234
235
36.9k
  res = dwarf_get_cie_info_b(cie, &bytes_in_cie, &version, &augmentation,
236
36.9k
                             &code_alignment_factor, &data_alignment_factor,
237
36.9k
                             &return_address_register_rule, &instrp, &instr_len,
238
36.9k
                             &offset_size, error);
239
36.9k
  if (res != DW_DLV_OK) {
240
0
    printf("Unable to get cie info!\n");
241
0
    return;
242
0
  }
243
36.9k
}
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
297k
                          Dwarf_Bool has_more_rows, Dwarf_Addr subsequent_pc) {
250
297k
  char *type_title = "";
251
297k
  Dwarf_Unsigned rule_id = k;
252
253
297k
  printf(" pc=0x%" DW_PR_DUx, jsave);
254
297k
  if (row_pc != jsave) {
255
1.23k
    printf(" row_pc=0x%" DW_PR_DUx, row_pc);
256
1.23k
  }
257
297k
  printf(" col=%" DW_PR_DSd " ", k);
258
297k
  switch (value_type) {
259
295k
  case DW_EXPR_OFFSET:
260
295k
    type_title = "off";
261
295k
    goto preg2;
262
300
  case DW_EXPR_VAL_OFFSET:
263
300
    type_title = "valoff";
264
265
295k
  preg2:
266
295k
    printf("<%s ", type_title);
267
295k
    if (reg_used == SAME_VAL) {
268
0
      printf(" SAME_VAL");
269
0
      break;
270
295k
    } else if (reg_used == INITIAL_VAL) {
271
0
      printf(" INITIAL_VAL");
272
0
      break;
273
0
    }
274
295k
    print_reg(rule_id);
275
276
295k
    printf("=");
277
295k
    if (offset_relevant == 0) {
278
238k
      print_reg(reg_used);
279
238k
      printf(" ");
280
238k
    } else {
281
57.1k
      printf("%02" DW_PR_DSd, offset);
282
57.1k
      printf("(");
283
57.1k
      print_reg(reg_used);
284
57.1k
      printf(") ");
285
57.1k
    }
286
295k
    break;
287
937
  case DW_EXPR_EXPRESSION:
288
937
    type_title = "expr";
289
937
    goto pexp2;
290
446
  case DW_EXPR_VAL_EXPRESSION:
291
446
    type_title = "valexpr";
292
293
1.38k
  pexp2:
294
1.38k
    printf("<%s ", type_title);
295
1.38k
    print_reg(rule_id);
296
1.38k
    printf("=");
297
1.38k
    printf("expr-block-len=%" DW_PR_DUu, block->bl_len);
298
1.38k
    {
299
1.38k
      char pref[40];
300
301
1.38k
      strcpy(pref, "<");
302
1.38k
      strcat(pref, type_title);
303
1.38k
      strcat(pref, "bytes:");
304
1.38k
      dump_block(pref, block->bl_data, block->bl_len);
305
1.38k
      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
1.38k
    }
318
1.38k
    break;
319
0
  default:
320
0
    printf("Internal error in libdwarf, value type %d\n", value_type);
321
0
    return;
322
297k
  }
323
297k
  printf(" more=%d", has_more_rows);
324
297k
  printf(" next=0x%" DW_PR_DUx, subsequent_pc);
325
297k
  printf("%s", "> ");
326
297k
  printf("\n");
327
297k
}
328
329
static const Dwarf_Block dwblockzero;
330
36.9k
static void print_fde_selected_regs(Dwarf_Fde fde) {
331
36.9k
  Dwarf_Error oneferr = 0;
332
36.9k
  static int selected_cols[] = {1, 3, 5};
333
36.9k
  static int selected_cols_count =
334
36.9k
      sizeof(selected_cols) / sizeof(selected_cols[0]);
335
36.9k
  Dwarf_Signed k = 0;
336
36.9k
  int fres = 0;
337
338
36.9k
  Dwarf_Addr low_pc = 0;
339
36.9k
  Dwarf_Unsigned func_length = 0;
340
36.9k
  Dwarf_Small *fde_bytes = NULL;
341
36.9k
  Dwarf_Unsigned fde_bytes_length = 0;
342
36.9k
  Dwarf_Off cie_offset = 0;
343
36.9k
  Dwarf_Signed cie_index = 0;
344
36.9k
  Dwarf_Off fde_offset = 0;
345
36.9k
  Dwarf_Fde curfde = fde;
346
36.9k
  Dwarf_Cie cie = 0;
347
36.9k
  Dwarf_Addr jsave = 0;
348
36.9k
  Dwarf_Addr high_addr = 0;
349
36.9k
  Dwarf_Addr next_jsave = 0;
350
36.9k
  Dwarf_Bool has_more_rows = 0;
351
36.9k
  Dwarf_Addr subsequent_pc = 0;
352
36.9k
  Dwarf_Error error = 0;
353
36.9k
  int res = 0;
354
355
36.9k
  fres = dwarf_get_fde_range(curfde, &low_pc, &func_length, &fde_bytes,
356
36.9k
                             &fde_bytes_length, &cie_offset, &cie_index,
357
36.9k
                             &fde_offset, &oneferr);
358
359
36.9k
  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.9k
  if (fres == DW_DLV_NO_ENTRY) {
365
0
    printf("No fde range data available\n");
366
0
    return;
367
0
  }
368
36.9k
  res = dwarf_get_cie_of_fde(fde, &cie, &error);
369
36.9k
  if (res != DW_DLV_OK) {
370
0
    printf("Error getting cie from fde\n");
371
0
    return;
372
0
  }
373
374
36.9k
  high_addr = low_pc + func_length;
375
136k
  for (jsave = low_pc; next_jsave < high_addr; jsave = next_jsave) {
376
120k
    next_jsave = jsave + 1;
377
120k
    printf("\n");
378
417k
    for (k = 0; k < selected_cols_count; ++k) {
379
318k
      Dwarf_Unsigned reg = 0;
380
318k
      Dwarf_Unsigned offset_relevant = 0;
381
318k
      int fires = 0;
382
318k
      Dwarf_Small value_type = 0;
383
318k
      Dwarf_Block block;
384
318k
      Dwarf_Unsigned offset;
385
318k
      Dwarf_Addr row_pc = 0;
386
387
318k
      block = dwblockzero;
388
318k
      fires = dwarf_get_fde_info_for_reg3_b(
389
318k
          curfde, selected_cols[k], jsave, &value_type, &offset_relevant, &reg,
390
318k
          &offset, &block, &row_pc, &has_more_rows, &subsequent_pc, &oneferr);
391
318k
      if (fires == DW_DLV_ERROR) {
392
21.3k
        printf("FAIL: dwarf_get_fde_info_for_reg3_b, "
393
21.3k
            "reading reg err %s line %d\n",
394
21.3k
            dwarf_errmsg(oneferr), __LINE__);
395
21.3k
        return;
396
21.3k
      }
397
297k
      if (fires == DW_DLV_NO_ENTRY) {
398
0
        continue;
399
0
      }
400
297k
      print_fde_col(selected_cols[k], jsave, value_type, offset_relevant, reg,
401
297k
                    offset, &block, row_pc, has_more_rows, subsequent_pc);
402
297k
      if (has_more_rows) {
403
260k
        next_jsave = subsequent_pc;
404
260k
      } else {
405
36.3k
        next_jsave = high_addr;
406
36.3k
      }
407
297k
    }
408
120k
  }
409
36.9k
}
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
12.4k
                              Dwarf_Error *error) {
415
12.4k
  Dwarf_Unsigned i = 0;
416
417
12.4k
  printf("\nPrint %" DW_PR_DUu " frame instructions\n", frame_instr_count);
418
230k
  for (; i < frame_instr_count; ++i) {
419
218k
    int res = 0;
420
218k
    Dwarf_Unsigned instr_offset_in_instrs = 0;
421
218k
    Dwarf_Small cfa_operation = 0;
422
218k
    const char *fields = 0;
423
218k
    Dwarf_Unsigned u0 = 0;
424
218k
    Dwarf_Unsigned u1 = 0;
425
218k
    Dwarf_Unsigned u2 = 0;
426
218k
    Dwarf_Signed s0 = 0;
427
218k
    Dwarf_Signed s1 = 0;
428
218k
    Dwarf_Block expression_block;
429
218k
    Dwarf_Unsigned code_alignment_factor = 0;
430
218k
    Dwarf_Signed data_alignment_factor = 0;
431
218k
    const char *op_name = 0;
432
433
218k
    expression_block = dwblockzero;
434
218k
    res = dwarf_get_frame_instruction_a(
435
218k
        frame_instr_head, i, &instr_offset_in_instrs, &cfa_operation, &fields,
436
218k
        &u0, &u1, &u2, &s0, &s1, &code_alignment_factor, &data_alignment_factor,
437
218k
        &expression_block, error);
438
218k
    res = dwarf_get_frame_instruction(
439
218k
        frame_instr_head, i, &instr_offset_in_instrs, &cfa_operation, &fields,
440
218k
        &u0, &u1, &s0, &s1, &code_alignment_factor, &data_alignment_factor,
441
218k
        &expression_block, error);
442
443
218k
    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
218k
    dwarf_get_CFA_name(cfa_operation, &op_name);
460
218k
    printf("[%2" DW_PR_DUu "]  %" DW_PR_DUu " %s ", i, instr_offset_in_instrs,
461
218k
           op_name);
462
218k
    switch (fields[0]) {
463
90.9k
    case 'u': {
464
90.9k
      if (!fields[1]) {
465
24.1k
        printf("%" DW_PR_DUu "\n", u0);
466
24.1k
      }
467
90.9k
      if (fields[1] == 'c') {
468
66.7k
        Dwarf_Unsigned final = u0 * code_alignment_factor;
469
66.7k
        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.7k
        printf("\n");
478
66.7k
      }
479
90.9k
    } break;
480
74.6k
    case 'r': {
481
74.6k
      if (!fields[1]) {
482
37.4k
        printf("r%" DW_PR_DUu "\n", u0);
483
37.4k
        break;
484
37.4k
      }
485
37.1k
      if (fields[1] == 'u') {
486
34.1k
        if (!fields[2]) {
487
5.86k
          printf("%" DW_PR_DUu, u1);
488
5.86k
          printf("\n");
489
5.86k
          break;
490
5.86k
        }
491
28.2k
        if (fields[2] == 'd') {
492
27.9k
          Dwarf_Signed final = (Dwarf_Signed)u0 * data_alignment_factor;
493
27.9k
          printf("%" DW_PR_DUu, final);
494
27.9k
          printf("\n");
495
27.9k
        }
496
28.2k
      }
497
31.2k
      if (fields[1] == 'r') {
498
1.13k
        printf("r%" DW_PR_DUu "\n", u0);
499
1.13k
        printf(" ");
500
1.13k
        printf("r%" DW_PR_DUu "\n", u1);
501
1.13k
        printf("\n");
502
1.13k
      }
503
31.2k
      if (fields[1] == 's') {
504
1.43k
        if (fields[2] == 'd') {
505
1.43k
          Dwarf_Signed final = 0;
506
1.43k
          printf("r%" DW_PR_DUu "\n", u0);
507
1.43k
          final = s1 * data_alignment_factor;
508
1.43k
          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.43k
          if (fields[3] == 'a') {
512
578
            printf(" addrspace %" DW_PR_DUu ,u2);
513
578
          }
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.43k
          printf("\n");
521
1.43k
        }
522
1.43k
      }
523
31.2k
      if (fields[1] == 'b') {
524
        /* rb */
525
407
        printf("r%" DW_PR_DUu "\n", u0);
526
407
        printf("%" DW_PR_DUu, u0);
527
407
        printf(" expr block len %" DW_PR_DUu "\n", expression_block.bl_len);
528
407
        dump_block("    ", expression_block.bl_data,
529
407
                   (Dwarf_Signed)expression_block.bl_len);
530
407
        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
407
      }
539
31.2k
    } break;
540
368
    case 's': {
541
368
      if (fields[1] == 'd') {
542
368
        Dwarf_Signed final = s0 * data_alignment_factor;
543
544
368
        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
368
        printf("\n");
552
368
      }
553
368
    } break;
554
500
    case 'b': {
555
500
      if (!fields[1]) {
556
500
        printf(" expr block len %" DW_PR_DUu "\n", expression_block.bl_len);
557
500
        dump_block("    ", expression_block.bl_data,
558
500
                   (Dwarf_Signed)expression_block.bl_len);
559
500
        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
500
      }
568
500
    } break;
569
51.9k
    case 0:
570
51.9k
      printf("\n");
571
51.9k
      break;
572
0
    default:
573
0
      printf("UNKNOWN FIELD 0x%x\n", fields[0]);
574
218k
    }
575
218k
  }
576
12.4k
  return DW_DLV_OK;
577
12.4k
}
578
579
static void print_fde_instrs(Dwarf_Debug dbg, Dwarf_Fde fde,
580
36.9k
                             Dwarf_Error *error) {
581
36.9k
  int res;
582
36.9k
  Dwarf_Addr lowpc = 0;
583
36.9k
  Dwarf_Unsigned func_length = 0;
584
36.9k
  Dwarf_Small *fde_bytes;
585
36.9k
  Dwarf_Unsigned fde_byte_length = 0;
586
36.9k
  Dwarf_Off cie_offset = 0;
587
36.9k
  Dwarf_Signed cie_index = 0;
588
36.9k
  Dwarf_Off fde_offset = 0;
589
36.9k
  Dwarf_Addr arbitrary_addr = 0;
590
36.9k
  Dwarf_Addr actual_pc = 0;
591
36.9k
  Dwarf_Regtable3 tab3;
592
36.9k
  int oldrulecount = 0;
593
36.9k
  Dwarf_Small *outinstrs = 0;
594
36.9k
  Dwarf_Unsigned instrslen = 0;
595
36.9k
  Dwarf_Cie cie = 0;
596
597
36.9k
  res = dwarf_get_fde_range(fde, &lowpc, &func_length, &fde_bytes,
598
36.9k
                            &fde_byte_length, &cie_offset, &cie_index,
599
36.9k
                            &fde_offset, error);
600
36.9k
  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.9k
  arbitrary_addr = lowpc + (func_length / 2);
609
36.9k
  printf("function low pc 0x%" DW_PR_DUx "  and length 0x%" DW_PR_DUx
610
36.9k
         "  and midpoint addr we choose 0x%" DW_PR_DUx "\n",
611
36.9k
         lowpc, func_length, arbitrary_addr);
612
613
36.9k
  oldrulecount = dwarf_set_frame_rule_table_size(dbg, 1);
614
36.9k
  dwarf_set_frame_rule_table_size(dbg, oldrulecount);
615
616
36.9k
  tab3.rt3_reg_table_size = oldrulecount;
617
36.9k
  tab3.rt3_rules = (struct Dwarf_Regtable_Entry3_s *)malloc(
618
36.9k
      sizeof(struct Dwarf_Regtable_Entry3_s) * oldrulecount);
619
36.9k
  if (!tab3.rt3_rules) {
620
0
    printf("Unable to malloc for %d rules\n", oldrulecount);
621
0
    return;
622
0
  }
623
624
36.9k
  res = dwarf_get_fde_info_for_all_regs3(fde, arbitrary_addr, &tab3, &actual_pc,
625
36.9k
                                         error);
626
36.9k
  printf("function actual addr of row 0x%" DW_PR_DUx "\n", actual_pc);
627
628
36.9k
  if (res != DW_DLV_OK) {
629
20.1k
    printf("dwarf_get_fde_info_for_all_regs3 failed!\n");
630
20.1k
    free(tab3.rt3_rules);
631
20.1k
    return;
632
20.1k
  }
633
16.8k
  print_regtable(&tab3);
634
635
16.8k
  res = dwarf_get_fde_instr_bytes(fde, &outinstrs, &instrslen, error);
636
16.8k
  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
16.8k
  res = dwarf_get_cie_of_fde(fde, &cie, error);
642
16.8k
  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
16.8k
  {
649
16.8k
    Dwarf_Frame_Instr_Head frame_instr_head = 0;
650
16.8k
    Dwarf_Unsigned frame_instr_count = 0;
651
16.8k
    res = dwarf_expand_frame_instructions(cie, outinstrs, instrslen,
652
16.8k
                                          &frame_instr_head, &frame_instr_count,
653
16.8k
                                          error);
654
16.8k
    if (res != DW_DLV_OK) {
655
4.32k
      free(tab3.rt3_rules);
656
4.32k
      printf("dwarf_expand_frame_instructions failed!\n");
657
4.32k
      return;
658
4.32k
    }
659
12.4k
    printf("Frame op count: %" DW_PR_DUu "\n", frame_instr_count);
660
12.4k
    print_frame_instrs(dbg, frame_instr_head, frame_instr_count, error);
661
662
12.4k
    dwarf_dealloc_frame_instr_head(frame_instr_head);
663
12.4k
  }
664
0
  free(tab3.rt3_rules);
665
12.4k
}
666
667
777k
static void print_reg(int r) {
668
777k
  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
777k
  default:
679
777k
    printf(" r%d ", r);
680
777k
    break;
681
777k
  }
682
777k
}
683
684
static void print_one_regentry(const char *prefix,
685
184k
                               struct Dwarf_Regtable_Entry3_s *entry) {
686
184k
  int is_cfa = !strcmp("cfa", prefix);
687
184k
  printf("%s ", prefix);
688
184k
  printf("type: %d %s ", entry->dw_value_type,
689
184k
         (entry->dw_value_type == DW_EXPR_OFFSET)       ? "DW_EXPR_OFFSET"
690
184k
         : (entry->dw_value_type == DW_EXPR_VAL_OFFSET) ? "DW_EXPR_VAL_OFFSET"
691
1.19k
         : (entry->dw_value_type == DW_EXPR_EXPRESSION) ? "DW_EXPR_EXPRESSION"
692
821
         : (entry->dw_value_type == DW_EXPR_VAL_EXPRESSION)
693
276
             ? "DW_EXPR_VAL_EXPRESSION"
694
276
             : "Unknown");
695
184k
  switch (entry->dw_value_type) {
696
183k
  case DW_EXPR_OFFSET:
697
183k
    print_reg(entry->dw_regnum);
698
183k
    printf(" offset_rel? %d ", entry->dw_offset_relevant);
699
183k
    if (entry->dw_offset_relevant) {
700
42.4k
      printf(" offset  %" DW_PR_DSd " ", entry->dw_offset);
701
42.4k
      if (is_cfa) {
702
11.2k
        printf("defines cfa value");
703
31.1k
      } else {
704
31.1k
        printf("address of value is CFA plus signed offset");
705
31.1k
      }
706
42.4k
      if (!is_cfa && entry->dw_regnum != CFA_VAL) {
707
31.1k
        printf(" compiler botch, regnum != CFA_VAL");
708
31.1k
      }
709
141k
    } else {
710
141k
      printf("value in register");
711
141k
    }
712
183k
    break;
713
372
  case DW_EXPR_VAL_OFFSET:
714
372
    print_reg(entry->dw_regnum);
715
372
    printf(" offset  %" DW_PR_DSd " ", entry->dw_offset);
716
372
    if (is_cfa) {
717
0
      printf("does this make sense? No?");
718
372
    } else {
719
372
      printf("value at CFA plus signed offset");
720
372
    }
721
372
    if (!is_cfa && entry->dw_regnum != CFA_VAL) {
722
372
      printf(" compiler botch, regnum != CFA_VAL");
723
372
    }
724
372
    break;
725
545
  case DW_EXPR_EXPRESSION:
726
545
    print_reg(entry->dw_regnum);
727
545
    printf(" offset_rel? %d ", entry->dw_offset_relevant);
728
545
    printf(" offset  %" DW_PR_DUu " ", entry->dw_offset);
729
545
    printf("Block ptr set? %s ", entry->dw_block.bl_data ? "yes" : "no");
730
545
    printf(" Value is at address given by expr val ");
731
545
    break;
732
276
  case DW_EXPR_VAL_EXPRESSION:
733
276
    printf(" expression byte len  %" DW_PR_DUu " ", entry->dw_block.bl_len);
734
276
    printf("Block ptr set? %s ", entry->dw_block.bl_data ? "yes" : "no");
735
276
    printf(" Value is expr val ");
736
276
    if (!entry->dw_block.bl_data) {
737
0
      printf("Compiler or libdwarf botch, "
738
0
             "NULL block data pointer. ");
739
0
    }
740
276
    break;
741
0
  default:
742
0
    break;
743
184k
  }
744
184k
  printf("\n");
745
184k
}
746
747
16.8k
static void print_regtable(Dwarf_Regtable3 *tab3) {
748
16.8k
  int r;
749
16.8k
  int max = 10;
750
16.8k
  if (max > tab3->rt3_reg_table_size) {
751
0
    max = tab3->rt3_reg_table_size;
752
0
  }
753
16.8k
  print_one_regentry("cfa", &tab3->rt3_cfa_rule);
754
755
184k
  for (r = 0; r < max; r++) {
756
168k
    char rn[30];
757
168k
    snprintf(rn, sizeof(rn), "reg %d", r);
758
168k
    print_one_regentry(rn, tab3->rt3_rules + r);
759
168k
  }
760
16.8k
}