Coverage Report

Created: 2024-07-27 07:07

/src/libdwarf/fuzz/fuzz_set_frame_all.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright 2021 Google LLC
2
Licensed under the Apache License, Version 2.0 (the "License");
3
you may not use this file except in compliance with the License.
4
You may obtain a copy of the License at
5
      http://www.apache.org/licenses/LICENSE-2.0
6
Unless required by applicable law or agreed to in writing, software
7
distributed under the License is distributed on an "AS IS" BASIS,
8
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9
See the License for the specific language governing permissions and
10
limitations under the License.
11
*/
12
#include <fcntl.h> /* open() O_RDONLY O_BINARY */
13
#include <limits.h>
14
#include <stdint.h>
15
#include <stdio.h>
16
#include <stdlib.h>
17
#include <string.h>
18
#include <sys/types.h>
19
#include <unistd.h>
20
#include "dwarf.h"
21
#include "libdwarf.h"
22
23
#ifndef O_BINARY
24
13.9k
#define O_BINARY 0 /* So it does nothing in Linux/Unix */
25
#endif
26
707k
#define DW_PR_DUx "llx"
27
#define DW_PR_DSx "llx"
28
132k
#define DW_PR_DUu "llu"
29
63.8k
#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
352k
#define UNDEF_VAL 2000
41
352k
#define SAME_VAL 2001
42
36.4k
#define CFA_VAL 2002
43
352k
#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
13.9k
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
60
13.9k
  char filename[256];
61
13.9k
  sprintf(filename, "/tmp/libfuzzer.%d", getpid());
62
63
13.9k
  FILE *fp = fopen(filename, "wb");
64
13.9k
  if (!fp) {
65
0
    return 0;
66
0
  }
67
13.9k
  fwrite(data, size, 1, fp);
68
13.9k
  fclose(fp);
69
70
13.9k
  Dwarf_Debug dbg = 0;
71
13.9k
  int res = DW_DLV_ERROR;
72
13.9k
  Dwarf_Error error = 0;
73
13.9k
  Dwarf_Handler errhand = 0;
74
13.9k
  Dwarf_Ptr errarg = 0;
75
13.9k
  int regtabrulecount = 0;
76
13.9k
  int curopt = 0;
77
78
13.9k
  int fd = open(filename, O_RDONLY | O_BINARY);
79
13.9k
  if (fd < 0) {
80
0
    printf("Unable to open %s, giving up.\n", filename);
81
0
    exit(EXIT_FAILURE);
82
0
  }
83
84
13.9k
  res = dwarf_init_b(fd, DW_GROUPNUMBER_ANY, errhand, errarg, &dbg, &error);
85
86
13.9k
  if (res != DW_DLV_OK) {
87
7.49k
    printf("Giving up, dwarf_init failed, "
88
7.49k
           "cannot do DWARF processing\n");
89
7.49k
    if (res == DW_DLV_ERROR) {
90
5.09k
      printf("Error code %s\n", dwarf_errmsg(error));
91
5.09k
    }
92
7.49k
    dwarf_dealloc_error(dbg, error);
93
7.49k
  } else {
94
6.46k
    Dwarf_Half frame_values[] = {SHRT_MIN, SHRT_MAX, 0};
95
25.8k
    for (int i = 0; i < 3; i++) {
96
19.4k
      dwarf_set_frame_undefined_value(dbg, frame_values[i]);
97
19.4k
      read_frame_data(dbg, ".debug_frame");
98
19.4k
      read_frame_data(dbg, ".eh_frame");
99
19.4k
    }
100
25.8k
    for (int i = 0; i < 3; i++) {
101
19.4k
      dwarf_set_frame_rule_initial_value(dbg, frame_values[i]);
102
19.4k
      read_frame_data(dbg, ".debug_frame");
103
19.4k
      read_frame_data(dbg, ".eh_frame");
104
19.4k
    }
105
25.8k
    for (int i = 0; i < 3; i++) {
106
19.4k
      dwarf_set_frame_same_value(dbg, frame_values[i]);
107
19.4k
      read_frame_data(dbg, ".debug_frame");
108
19.4k
      read_frame_data(dbg, ".eh_frame");
109
19.4k
    }
110
25.8k
    for (int i = 0; i < 3; i++) {
111
19.4k
      dwarf_set_frame_cfa_value(dbg, frame_values[i]);
112
19.4k
      read_frame_data(dbg, ".debug_frame");
113
19.4k
      read_frame_data(dbg, ".eh_frame");
114
19.4k
    }
115
25.8k
    for (int i = 0; i < 3; i++) {
116
19.4k
      dwarf_set_frame_rule_table_size(dbg, frame_values[i]);
117
19.4k
      read_frame_data(dbg, ".debug_frame");
118
19.4k
      read_frame_data(dbg, ".eh_frame");
119
19.4k
    }
120
6.46k
  }
121
122
13.9k
  res = dwarf_finish(dbg);
123
13.9k
  close(fd);
124
13.9k
  unlink(filename);
125
13.9k
  return 0;
126
13.9k
}
127
128
1.40k
static void dump_block(char *prefix, Dwarf_Small *data, Dwarf_Unsigned len) {
129
1.40k
  Dwarf_Small *end_data = data + len;
130
1.40k
  Dwarf_Small *cur = data;
131
1.40k
  int i = 0;
132
133
1.40k
  printf("%s", prefix);
134
12.9k
  for (; cur < end_data; ++cur, ++i) {
135
11.5k
    if (i > 0 && i % 4 == 0)
136
2.32k
      printf(" ");
137
11.5k
    printf("%02x", 0xff & *cur);
138
11.5k
  }
139
1.40k
}
140
141
194k
static void read_frame_data(Dwarf_Debug dbg, const char *sect) {
142
194k
  Dwarf_Error error;
143
194k
  Dwarf_Signed cie_element_count = 0;
144
194k
  Dwarf_Signed fde_element_count = 0;
145
194k
  Dwarf_Cie *cie_data = 0;
146
194k
  Dwarf_Fde *fde_data = 0;
147
194k
  int res = DW_DLV_ERROR;
148
194k
  Dwarf_Signed fdenum = 0;
149
150
194k
  printf(" Print %s\n", sect);
151
194k
  if (!strcmp(sect, ".eh_frame")) {
152
97.0k
    res = dwarf_get_fde_list_eh(dbg, &cie_data, &cie_element_count, &fde_data,
153
97.0k
                                &fde_element_count, &error);
154
97.0k
  } else {
155
97.0k
    res = dwarf_get_fde_list(dbg, &cie_data, &cie_element_count, &fde_data,
156
97.0k
                             &fde_element_count, &error);
157
97.0k
  }
158
194k
  if (res == DW_DLV_NO_ENTRY) {
159
98.1k
    printf("No %s data present\n", sect);
160
98.1k
    return;
161
98.1k
  }
162
95.9k
  if (res == DW_DLV_ERROR) {
163
89.4k
    printf("Error reading frame data \n");
164
89.4k
    return;
165
89.4k
  }
166
6.42k
  printf("%" DW_PR_DSd " cies present. "
167
6.42k
         "%" DW_PR_DSd " fdes present. \n",
168
6.42k
         cie_element_count, fde_element_count);
169
36.4k
  for (fdenum = 0; fdenum < fde_element_count; ++fdenum) {
170
30.0k
    Dwarf_Cie cie = 0;
171
172
30.0k
    Dwarf_Fde fde;
173
30.0k
    dwarf_get_fde_n(fde_data, fdenum, &fde, &error);
174
175
30.0k
    res = dwarf_get_cie_of_fde(fde, &cie, &error);
176
30.0k
    if (res != DW_DLV_OK) {
177
0
      printf("Error accessing cie of fdenum %" DW_PR_DSd " to get its cie\n",
178
0
             fdenum);
179
0
      return;
180
0
    }
181
30.0k
    printf("Print cie of fde %" DW_PR_DSd "\n", fdenum);
182
30.0k
    print_cie_instrs(cie, &error);
183
30.0k
    printf("Print fde %" DW_PR_DSd "\n", fdenum);
184
30.0k
    print_fde_selected_regs(fde_data[fdenum]);
185
30.0k
    print_fde_instrs(dbg, fde_data[fdenum], &error);
186
187
30.0k
    Dwarf_Signed dw_offset_into_exception_tables;
188
30.0k
    Dwarf_Signed dw_idx;
189
190
30.0k
    dwarf_get_fde_exception_info(fde_data[fdenum],
191
30.0k
                                 &dw_offset_into_exception_tables, &error);
192
30.0k
    dwarf_get_cie_index(cie, &dw_idx, &error);
193
194
30.0k
    Dwarf_Small *dw_augdata;
195
30.0k
    Dwarf_Unsigned dw_augdata_len;
196
30.0k
    dwarf_get_cie_augmentation_data(cie, &dw_augdata, &dw_augdata_len, &error);
197
198
30.0k
    Dwarf_Small *fde_augdata;
199
30.0k
    Dwarf_Unsigned fde_augdata_len;
200
30.0k
    dwarf_get_fde_augmentation_data(fde, &fde_augdata, &fde_augdata_len,
201
30.0k
                                    &error);
202
203
30.0k
    Dwarf_Off dw_fde_off;
204
30.0k
    Dwarf_Off dw_cie_off;
205
206
30.0k
    dwarf_fde_section_offset(dbg, fde, &dw_fde_off, &dw_cie_off, &error);
207
30.0k
    dwarf_cie_section_offset(dbg, cie, &dw_cie_off, &error);
208
30.0k
  }
209
210
6.42k
  dwarf_dealloc_fde_cie_list(dbg, cie_data, cie_element_count, fde_data,
211
6.42k
                             fde_element_count);
212
6.42k
  return;
213
6.42k
}
214
215
30.0k
static void print_cie_instrs(Dwarf_Cie cie, Dwarf_Error *error) {
216
30.0k
  int res = DW_DLV_ERROR;
217
30.0k
  Dwarf_Unsigned bytes_in_cie = 0;
218
30.0k
  Dwarf_Small version = 0;
219
30.0k
  char *augmentation = 0;
220
30.0k
  Dwarf_Unsigned code_alignment_factor = 0;
221
30.0k
  Dwarf_Signed data_alignment_factor = 0;
222
30.0k
  Dwarf_Half return_address_register_rule = 0;
223
30.0k
  Dwarf_Small *instrp = 0;
224
30.0k
  Dwarf_Unsigned instr_len = 0;
225
30.0k
  Dwarf_Half offset_size = 0;
226
227
30.0k
  res = dwarf_get_cie_info_b(cie, &bytes_in_cie, &version, &augmentation,
228
30.0k
                             &code_alignment_factor, &data_alignment_factor,
229
30.0k
                             &return_address_register_rule, &instrp, &instr_len,
230
30.0k
                             &offset_size, error);
231
30.0k
  if (res != DW_DLV_OK) {
232
0
    printf("Unable to get cie info!\n");
233
0
    return;
234
0
  }
235
30.0k
}
236
237
static void print_fde_col(Dwarf_Signed k, Dwarf_Addr jsave,
238
                          Dwarf_Small value_type, Dwarf_Signed offset_relevant,
239
                          Dwarf_Signed reg_used, Dwarf_Signed offset,
240
                          Dwarf_Block *block, Dwarf_Addr row_pc,
241
353k
                          Dwarf_Bool has_more_rows, Dwarf_Addr subsequent_pc) {
242
353k
  char *type_title = "";
243
353k
  Dwarf_Unsigned rule_id = k;
244
245
353k
  printf(" pc=0x%" DW_PR_DUx, jsave);
246
353k
  if (row_pc != jsave) {
247
1.39k
    printf(" row_pc=0x%" DW_PR_DUx, row_pc);
248
1.39k
  }
249
353k
  printf(" col=%" DW_PR_DSd " ", k);
250
353k
  switch (value_type) {
251
351k
  case DW_EXPR_OFFSET:
252
351k
    type_title = "off";
253
351k
    goto preg2;
254
518
  case DW_EXPR_VAL_OFFSET:
255
518
    type_title = "valoff";
256
257
352k
  preg2:
258
352k
    printf("<%s ", type_title);
259
352k
    if (reg_used == SAME_VAL) {
260
0
      printf(" SAME_VAL");
261
0
      break;
262
352k
    } else if (reg_used == INITIAL_VAL) {
263
0
      printf(" INITIAL_VAL");
264
0
      break;
265
0
    }
266
352k
    print_reg(rule_id);
267
268
352k
    printf("=");
269
352k
    if (offset_relevant == 0) {
270
290k
      print_reg(reg_used);
271
290k
      printf(" ");
272
290k
    } else {
273
62.0k
      printf("%02" DW_PR_DSd, offset);
274
62.0k
      printf("(");
275
62.0k
      print_reg(reg_used);
276
62.0k
      printf(") ");
277
62.0k
    }
278
352k
    break;
279
438
  case DW_EXPR_EXPRESSION:
280
438
    type_title = "expr";
281
438
    goto pexp2;
282
305
  case DW_EXPR_VAL_EXPRESSION:
283
305
    type_title = "valexpr";
284
285
743
  pexp2:
286
743
    printf("<%s ", type_title);
287
743
    print_reg(rule_id);
288
743
    printf("=");
289
743
    printf("expr-block-len=%" DW_PR_DUu, block->bl_len);
290
743
    {
291
743
      char pref[40];
292
293
743
      strcpy(pref, "<");
294
743
      strcat(pref, type_title);
295
743
      strcat(pref, "bytes:");
296
743
      dump_block(pref, block->bl_data, block->bl_len);
297
743
      printf("%s", "> \n");
298
#if 0
299
            if (glflags.verbose) {
300
                struct esb_s exprstring;
301
                esb_constructor(&exprstring);
302
                get_string_from_locs(dbg,
303
                    block_ptr,offset,addr_size,
304
                    offset_size,version,&exprstring);
305
                printf("<expr:%s>",esb_get_string(&exprstring));
306
                esb_destructor(&exprstring);
307
            }
308
#endif
309
743
    }
310
743
    break;
311
0
  default:
312
0
    printf("Internal error in libdwarf, value type %d\n", value_type);
313
0
    return;
314
353k
  }
315
353k
  printf(" more=%d", has_more_rows);
316
353k
  printf(" next=0x%" DW_PR_DUx, subsequent_pc);
317
353k
  printf("%s", "> ");
318
353k
  printf("\n");
319
353k
}
320
321
static const Dwarf_Block dwblockzero;
322
30.0k
static void print_fde_selected_regs(Dwarf_Fde fde) {
323
30.0k
  Dwarf_Error oneferr = 0;
324
30.0k
  static int selected_cols[] = {1, 3, 5};
325
30.0k
  static int selected_cols_count =
326
30.0k
      sizeof(selected_cols) / sizeof(selected_cols[0]);
327
30.0k
  Dwarf_Signed k = 0;
328
30.0k
  int fres = 0;
329
330
30.0k
  Dwarf_Addr low_pc = 0;
331
30.0k
  Dwarf_Unsigned func_length = 0;
332
30.0k
  Dwarf_Small *fde_bytes = NULL;
333
30.0k
  Dwarf_Unsigned fde_bytes_length = 0;
334
30.0k
  Dwarf_Off cie_offset = 0;
335
30.0k
  Dwarf_Signed cie_index = 0;
336
30.0k
  Dwarf_Off fde_offset = 0;
337
30.0k
  Dwarf_Fde curfde = fde;
338
30.0k
  Dwarf_Cie cie = 0;
339
30.0k
  Dwarf_Addr jsave = 0;
340
30.0k
  Dwarf_Addr high_addr = 0;
341
30.0k
  Dwarf_Addr next_jsave = 0;
342
30.0k
  Dwarf_Bool has_more_rows = 0;
343
30.0k
  Dwarf_Addr subsequent_pc = 0;
344
30.0k
  Dwarf_Error error = 0;
345
30.0k
  int res = 0;
346
347
30.0k
  fres = dwarf_get_fde_range(curfde, &low_pc, &func_length, &fde_bytes,
348
30.0k
                             &fde_bytes_length, &cie_offset, &cie_index,
349
30.0k
                             &fde_offset, &oneferr);
350
351
30.0k
  if (fres == DW_DLV_ERROR) {
352
0
    printf("FAIL: dwarf_get_fde_range err %" DW_PR_DUu " line %d\n",
353
0
           dwarf_errno(oneferr), __LINE__);
354
0
    return;
355
0
  }
356
30.0k
  if (fres == DW_DLV_NO_ENTRY) {
357
0
    printf("No fde range data available\n");
358
0
    return;
359
0
  }
360
30.0k
  res = dwarf_get_cie_of_fde(fde, &cie, &error);
361
30.0k
  if (res != DW_DLV_OK) {
362
0
    printf("Error getting cie from fde\n");
363
0
    return;
364
0
  }
365
366
30.0k
  high_addr = low_pc + func_length;
367
147k
  for (jsave = low_pc; next_jsave < high_addr; jsave = next_jsave) {
368
128k
    next_jsave = jsave + 1;
369
128k
    printf("\n");
370
481k
    for (k = 0; k < selected_cols_count; ++k) {
371
364k
      Dwarf_Unsigned reg = 0;
372
364k
      Dwarf_Unsigned offset_relevant = 0;
373
364k
      int fires = 0;
374
364k
      Dwarf_Small value_type = 0;
375
364k
      Dwarf_Block block;
376
364k
      Dwarf_Unsigned offset;
377
364k
      Dwarf_Addr row_pc = 0;
378
379
364k
      block = dwblockzero;
380
364k
      fires = dwarf_get_fde_info_for_reg3_b(
381
364k
          curfde, selected_cols[k], jsave, &value_type, &offset_relevant, &reg,
382
364k
          &offset, &block, &row_pc, &has_more_rows, &subsequent_pc, &oneferr);
383
364k
      if (fires == DW_DLV_ERROR) {
384
11.1k
        printf("FAIL: dwarf_get_fde_info_for_reg3_b, "
385
11.1k
            "reading reg err %s line %d\n",
386
11.1k
            dwarf_errmsg(oneferr), __LINE__);
387
11.1k
        return;
388
11.1k
      }
389
353k
      if (fires == DW_DLV_NO_ENTRY) {
390
0
        continue;
391
0
      }
392
353k
      print_fde_col(selected_cols[k], jsave, value_type, offset_relevant, reg,
393
353k
                    offset, &block, row_pc, has_more_rows, subsequent_pc);
394
353k
      if (has_more_rows) {
395
304k
        next_jsave = subsequent_pc;
396
304k
      } else {
397
48.4k
        next_jsave = high_addr;
398
48.4k
      }
399
353k
    }
400
128k
  }
401
30.0k
}
402
403
static int print_frame_instrs(Dwarf_Debug dbg,
404
                              Dwarf_Frame_Instr_Head frame_instr_head,
405
                              Dwarf_Unsigned frame_instr_count,
406
17.0k
                              Dwarf_Error *error) {
407
17.0k
  Dwarf_Unsigned i = 0;
408
409
17.0k
  printf("\nPrint %" DW_PR_DUu " frame instructions\n", frame_instr_count);
410
308k
  for (; i < frame_instr_count; ++i) {
411
291k
    int res = 0;
412
291k
    Dwarf_Unsigned instr_offset_in_instrs = 0;
413
291k
    Dwarf_Small cfa_operation = 0;
414
291k
    const char *fields = 0;
415
291k
    Dwarf_Unsigned u0 = 0;
416
291k
    Dwarf_Unsigned u1 = 0;
417
291k
    Dwarf_Unsigned u2 = 0;
418
291k
    Dwarf_Signed s0 = 0;
419
291k
    Dwarf_Signed s1 = 0;
420
291k
    Dwarf_Block expression_block;
421
291k
    Dwarf_Unsigned code_alignment_factor = 0;
422
291k
    Dwarf_Signed data_alignment_factor = 0;
423
291k
    const char *op_name = 0;
424
425
291k
    expression_block = dwblockzero;
426
291k
    res = dwarf_get_frame_instruction_a(
427
291k
        frame_instr_head, i, &instr_offset_in_instrs, &cfa_operation, &fields,
428
291k
        &u0, &u1, &u2, &s0, &s1, &code_alignment_factor, &data_alignment_factor,
429
291k
        &expression_block, error);
430
291k
    res = dwarf_get_frame_instruction(
431
291k
        frame_instr_head, i, &instr_offset_in_instrs, &cfa_operation, &fields,
432
291k
        &u0, &u1, &s0, &s1, &code_alignment_factor, &data_alignment_factor,
433
291k
        &expression_block, error);
434
435
291k
    if (res != DW_DLV_OK) {
436
0
      if (res == DW_DLV_ERROR) {
437
0
        printf("ERROR reading frame instruction "
438
0
               "%" DW_PR_DUu "\n",
439
0
               frame_instr_count);
440
0
        if(error) {
441
0
          dwarf_dealloc_error(dbg, *error);
442
0
          *error = 0;
443
0
        }
444
0
      } else {
445
0
        printf("NO ENTRY reading frame instruction "
446
0
               " %" DW_PR_DUu "\n",
447
0
               frame_instr_count);
448
0
      }
449
0
      break;
450
0
    }
451
291k
    dwarf_get_CFA_name(cfa_operation, &op_name);
452
291k
    printf("[%2" DW_PR_DUu "]  %" DW_PR_DUu " %s ", i, instr_offset_in_instrs,
453
291k
           op_name);
454
291k
    switch (fields[0]) {
455
127k
    case 'u': {
456
127k
      if (!fields[1]) {
457
39.9k
        printf("%" DW_PR_DUu "\n", u0);
458
39.9k
      }
459
127k
      if (fields[1] == 'c') {
460
87.7k
        Dwarf_Unsigned final = u0 * code_alignment_factor;
461
87.7k
        printf("%" DW_PR_DUu, final);
462
#if 0
463
                if (glflags.verbose) {
464
                    printf("  (%" DW_PR_DUu " * %" DW_PR_DUu,
465
                        u0,code_alignment_factor);
466
467
                }
468
#endif
469
87.7k
        printf("\n");
470
87.7k
      }
471
127k
    } break;
472
84.9k
    case 'r': {
473
84.9k
      if (!fields[1]) {
474
39.1k
        printf("r%" DW_PR_DUu "\n", u0);
475
39.1k
        break;
476
39.1k
      }
477
45.8k
      if (fields[1] == 'u') {
478
43.2k
        if (!fields[2]) {
479
5.07k
          printf("%" DW_PR_DUu, u1);
480
5.07k
          printf("\n");
481
5.07k
          break;
482
5.07k
        }
483
38.2k
        if (fields[2] == 'd') {
484
37.8k
          Dwarf_Signed final = (Dwarf_Signed)u0 * data_alignment_factor;
485
37.8k
          printf("%" DW_PR_DUu, final);
486
37.8k
          printf("\n");
487
37.8k
        }
488
38.2k
      }
489
40.7k
      if (fields[1] == 'r') {
490
735
        printf("r%" DW_PR_DUu "\n", u0);
491
735
        printf(" ");
492
735
        printf("r%" DW_PR_DUu "\n", u1);
493
735
        printf("\n");
494
735
      }
495
40.7k
      if (fields[1] == 's') {
496
1.39k
        if (fields[2] == 'd') {
497
1.39k
          Dwarf_Signed final = 0;
498
1.39k
          printf("r%" DW_PR_DUu "\n", u0);
499
1.39k
          final = s1 * data_alignment_factor;
500
1.39k
          printf("%" DW_PR_DSd, final);
501
          /*  The original did not do this check for 'a'
502
              but it's harmless to the testing, so added. 2023-06-10 */
503
1.39k
          if (fields[3] == 'a') {
504
365
            printf(" addrspace %" DW_PR_DUu ,u2);
505
365
          }
506
#if 0
507
                    if (glflags.verbose) {
508
                        printf("  (%" DW_PR_DSd " * %" DW_PR_DSd,
509
                            s1,data_alignment_factor);
510
                    }
511
#endif
512
1.39k
          printf("\n");
513
1.39k
        }
514
1.39k
      }
515
40.7k
      if (fields[1] == 'b') {
516
        /* rb */
517
425
        printf("r%" DW_PR_DUu "\n", u0);
518
425
        printf("%" DW_PR_DUu, u0);
519
425
        printf(" expr block len %" DW_PR_DUu "\n", expression_block.bl_len);
520
425
        dump_block("    ", expression_block.bl_data,
521
425
                   (Dwarf_Signed)expression_block.bl_len);
522
425
        printf("\n");
523
#if 0
524
                if (glflags.verbose) {
525
                    print_expression(dbg,die,&expression_block,
526
                        addr_size,offset_size,
527
                        version);
528
                }
529
#endif
530
425
      }
531
40.7k
    } break;
532
390
    case 's': {
533
390
      if (fields[1] == 'd') {
534
390
        Dwarf_Signed final = s0 * data_alignment_factor;
535
536
390
        printf(" %" DW_PR_DSd, final);
537
#if 0
538
                if (glflags.verbose) {
539
                    printf("  (%" DW_PR_DSd " * %" DW_PR_DSd,
540
                        s0,data_alignment_factor);
541
                }
542
#endif
543
390
        printf("\n");
544
390
      }
545
390
    } break;
546
233
    case 'b': {
547
233
      if (!fields[1]) {
548
233
        printf(" expr block len %" DW_PR_DUu "\n", expression_block.bl_len);
549
233
        dump_block("    ", expression_block.bl_data,
550
233
                   (Dwarf_Signed)expression_block.bl_len);
551
233
        printf("\n");
552
#if 0
553
                if (glflags.verbose) {
554
                    print_expression(dbg,die,&expression_block,
555
                        addr_size,offset_size,
556
                        version);
557
                }
558
#endif
559
233
      }
560
233
    } break;
561
77.7k
    case 0:
562
77.7k
      printf("\n");
563
77.7k
      break;
564
0
    default:
565
0
      printf("UNKNOWN FIELD 0x%x\n", fields[0]);
566
291k
    }
567
291k
  }
568
17.0k
  return DW_DLV_OK;
569
17.0k
}
570
571
static void print_fde_instrs(Dwarf_Debug dbg, Dwarf_Fde fde,
572
30.0k
                             Dwarf_Error *error) {
573
30.0k
  int res;
574
30.0k
  Dwarf_Addr lowpc = 0;
575
30.0k
  Dwarf_Unsigned func_length = 0;
576
30.0k
  Dwarf_Small *fde_bytes;
577
30.0k
  Dwarf_Unsigned fde_byte_length = 0;
578
30.0k
  Dwarf_Off cie_offset = 0;
579
30.0k
  Dwarf_Signed cie_index = 0;
580
30.0k
  Dwarf_Off fde_offset = 0;
581
30.0k
  Dwarf_Addr arbitrary_addr = 0;
582
30.0k
  Dwarf_Addr actual_pc = 0;
583
30.0k
  Dwarf_Regtable3 tab3;
584
30.0k
  int oldrulecount = 0;
585
30.0k
  Dwarf_Small *outinstrs = 0;
586
30.0k
  Dwarf_Unsigned instrslen = 0;
587
30.0k
  Dwarf_Cie cie = 0;
588
589
30.0k
  res = dwarf_get_fde_range(fde, &lowpc, &func_length, &fde_bytes,
590
30.0k
                            &fde_byte_length, &cie_offset, &cie_index,
591
30.0k
                            &fde_offset, error);
592
30.0k
  if (res != DW_DLV_OK) {
593
    /*  So nothing clears the error record here,
594
        the caller does not know the call failed.
595
        Terrible code, but interesting testcase. */
596
0
    printf("Problem getting fde range \n");
597
0
    return;
598
0
  }
599
600
30.0k
  arbitrary_addr = lowpc + (func_length / 2);
601
30.0k
  printf("function low pc 0x%" DW_PR_DUx "  and length 0x%" DW_PR_DUx
602
30.0k
         "  and midpoint addr we choose 0x%" DW_PR_DUx "\n",
603
30.0k
         lowpc, func_length, arbitrary_addr);
604
605
30.0k
  oldrulecount = dwarf_set_frame_rule_table_size(dbg, 1);
606
30.0k
  dwarf_set_frame_rule_table_size(dbg, oldrulecount);
607
608
30.0k
  tab3.rt3_reg_table_size = oldrulecount;
609
30.0k
  tab3.rt3_rules = (struct Dwarf_Regtable_Entry3_s *)malloc(
610
30.0k
      sizeof(struct Dwarf_Regtable_Entry3_s) * oldrulecount);
611
30.0k
  if (!tab3.rt3_rules) {
612
0
    printf("Unable to malloc for %d rules\n", oldrulecount);
613
0
    return;
614
0
  }
615
616
30.0k
  res = dwarf_get_fde_info_for_all_regs3(fde, arbitrary_addr, &tab3, &actual_pc,
617
30.0k
                                         error);
618
30.0k
  printf("function actual addr of row 0x%" DW_PR_DUx "\n", actual_pc);
619
620
30.0k
  if (res != DW_DLV_OK) {
621
8.15k
    printf("dwarf_get_fde_info_for_all_regs3 failed!\n");
622
8.15k
    free(tab3.rt3_rules);
623
8.15k
    return;
624
8.15k
  }
625
21.8k
  print_regtable(&tab3);
626
627
21.8k
  res = dwarf_get_fde_instr_bytes(fde, &outinstrs, &instrslen, error);
628
21.8k
  if (res != DW_DLV_OK) {
629
0
    free(tab3.rt3_rules);
630
0
    printf("dwarf_get_fde_instr_bytes failed!\n");
631
0
    return;
632
0
  }
633
21.8k
  res = dwarf_get_cie_of_fde(fde, &cie, error);
634
21.8k
  if (res != DW_DLV_OK) {
635
0
    free(tab3.rt3_rules);
636
0
    printf("Error getting cie from fde\n");
637
0
    return;
638
0
  }
639
640
21.8k
  {
641
21.8k
    Dwarf_Frame_Instr_Head frame_instr_head = 0;
642
21.8k
    Dwarf_Unsigned frame_instr_count = 0;
643
21.8k
    res = dwarf_expand_frame_instructions(cie, outinstrs, instrslen,
644
21.8k
                                          &frame_instr_head, &frame_instr_count,
645
21.8k
                                          error);
646
21.8k
    if (res != DW_DLV_OK) {
647
4.80k
      free(tab3.rt3_rules);
648
4.80k
      printf("dwarf_expand_frame_instructions failed!\n");
649
4.80k
      return;
650
4.80k
    }
651
17.0k
    printf("Frame op count: %" DW_PR_DUu "\n", frame_instr_count);
652
17.0k
    print_frame_instrs(dbg, frame_instr_head, frame_instr_count, error);
653
654
17.0k
    dwarf_dealloc_frame_instr_head(frame_instr_head);
655
17.0k
  }
656
0
  free(tab3.rt3_rules);
657
17.0k
}
658
659
945k
static void print_reg(int r) {
660
945k
  switch (r) {
661
0
  case SAME_VAL:
662
0
    printf(" %d SAME_VAL ", r);
663
0
    break;
664
0
  case UNDEF_VAL:
665
0
    printf(" %d UNDEF_VAL ", r);
666
0
    break;
667
0
  case CFA_VAL:
668
0
    printf(" %d (CFA) ", r);
669
0
    break;
670
945k
  default:
671
945k
    printf(" r%d ", r);
672
945k
    break;
673
945k
  }
674
945k
}
675
676
static void print_one_regentry(const char *prefix,
677
240k
                               struct Dwarf_Regtable_Entry3_s *entry) {
678
240k
  int is_cfa = !strcmp("cfa", prefix);
679
240k
  printf("%s ", prefix);
680
240k
  printf("type: %d %s ", entry->dw_value_type,
681
240k
         (entry->dw_value_type == DW_EXPR_OFFSET)       ? "DW_EXPR_OFFSET"
682
240k
         : (entry->dw_value_type == DW_EXPR_VAL_OFFSET) ? "DW_EXPR_VAL_OFFSET"
683
1.11k
         : (entry->dw_value_type == DW_EXPR_EXPRESSION) ? "DW_EXPR_EXPRESSION"
684
571
         : (entry->dw_value_type == DW_EXPR_VAL_EXPRESSION)
685
229
             ? "DW_EXPR_VAL_EXPRESSION"
686
229
             : "Unknown");
687
240k
  switch (entry->dw_value_type) {
688
239k
  case DW_EXPR_OFFSET:
689
239k
    print_reg(entry->dw_regnum);
690
239k
    printf(" offset_rel? %d ", entry->dw_offset_relevant);
691
239k
    if (entry->dw_offset_relevant) {
692
51.4k
      printf(" offset  %" DW_PR_DSd " ", entry->dw_offset);
693
51.4k
      if (is_cfa) {
694
15.4k
        printf("defines cfa value");
695
35.9k
      } else {
696
35.9k
        printf("address of value is CFA plus signed offset");
697
35.9k
      }
698
51.4k
      if (!is_cfa && entry->dw_regnum != CFA_VAL) {
699
35.9k
        printf(" compiler botch, regnum != CFA_VAL");
700
35.9k
      }
701
188k
    } else {
702
188k
      printf("value in register");
703
188k
    }
704
239k
    break;
705
544
  case DW_EXPR_VAL_OFFSET:
706
544
    print_reg(entry->dw_regnum);
707
544
    printf(" offset  %" DW_PR_DSd " ", entry->dw_offset);
708
544
    if (is_cfa) {
709
0
      printf("does this make sense? No?");
710
544
    } else {
711
544
      printf("value at CFA plus signed offset");
712
544
    }
713
544
    if (!is_cfa && entry->dw_regnum != CFA_VAL) {
714
544
      printf(" compiler botch, regnum != CFA_VAL");
715
544
    }
716
544
    break;
717
342
  case DW_EXPR_EXPRESSION:
718
342
    print_reg(entry->dw_regnum);
719
342
    printf(" offset_rel? %d ", entry->dw_offset_relevant);
720
342
    printf(" offset  %" DW_PR_DUu " ", entry->dw_offset);
721
342
    printf("Block ptr set? %s ", entry->dw_block.bl_data ? "yes" : "no");
722
342
    printf(" Value is at address given by expr val ");
723
342
    break;
724
229
  case DW_EXPR_VAL_EXPRESSION:
725
229
    printf(" expression byte len  %" DW_PR_DUu " ", entry->dw_block.bl_len);
726
229
    printf("Block ptr set? %s ", entry->dw_block.bl_data ? "yes" : "no");
727
229
    printf(" Value is expr val ");
728
229
    if (!entry->dw_block.bl_data) {
729
0
      printf("Compiler or libdwarf botch, "
730
0
             "NULL block data pointer. ");
731
0
    }
732
229
    break;
733
0
  default:
734
0
    break;
735
240k
  }
736
240k
  printf("\n");
737
240k
}
738
739
21.8k
static void print_regtable(Dwarf_Regtable3 *tab3) {
740
21.8k
  int r;
741
21.8k
  int max = 10;
742
21.8k
  if (max > tab3->rt3_reg_table_size) {
743
0
    max = tab3->rt3_reg_table_size;
744
0
  }
745
21.8k
  print_one_regentry("cfa", &tab3->rt3_cfa_rule);
746
747
240k
  for (r = 0; r < max; r++) {
748
218k
    char rn[30];
749
218k
    snprintf(rn, sizeof(rn), "reg %d", r);
750
218k
    print_one_regentry(rn, tab3->rt3_rules + r);
751
218k
  }
752
21.8k
}