Coverage Report

Created: 2026-09-04 07:06

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