Coverage Report

Created: 2026-09-04 07:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libdwarf/fuzz/fuzz_findfuncbypc.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 <config.h>
13
#include <stdint.h>
14
#include <stdio.h>
15
#include <stdlib.h>
16
#include <string.h>
17
#include <sys/types.h>
18
#include <unistd.h>
19
20
/*
21
 * Libdwarf library callers can only use these headers.
22
 */
23
#include "dwarf.h"
24
#include "libdwarf.h"
25
26
#define DW_PR_DUx "llx"
27
#define DW_PR_DSx "llx"
28
#define DW_PR_DUu "llu"
29
#define DW_PR_DSd "lld"
30
31
55.6k
#define TRUE 1
32
294k
#define FALSE 0
33
static int unittype = DW_UT_compile;
34
static Dwarf_Bool g_is_info = FALSE;
35
36
int cu_version_stamp = 0;
37
int cu_offset_size = 0;
38
39
struct srcfilesdata {
40
  char **srcfiles;
41
  Dwarf_Signed srcfilescount;
42
  int srcfilesres;
43
};
44
struct target_data_s {
45
  Dwarf_Debug td_dbg;
46
  Dwarf_Unsigned td_target_pc; /* from argv */
47
  int td_print_details;        /* from argv */
48
  int td_reportallfound;       /* from argv */
49
50
  /*  cu die data. */
51
  Dwarf_Unsigned td_cu_lowpc;
52
  Dwarf_Unsigned td_cu_highpc;
53
  int td_cu_haslowhighpc;
54
  Dwarf_Die td_cu_die;
55
  char *td_cu_name;
56
  char *td_cu_comp_dir;
57
  Dwarf_Unsigned td_cu_number;
58
  struct srcfilesdata td_cu_srcfiles;
59
  Dwarf_Unsigned td_cu_ranges_base;
60
61
  Dwarf_Off td_ranges_offset;
62
  char *td_subprog_name;
63
  Dwarf_Unsigned td_subprog_fileindex;
64
  Dwarf_Die td_subprog_die;
65
  Dwarf_Unsigned td_subprog_lowpc;
66
  Dwarf_Unsigned td_subprog_highpc;
67
  int td_subprog_haslowhighpc;
68
  Dwarf_Unsigned td_subprog_lineaddr;
69
  Dwarf_Unsigned td_subprog_lineno;
70
  char *td_subprog_srcfile; /* dealloc */
71
};
72
583k
#define NOT_THIS_CU 10
73
341k
#define IN_THIS_CU 11
74
700k
#define FOUND_SUBPROG 12
75
76
static int look_for_our_target(Dwarf_Debug dbg,
77
                               struct target_data_s *target_data,
78
                               Dwarf_Error *errp);
79
static int examine_die_data(Dwarf_Debug dbg, int is_info, Dwarf_Die die,
80
                            int level, struct target_data_s *td,
81
                            Dwarf_Error *errp);
82
static int check_comp_dir(Dwarf_Debug dbg, Dwarf_Die die,
83
                          struct target_data_s *td, Dwarf_Error *errp);
84
static int get_die_and_siblings(Dwarf_Debug dbg, Dwarf_Die in_die, int is_info,
85
                                int in_level, int cu_number,
86
                                struct target_data_s *td, Dwarf_Error *errp);
87
88
#if 0
89
DW_UT_compile                   0x01  /* DWARF5 */
90
DW_UT_type                      0x02  /* DWARF5 */
91
DW_UT_partial                   0x03  /* DWARF5 */
92
#endif
93
94
16.9k
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
95
16.9k
  char filename[256];
96
97
#ifdef DWREGRESSIONTEMP 
98
  /*  under msys2, the /tmp/ results in an open fail,
99
      so we discard the /tmp/. No need for
100
      /tmp/ in Linux anyway. libdwarf regressiontests
101
      use it this way. */
102
  sprintf(filename, "junklibfuzzer.%d", getpid());
103
#else
104
16.9k
  sprintf(filename, "/tmp/libfuzzer.%d", getpid());
105
16.9k
#endif
106
16.9k
  FILE *fp = fopen(filename, "wb");
107
16.9k
  if (!fp) {
108
0
    printf("FAIL libfuzzer cannot open temp as writeable %s\n",
109
0
        filename);
110
0
    return 0;
111
0
  }
112
16.9k
  fwrite(data, size, 1, fp);
113
16.9k
  fclose(fp);
114
115
16.9k
  Dwarf_Debug dbg = 0;
116
16.9k
  Dwarf_Error error = 0;
117
16.9k
  Dwarf_Handler errhand = 0;
118
16.9k
  Dwarf_Ptr errarg = 0;
119
16.9k
  int i = 0;
120
16.9k
  Dwarf_Unsigned target_pc = 0x1000;
121
16.9k
#define PATH_LEN 2000
122
16.9k
  char real_path[PATH_LEN];
123
16.9k
  struct target_data_s target_data;
124
125
  /*  Added 19 May 2023 so valgrind will not complain
126
      about testing uninitialized values in
127
      check_coup_dir (for example). */
128
16.9k
  memset(&target_data,0,sizeof(target_data));
129
16.9k
  int res =
130
16.9k
      dwarf_init_path(filename, 0, 0, DW_GROUPNUMBER_ANY, 0, 0, &dbg, &error);
131
16.9k
  if (res == DW_DLV_ERROR) {
132
5.14k
    dwarf_dealloc_error(dbg, error);
133
5.14k
    dwarf_finish(dbg);
134
11.7k
  } else {
135
11.7k
    res = look_for_our_target(dbg, &target_data, &error);
136
11.7k
    res = dwarf_finish(dbg);
137
11.7k
  }
138
139
16.9k
  unlink(filename);
140
16.9k
  return 0;
141
16.9k
}
142
143
static int read_line_data(Dwarf_Debug dbg, struct target_data_s *td,
144
1.34k
                          Dwarf_Error *errp) {
145
1.34k
  int res = 0;
146
1.34k
  Dwarf_Unsigned line_version = 0;
147
1.34k
  Dwarf_Small table_type = 0;
148
1.34k
  Dwarf_Line_Context line_context = 0;
149
1.34k
  Dwarf_Signed i = 0;
150
1.34k
  Dwarf_Signed baseindex = 0;
151
1.34k
  Dwarf_Signed endindex = 0;
152
1.34k
  Dwarf_Signed file_count = 0;
153
1.34k
  Dwarf_Unsigned dirindex = 0;
154
155
1.34k
  (void)dbg;
156
1.34k
  res = dwarf_srclines_b(td->td_cu_die, &line_version, &table_type,
157
1.34k
                         &line_context, errp);
158
1.34k
  if (res != DW_DLV_OK) {
159
1.05k
    return res;
160
1.05k
  }
161
286
  if (table_type == 0) {
162
11
    int sres = 0;
163
164
11
    sres = dwarf_srclines_files_indexes(line_context, &baseindex, &file_count,
165
11
                                        &endindex, errp);
166
11
    if (sres != DW_DLV_OK) {
167
0
      dwarf_srclines_dealloc_b(line_context);
168
0
      line_context = 0;
169
0
      return sres;
170
0
    }
171
784
    for (i = baseindex; i < endindex; i++) {
172
773
      Dwarf_Unsigned modtime = 0;
173
773
      Dwarf_Unsigned flength = 0;
174
773
      Dwarf_Form_Data16 *md5data = 0;
175
773
      int vres = 0;
176
773
      const char *name = 0;
177
178
773
      vres = dwarf_srclines_files_data_b(line_context, i, &name, &dirindex,
179
773
                                         &modtime, &flength, &md5data, errp);
180
773
      if (vres != DW_DLV_OK) {
181
0
        dwarf_srclines_dealloc_b(line_context);
182
0
        line_context = 0;
183
0
        return vres;
184
0
      }
185
773
    }
186
11
    dwarf_srclines_dealloc_b(line_context);
187
11
    return DW_DLV_OK;
188
275
  } else if (table_type == 1) {
189
273
    const char *dir_name = 0;
190
273
    int sres = 0;
191
273
    Dwarf_Line *linebuf = 0;
192
273
    Dwarf_Signed linecount = 0;
193
273
    Dwarf_Signed dir_count = 0;
194
273
    Dwarf_Addr prev_lineaddr = 0;
195
273
    Dwarf_Unsigned prev_lineno = 0;
196
273
    char *prev_linesrcfile = 0;
197
198
273
    sres = dwarf_srclines_files_indexes(line_context, &baseindex, &file_count,
199
273
                                        &endindex, errp);
200
273
    if (sres != DW_DLV_OK) {
201
0
      dwarf_srclines_dealloc_b(line_context);
202
0
      line_context = 0;
203
0
      return sres;
204
0
    }
205
21.5k
    for (i = baseindex; i < endindex; i++) {
206
21.2k
      Dwarf_Unsigned dirindexb = 0;
207
21.2k
      Dwarf_Unsigned modtime = 0;
208
21.2k
      Dwarf_Unsigned flength = 0;
209
21.2k
      Dwarf_Form_Data16 *md5data = 0;
210
21.2k
      int vres = 0;
211
21.2k
      const char *name = 0;
212
213
21.2k
      vres = dwarf_srclines_files_data_b(line_context, i, &name, &dirindexb,
214
21.2k
                                         &modtime, &flength, &md5data, errp);
215
21.2k
      if (vres != DW_DLV_OK) {
216
0
        dwarf_srclines_dealloc_b(line_context);
217
0
        line_context = 0;
218
0
        return vres;
219
0
      }
220
21.2k
    }
221
273
    sres = dwarf_srclines_include_dir_count(line_context, &dir_count, errp);
222
273
    if (sres != DW_DLV_OK) {
223
0
      dwarf_srclines_dealloc_b(line_context);
224
0
      line_context = 0;
225
0
      return sres;
226
0
    }
227
228
2.89k
    for (i = 1; i <= dir_count; ++i) {
229
2.61k
      dir_name = 0;
230
2.61k
      sres = dwarf_srclines_include_dir_data(line_context, i, &dir_name, errp);
231
2.61k
      if (sres == DW_DLV_ERROR) {
232
0
        dwarf_srclines_dealloc_b(line_context);
233
0
        line_context = 0;
234
0
        return sres;
235
0
      }
236
2.61k
    }
237
238
273
    sres = dwarf_srclines_from_linecontext(line_context, &linebuf, &linecount,
239
273
                                           errp);
240
273
    if (sres != DW_DLV_OK) {
241
0
      dwarf_srclines_dealloc_b(line_context);
242
0
      line_context = 0;
243
0
      return sres;
244
0
    }
245
322k
    for (i = 0; i < linecount; ++i) {
246
322k
      Dwarf_Addr lineaddr = 0;
247
322k
      Dwarf_Unsigned filenum = 0;
248
322k
      Dwarf_Unsigned lineno = 0;
249
322k
      char *linesrcfile = 0;
250
251
322k
      sres = dwarf_lineno(linebuf[i], &lineno, errp);
252
322k
      if (sres == DW_DLV_ERROR) {
253
0
        if (prev_linesrcfile) {
254
0
          dwarf_dealloc(dbg, prev_linesrcfile, DW_DLA_STRING);
255
0
        }
256
0
        return sres;
257
0
      }
258
322k
      sres = dwarf_line_srcfileno(linebuf[i], &filenum, errp);
259
322k
      if (sres == DW_DLV_ERROR) {
260
0
        if (prev_linesrcfile) {
261
0
          dwarf_dealloc(dbg, prev_linesrcfile, DW_DLA_STRING);
262
0
        }
263
0
        return sres;
264
0
      }
265
322k
      if (filenum) {
266
311k
        filenum -= 1;
267
311k
      }
268
322k
      sres = dwarf_lineaddr(linebuf[i], &lineaddr, errp);
269
322k
      if (sres == DW_DLV_ERROR) {
270
0
        if (prev_linesrcfile) {
271
0
          dwarf_dealloc(dbg, prev_linesrcfile, DW_DLA_STRING);
272
0
        }
273
0
        return sres;
274
0
      }
275
322k
      sres = dwarf_linesrc(linebuf[i], &linesrcfile, errp);
276
322k
      if (sres == DW_DLV_ERROR) {
277
119
        if (prev_linesrcfile) {
278
105
          dwarf_dealloc(dbg, prev_linesrcfile, DW_DLA_STRING);
279
105
        }
280
119
        return sres;
281
119
      }
282
321k
      if (lineaddr > td->td_target_pc) {
283
77
        td->td_subprog_lineaddr = prev_lineaddr;
284
77
        td->td_subprog_lineno = prev_lineno;
285
77
        td->td_subprog_srcfile = prev_linesrcfile;
286
77
        dwarf_dealloc(dbg, linesrcfile, DW_DLA_STRING);
287
77
        return DW_DLV_OK;
288
77
      }
289
321k
      prev_lineaddr = lineaddr;
290
321k
      prev_lineno = lineno;
291
321k
      if (prev_linesrcfile) {
292
311k
        dwarf_dealloc(dbg, prev_linesrcfile, DW_DLA_STRING);
293
311k
      }
294
321k
      prev_linesrcfile = linesrcfile;
295
321k
    }
296
77
    td->td_subprog_lineaddr = prev_lineaddr;
297
77
    td->td_subprog_lineno = prev_lineno;
298
77
    td->td_subprog_srcfile = prev_linesrcfile;
299
77
    dwarf_srclines_dealloc_b(line_context);
300
77
    return DW_DLV_OK;
301
273
  }
302
2
  return DW_DLV_ERROR;
303
286
}
304
305
static int look_for_our_target(Dwarf_Debug dbg, struct target_data_s *td,
306
11.7k
                               Dwarf_Error *errp) {
307
11.7k
  Dwarf_Unsigned cu_header_length = 0;
308
11.7k
  Dwarf_Unsigned abbrev_offset = 0;
309
11.7k
  Dwarf_Half address_size = 0;
310
11.7k
  Dwarf_Half version_stamp = 0;
311
11.7k
  Dwarf_Half offset_size = 0;
312
11.7k
  Dwarf_Half extension_size = 0;
313
11.7k
  Dwarf_Unsigned typeoffset = 0;
314
11.7k
  Dwarf_Half header_cu_type = unittype;
315
11.7k
  Dwarf_Bool is_info = g_is_info;
316
11.7k
  int cu_number = 0;
317
318
11.7k
  for (;; ++cu_number) {
319
11.7k
    Dwarf_Die no_die = 0;
320
11.7k
    Dwarf_Die cu_die = 0;
321
11.7k
    int res = DW_DLV_ERROR;
322
11.7k
    Dwarf_Sig8 signature;
323
324
11.7k
    memset(&signature, 0, sizeof(signature));
325
11.7k
    res = dwarf_next_cu_header_d(dbg, is_info, &cu_header_length,
326
11.7k
                                 &version_stamp, &abbrev_offset, &address_size,
327
11.7k
                                 &offset_size, &extension_size, &signature,
328
11.7k
                                 &typeoffset, 0, &header_cu_type, errp);
329
11.7k
    if (res == DW_DLV_ERROR) {
330
4.77k
      if (errp) {
331
4.77k
        char *em = dwarf_errmsg(*errp);
332
4.77k
      }
333
4.77k
      return DW_DLV_NO_ENTRY;
334
4.77k
    }
335
6.98k
    if (res == DW_DLV_NO_ENTRY) {
336
508
      return DW_DLV_NO_ENTRY;
337
508
    }
338
6.48k
    cu_version_stamp = version_stamp;
339
6.48k
    cu_offset_size = offset_size;
340
6.48k
    res = dwarf_siblingof_b(dbg, no_die, is_info, &cu_die, errp);
341
6.48k
    if (res == DW_DLV_ERROR) {
342
0
      if (errp) {
343
0
        char *em = dwarf_errmsg(*errp);
344
0
      }
345
0
      return res;
346
0
    }
347
6.48k
    if (res == DW_DLV_NO_ENTRY) {
348
502
      return res;
349
502
    }
350
351
5.97k
    td->td_cu_die = cu_die;
352
5.97k
    res = get_die_and_siblings(dbg, cu_die, is_info, 0, cu_number, td, errp);
353
5.97k
    if (res == FOUND_SUBPROG) {
354
1.34k
      read_line_data(dbg, td, errp);
355
1.34k
      if (td->td_reportallfound) {
356
0
        return res;
357
0
      }
358
1.34k
      return res;
359
4.63k
    } else if (res == IN_THIS_CU) {
360
0
      if (errp) {
361
0
          char *em = dwarf_errmsg(*errp);
362
0
      }
363
0
      return res;
364
4.63k
    } else if (res == DW_DLV_ERROR) {
365
2.20k
      if (errp) {
366
2.20k
        char *em = dwarf_errmsg(*errp);
367
2.20k
      }
368
2.20k
      return DW_DLV_ERROR;
369
2.20k
    }
370
2.43k
    return DW_DLV_NO_ENTRY;
371
5.97k
  }
372
11.7k
}
373
374
static int get_die_and_siblings(Dwarf_Debug dbg, Dwarf_Die in_die, int is_info,
375
                                int in_level, int cu_number,
376
255k
                                struct target_data_s *td, Dwarf_Error *errp) {
377
255k
  int res = DW_DLV_ERROR;
378
255k
  Dwarf_Die cur_die = in_die;
379
255k
  Dwarf_Die child = 0;
380
381
255k
  td->td_cu_number = cu_number;
382
255k
  res = examine_die_data(dbg, is_info, in_die, in_level, td, errp);
383
255k
  if (res == DW_DLV_ERROR) {
384
464
    return res;
385
464
  }
386
254k
  if (res == DW_DLV_NO_ENTRY) {
387
14.1k
    return res;
388
14.1k
  }
389
240k
  if (res == NOT_THIS_CU) {
390
19
    return res;
391
240k
  } else if (res == FOUND_SUBPROG) {
392
270
    return res;
393
240k
  } else {
394
240k
  }
395
396
9.27M
  for (;;) {
397
9.27M
    Dwarf_Die sib_die = 0;
398
9.27M
    res = dwarf_child(cur_die, &child, errp);
399
9.27M
    if (res == DW_DLV_ERROR) {
400
729
      return res;
401
729
    }
402
9.27M
    if (res == DW_DLV_OK) {
403
249k
      int res2 = 0;
404
405
249k
      res2 = get_die_and_siblings(dbg, child, is_info, in_level + 1, cu_number,
406
249k
                                  td, errp);
407
249k
      if (child != td->td_cu_die && child != td->td_subprog_die) {
408
236k
        dwarf_dealloc(dbg, child, DW_DLA_DIE);
409
236k
      }
410
249k
      if (res2 == FOUND_SUBPROG) {
411
3.26k
        return res2;
412
246k
      } else if (res2 == IN_THIS_CU) {
413
246k
      } else if (res2 == NOT_THIS_CU) {
414
260
        return res2;
415
245k
      } else if (res2 == DW_DLV_ERROR) {
416
47.0k
        return res2;
417
198k
      } else if (res2 == DW_DLV_NO_ENTRY) {
418
185k
      } else { /* DW_DLV_OK */
419
185k
      }
420
198k
      child = 0;
421
198k
    }
422
9.22M
    res = dwarf_siblingof_b(dbg, cur_die, is_info, &sib_die, errp);
423
9.22M
    if (res == DW_DLV_ERROR) {
424
901
      if (errp) {
425
901
          char *em = dwarf_errmsg(*errp);
426
901
      }
427
901
      return res;
428
901
    }
429
9.22M
    if (res == DW_DLV_NO_ENTRY) {
430
186k
      break;
431
186k
    }
432
9.03M
    if (cur_die != in_die) {
433
8.86M
      if (child != td->td_cu_die && child != td->td_subprog_die) {
434
2.99M
        dwarf_dealloc(dbg, cur_die, DW_DLA_DIE);
435
2.99M
      }
436
8.86M
      cur_die = 0;
437
8.86M
    }
438
9.03M
    cur_die = sib_die;
439
9.03M
    res = examine_die_data(dbg, is_info, cur_die, in_level, td, errp);
440
9.03M
    if (res == DW_DLV_ERROR) {
441
111
      return res;
442
9.03M
    } else if (res == DW_DLV_OK) {
443
8.97M
    } else if (res == FOUND_SUBPROG) {
444
1.07k
      return res;
445
63.5k
    } else if (res == NOT_THIS_CU) {
446
59.8k
    } else if (res == IN_THIS_CU) {
447
59.2k
    } else {
448
59.2k
    }
449
9.03M
  }
450
186k
  return DW_DLV_OK;
451
240k
}
452
453
static void dealloc_rest_of_list(Dwarf_Debug dbg, Dwarf_Attribute *attrbuf,
454
52.9k
                                 Dwarf_Signed attrcount, Dwarf_Signed i) {
455
319k
  for (; i < attrcount; ++i) {
456
266k
    dwarf_dealloc_attribute(attrbuf[i]);
457
266k
  }
458
52.9k
  dwarf_dealloc(dbg, attrbuf, DW_DLA_LIST);
459
52.9k
}
460
461
static int getlowhighpc(Dwarf_Die die, int *have_pc_range,
462
                        Dwarf_Addr *lowpc_out, Dwarf_Addr *highpc_out,
463
107k
                        Dwarf_Error *error) {
464
107k
  Dwarf_Addr hipc = 0;
465
107k
  int res = 0;
466
107k
  Dwarf_Half form = 0;
467
107k
  enum Dwarf_Form_Class formclass = 0;
468
469
107k
  *have_pc_range = FALSE;
470
107k
  res = dwarf_lowpc(die, lowpc_out, error);
471
107k
  if (res == DW_DLV_OK) {
472
57.4k
    res = dwarf_highpc_b(die, &hipc, &form, &formclass, error);
473
57.4k
    if (res == DW_DLV_OK) {
474
52.4k
      if (formclass == DW_FORM_CLASS_CONSTANT) {
475
18.4k
        hipc += *lowpc_out;
476
18.4k
      }
477
52.4k
      *highpc_out = hipc;
478
52.4k
      *have_pc_range = TRUE;
479
52.4k
      return DW_DLV_OK;
480
52.4k
    }
481
57.4k
  }
482
54.6k
  return DW_DLV_NO_ENTRY;
483
107k
}
484
485
static int check_subprog_ranges_for_match(Dwarf_Debug dbg, Dwarf_Die die,
486
                                          struct target_data_s *td,
487
                                          int *have_pc_range,
488
                                          Dwarf_Addr *lowpc_out,
489
                                          Dwarf_Addr *highpc_out,
490
6.91k
                                          Dwarf_Error *errp) {
491
6.91k
  int res = 0;
492
6.91k
  Dwarf_Ranges *ranges;
493
6.91k
  Dwarf_Signed ranges_count;
494
6.91k
  Dwarf_Unsigned byte_count;
495
6.91k
  Dwarf_Signed i = 0;
496
6.91k
  Dwarf_Addr baseaddr = 0;
497
6.91k
  Dwarf_Off actualoffset = 0;
498
6.91k
  int done = FALSE;
499
500
6.91k
  res = dwarf_get_ranges_b(dbg, td->td_ranges_offset, die, &actualoffset,
501
6.91k
                           &ranges, &ranges_count, &byte_count, errp);
502
6.91k
  if (res != DW_DLV_OK) {
503
5.88k
    return res;
504
5.88k
  }
505
30.5k
  for (i = 0; i < ranges_count && !done; ++i) {
506
29.5k
    Dwarf_Ranges *cur = ranges + i;
507
29.5k
    Dwarf_Addr lowpc = 0;
508
29.5k
    Dwarf_Addr highpc = 0;
509
29.5k
    switch (cur->dwr_type) {
510
27.8k
    case DW_RANGES_ENTRY:
511
27.8k
      lowpc = cur->dwr_addr1 + baseaddr;
512
27.8k
      highpc = cur->dwr_addr2 + baseaddr;
513
27.8k
      if (td->td_target_pc < lowpc || td->td_target_pc >= highpc) {
514
27.7k
        break;
515
27.7k
      }
516
114
      *lowpc_out = lowpc;
517
114
      *highpc_out = highpc;
518
114
      *have_pc_range = TRUE;
519
114
      done = TRUE;
520
114
      res = FOUND_SUBPROG;
521
114
      break;
522
1.16k
    case DW_RANGES_ADDRESS_SELECTION:
523
1.16k
      baseaddr = cur->dwr_addr2;
524
1.16k
      break;
525
556
    case DW_RANGES_END:
526
556
      break;
527
0
    default:
528
0
      return DW_DLV_ERROR;
529
29.5k
    }
530
29.5k
  }
531
1.03k
  dwarf_dealloc_ranges(dbg, ranges, ranges_count);
532
1.03k
  return res;
533
1.03k
}
534
535
static int get_name_from_abstract_origin(Dwarf_Debug dbg, int is_info,
536
                                         Dwarf_Die die, char **name,
537
43.3k
                                         Dwarf_Error *errp) {
538
43.3k
  int res = 0;
539
43.3k
  Dwarf_Die abrootdie = 0;
540
43.3k
  Dwarf_Attribute ab_attr = 0;
541
43.3k
  Dwarf_Off ab_offset = 0;
542
543
43.3k
  res = dwarf_attr(die, DW_AT_abstract_origin, &ab_attr, errp);
544
43.3k
  if (res != DW_DLV_OK) {
545
1.87k
    return res;
546
1.87k
  }
547
548
41.4k
  res = dwarf_global_formref(ab_attr, &ab_offset, errp);
549
41.4k
  if (res != DW_DLV_OK) {
550
13.0k
    dwarf_dealloc(dbg, ab_attr, DW_DLA_ATTR);
551
13.0k
    return res;
552
13.0k
  }
553
554
28.3k
  dwarf_dealloc(dbg, ab_attr, DW_DLA_ATTR);
555
28.3k
  res = dwarf_offdie_b(dbg, ab_offset, is_info, &abrootdie, errp);
556
28.3k
  if (res != DW_DLV_OK) {
557
21.1k
    return res;
558
21.1k
  }
559
7.29k
  res = dwarf_diename(abrootdie, name, errp);
560
7.29k
  dwarf_dealloc_die(abrootdie);
561
7.29k
  return res;
562
28.3k
}
563
564
static int check_subprog_details(Dwarf_Debug dbg, int is_info, Dwarf_Die die,
565
                                 struct target_data_s *td,
566
                                 int *have_pc_range_out, Dwarf_Addr *lowpc_out,
567
95.2k
                                 Dwarf_Addr *highpc_out, Dwarf_Error *errp) {
568
95.2k
  int res = 0;
569
95.2k
  Dwarf_Addr lowpc = 0;
570
95.2k
  Dwarf_Addr highpc = 0;
571
95.2k
  int finalres = 0;
572
95.2k
  int have_pc_range = FALSE;
573
574
95.2k
  res = getlowhighpc(die, &have_pc_range, &lowpc, &highpc, errp);
575
95.2k
  if (res == DW_DLV_OK) {
576
50.6k
    if (have_pc_range) {
577
50.6k
      int res2 = DW_DLV_OK;
578
50.6k
      char *name = 0;
579
580
50.6k
      if (td->td_target_pc < lowpc || td->td_target_pc >= highpc) {
581
6.52k
        finalres = DW_DLV_OK;
582
44.1k
      } else {
583
44.1k
        td->td_subprog_die = die;
584
44.1k
        td->td_subprog_lowpc = lowpc;
585
44.1k
        *lowpc_out = lowpc;
586
44.1k
        *highpc_out = highpc;
587
44.1k
        *have_pc_range_out = have_pc_range;
588
44.1k
        td->td_subprog_highpc = highpc;
589
44.1k
        td->td_subprog_haslowhighpc = have_pc_range;
590
44.1k
        res2 = dwarf_diename(die, &name, errp);
591
44.1k
        if (res2 == DW_DLV_OK) {
592
801
          td->td_subprog_name = name;
593
43.3k
        } else {
594
43.3k
          get_name_from_abstract_origin(dbg, is_info, die, &name, errp);
595
43.3k
        }
596
44.1k
        td->td_subprog_name = name;
597
44.1k
        name = 0;
598
44.1k
        finalres = FOUND_SUBPROG;
599
44.1k
      }
600
50.6k
    }
601
50.6k
  }
602
95.2k
  {
603
95.2k
    Dwarf_Signed i = 0;
604
95.2k
    Dwarf_Signed atcount = 0;
605
95.2k
    Dwarf_Attribute *atlist = 0;
606
607
95.2k
    res = dwarf_attrlist(die, &atlist, &atcount, errp);
608
95.2k
    if (res != DW_DLV_OK) {
609
11.5k
      return res;
610
11.5k
    }
611
248k
    for (i = 0; i < atcount; ++i) {
612
217k
      Dwarf_Half atr = 0;
613
217k
      Dwarf_Attribute attrib = atlist[i];
614
615
217k
      res = dwarf_whatattr(attrib, &atr, errp);
616
217k
      if (res != DW_DLV_OK) {
617
0
        dealloc_rest_of_list(dbg, atlist, atcount, i);
618
0
        return res;
619
0
      }
620
217k
      if (atr == DW_AT_ranges) {
621
59.7k
        int res2 = 0;
622
59.7k
        int res4 = 0;
623
59.7k
        Dwarf_Off ret_offset = 0;
624
59.7k
        int has_low_hi = FALSE;
625
59.7k
        Dwarf_Addr low = 0;
626
59.7k
        Dwarf_Addr high = 0;
627
628
59.7k
        res2 = dwarf_global_formref(attrib, &ret_offset, errp);
629
59.7k
        if (res2 != DW_DLV_OK) {
630
52.8k
          dealloc_rest_of_list(dbg, atlist, atcount, i);
631
52.8k
          return res2;
632
52.8k
        }
633
6.91k
        td->td_ranges_offset = ret_offset + td->td_cu_ranges_base;
634
6.91k
        res4 = check_subprog_ranges_for_match(dbg, die, td, &has_low_hi, &low,
635
6.91k
                                              &high, errp);
636
6.91k
        if (res4 == DW_DLV_OK) {
637
918
          continue;
638
918
        }
639
5.99k
        if (res4 == DW_DLV_NO_ENTRY) {
640
5.83k
          continue;
641
5.83k
        }
642
162
        if (res4 == FOUND_SUBPROG) {
643
114
          td->td_subprog_lowpc = lowpc;
644
114
          td->td_subprog_highpc = highpc;
645
114
          td->td_subprog_haslowhighpc = has_low_hi;
646
114
          finalres = FOUND_SUBPROG;
647
114
          continue;
648
114
        }
649
48
        dealloc_rest_of_list(dbg, atlist, atcount, i);
650
48
        return res4;
651
157k
      } else if (atr == DW_AT_decl_file) {
652
5.74k
        int res5 = 0;
653
5.74k
        Dwarf_Unsigned file_index = 0;
654
655
5.74k
        res5 = dwarf_formudata(attrib, &file_index, errp);
656
5.74k
        if (res5 != DW_DLV_OK) {
657
22
          dealloc_rest_of_list(dbg, atlist, atcount, i);
658
22
          return res5;
659
22
        }
660
5.72k
        td->td_subprog_fileindex = file_index;
661
5.72k
      }
662
157k
      dwarf_dealloc(dbg, attrib, DW_DLA_ATTR);
663
157k
    }
664
30.8k
    dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
665
30.8k
  }
666
0
  return finalres;
667
83.7k
}
668
669
static int check_comp_dir(Dwarf_Debug dbg, Dwarf_Die die,
670
11.8k
                          struct target_data_s *td, Dwarf_Error *errp) {
671
11.8k
  int res = 0;
672
11.8k
  int finalres = DW_DLV_NO_ENTRY;
673
11.8k
  int have_pc_range = FALSE;
674
11.8k
  Dwarf_Addr lowpc = 0;
675
11.8k
  Dwarf_Addr highpc = 0;
676
11.8k
  Dwarf_Off real_ranges_offset = 0;
677
11.8k
  int rdone = FALSE;
678
679
11.8k
  res = getlowhighpc(die, &have_pc_range, &lowpc, &highpc, errp);
680
11.8k
  if (res == DW_DLV_OK) {
681
1.77k
    if (have_pc_range) {
682
1.77k
      if (td->td_target_pc < lowpc || td->td_target_pc >= highpc) {
683
475
        res = NOT_THIS_CU;
684
1.29k
      } else {
685
1.29k
        td->td_cu_lowpc = lowpc;
686
1.29k
        td->td_cu_highpc = highpc;
687
1.29k
        res = IN_THIS_CU;
688
1.29k
      }
689
1.77k
    }
690
1.77k
  }
691
11.8k
  finalres = res;
692
11.8k
  {
693
11.8k
    Dwarf_Signed atcount = 0;
694
11.8k
    Dwarf_Attribute *atlist = 0;
695
11.8k
    Dwarf_Signed j = 0;
696
11.8k
    int alres = 0;
697
698
11.8k
    alres = dwarf_attrlist(die, &atlist, &atcount, errp);
699
11.8k
    if (alres != DW_DLV_OK) {
700
285
      return alres;
701
285
    }
702
65.9k
    for (j = 0; j < atcount; ++j) {
703
54.6k
      Dwarf_Half atr = 0;
704
54.6k
      Dwarf_Attribute attrib = atlist[j];
705
54.6k
      int resb = 0;
706
707
54.6k
      resb = dwarf_whatattr(attrib, &atr, errp);
708
54.6k
      if (resb != DW_DLV_OK) {
709
0
        dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
710
0
        return resb;
711
0
      }
712
54.6k
      if (atr == DW_AT_name) {
713
10.0k
        char *name = 0;
714
10.0k
        resb = dwarf_formstring(attrib, &name, errp);
715
10.0k
        if (resb == DW_DLV_OK) {
716
333
          td->td_cu_name = name;
717
333
        }
718
44.6k
      } else if (atr == DW_AT_comp_dir) {
719
5.41k
        char *name = 0;
720
5.41k
        resb = dwarf_formstring(attrib, &name, errp);
721
5.41k
        if (resb == DW_DLV_OK) {
722
299
          td->td_cu_comp_dir = name;
723
299
        }
724
39.2k
      } else if (atr == DW_AT_rnglists_base || atr == DW_AT_GNU_ranges_base) {
725
1.10k
        Dwarf_Off rbase = 0;
726
727
1.10k
        resb = dwarf_global_formref(attrib, &rbase, errp);
728
1.10k
        if (resb != DW_DLV_OK) {
729
154
          dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
730
154
          return resb;
731
154
        }
732
948
        td->td_cu_ranges_base = rbase;
733
38.1k
      } else if (atr == DW_AT_ranges) {
734
        /* we have actual ranges. */
735
1.97k
        Dwarf_Off rbase = 0;
736
737
1.97k
        resb = dwarf_global_formref(attrib, &rbase, errp);
738
1.97k
        if (resb != DW_DLV_OK) {
739
79
          dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
740
79
          return resb;
741
79
        }
742
1.89k
        real_ranges_offset = rbase;
743
1.89k
        rdone = TRUE;
744
1.89k
      }
745
54.4k
      dwarf_dealloc(dbg, attrib, DW_DLA_ATTR);
746
54.4k
    }
747
11.2k
    dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
748
11.2k
  }
749
11.2k
  if (rdone) {
750
1.88k
    int resr = 0;
751
1.88k
    Dwarf_Ranges *ranges = 0;
752
1.88k
    Dwarf_Signed ranges_count = 0;
753
1.88k
    Dwarf_Unsigned byte_count = 0;
754
1.88k
    Dwarf_Off actualoffset = 0;
755
1.88k
    Dwarf_Signed k = 0;
756
1.88k
    int done = FALSE;
757
758
1.88k
    resr = dwarf_get_ranges_b(dbg, real_ranges_offset, die, &actualoffset,
759
1.88k
                              &ranges, &ranges_count, &byte_count, errp);
760
1.88k
    if (resr != DW_DLV_OK) {
761
1.00k
      return res;
762
1.00k
    }
763
30.3k
    for (k = 0; k < ranges_count && !done; ++k) {
764
29.4k
      Dwarf_Ranges *cur = ranges + k;
765
29.4k
      Dwarf_Addr lowpcr = 0;
766
29.4k
      Dwarf_Addr highpcr = 0;
767
29.4k
      Dwarf_Addr baseaddr = td->td_cu_ranges_base;
768
769
29.4k
      switch (cur->dwr_type) {
770
28.6k
      case DW_RANGES_ENTRY:
771
28.6k
        lowpc = cur->dwr_addr1 + baseaddr;
772
28.6k
        highpc = cur->dwr_addr2 + baseaddr;
773
28.6k
        if (td->td_target_pc < lowpc || td->td_target_pc >= highpc) {
774
28.1k
          break;
775
28.1k
        }
776
525
        td->td_cu_lowpc = lowpcr;
777
525
        td->td_cu_highpc = highpcr;
778
525
        td->td_cu_haslowhighpc = TRUE;
779
525
        done = TRUE;
780
525
        finalres = IN_THIS_CU;
781
525
        break;
782
463
      case DW_RANGES_ADDRESS_SELECTION:
783
463
        baseaddr = cur->dwr_addr2;
784
463
        break;
785
330
      case DW_RANGES_END:
786
330
        break;
787
0
      default:
788
0
        return DW_DLV_ERROR;
789
29.4k
      }
790
29.4k
    }
791
881
    dwarf_dealloc_ranges(dbg, ranges, ranges_count);
792
881
  }
793
10.2k
  return finalres;
794
11.2k
}
795
796
static int examine_die_data(Dwarf_Debug dbg, int is_info, Dwarf_Die die,
797
                            int level, struct target_data_s *td,
798
9.29M
                            Dwarf_Error *errp) {
799
9.29M
  Dwarf_Half tag = 0;
800
9.29M
  int res = 0;
801
802
9.29M
  res = dwarf_tag(die, &tag, errp);
803
9.29M
  if (res != DW_DLV_OK) {
804
0
    return res;
805
0
  }
806
9.29M
  if (tag == DW_TAG_subprogram || tag == DW_TAG_inlined_subroutine) {
807
95.2k
    int have_pc_range = 0;
808
95.2k
    Dwarf_Addr lowpc = 0;
809
95.2k
    Dwarf_Addr highpc = 0;
810
811
95.2k
    res = check_subprog_details(dbg, is_info, die, td, &have_pc_range, &lowpc,
812
95.2k
                                &highpc, errp);
813
95.2k
    if (res == FOUND_SUBPROG) {
814
1.34k
      td->td_subprog_die = die;
815
1.34k
      return res;
816
93.9k
    } else if (res == DW_DLV_ERROR) {
817
442
      return res;
818
93.4k
    } else if (res == DW_DLV_NO_ENTRY) {
819
      /* impossible? */
820
64.0k
      return res;
821
64.0k
    } else if (res == NOT_THIS_CU) {
822
      /* impossible */
823
0
      return res;
824
29.4k
    } else if (res == IN_THIS_CU) {
825
      /* impossible */
826
0
      return res;
827
29.4k
    } else {
828
      /* DW_DLV_OK */
829
29.4k
    }
830
29.4k
    return DW_DLV_OK;
831
9.19M
  } else if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit ||
832
9.18M
             tag == DW_TAG_type_unit) {
833
834
15.0k
    if (level) {
835
3.23k
      return NOT_THIS_CU;
836
3.23k
    }
837
11.8k
    res = check_comp_dir(dbg, die, td, errp);
838
11.8k
    return res;
839
15.0k
  }
840
9.18M
  return DW_DLV_OK;
841
9.29M
}