Coverage Report

Created: 2025-09-27 06:39

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