Coverage Report

Created: 2025-08-26 06:24

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