Coverage Report

Created: 2025-11-11 06:41

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