Coverage Report

Created: 2025-12-10 06:38

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