Coverage Report

Created: 2025-11-09 06:48

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