Coverage Report

Created: 2025-11-16 06:51

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
73.9k
#define TRUE 1
32
342k
#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
9.99M
#define NOT_THIS_CU 10
73
392k
#define IN_THIS_CU 11
74
5.47M
#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
15.3k
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
95
15.3k
  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
15.3k
  sprintf(filename, "/tmp/libfuzzer.%d", getpid());
105
15.3k
#endif
106
15.3k
  FILE *fp = fopen(filename, "wb");
107
15.3k
  if (!fp) {
108
0
    printf("FAIL libfuzzer cannot open temp as writeable %s\n",
109
0
        filename);
110
0
    return 0;
111
0
  }
112
15.3k
  fwrite(data, size, 1, fp);
113
15.3k
  fclose(fp);
114
115
15.3k
  Dwarf_Debug dbg = 0;
116
15.3k
  Dwarf_Error error = 0;
117
15.3k
  Dwarf_Handler errhand = 0;
118
15.3k
  Dwarf_Ptr errarg = 0;
119
15.3k
  int i = 0;
120
15.3k
  Dwarf_Unsigned target_pc = 0x1000;
121
15.3k
#define PATH_LEN 2000
122
15.3k
  char real_path[PATH_LEN];
123
15.3k
  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
15.3k
  memset(&target_data,0,sizeof(target_data));
129
15.3k
  int res =
130
15.3k
      dwarf_init_path(filename, 0, 0, DW_GROUPNUMBER_ANY, 0, 0, &dbg, &error);
131
15.3k
  if (res == DW_DLV_ERROR) {
132
5.03k
    dwarf_dealloc_error(dbg, error);
133
5.03k
    dwarf_finish(dbg);
134
10.3k
  } else {
135
10.3k
    res = look_for_our_target(dbg, &target_data, &error);
136
10.3k
    res = dwarf_finish(dbg);
137
10.3k
  }
138
139
15.3k
  unlink(filename);
140
15.3k
  return 0;
141
15.3k
}
142
143
static int read_line_data(Dwarf_Debug dbg, struct target_data_s *td,
144
1.24k
                          Dwarf_Error *errp) {
145
1.24k
  int res = 0;
146
1.24k
  Dwarf_Unsigned line_version = 0;
147
1.24k
  Dwarf_Small table_type = 0;
148
1.24k
  Dwarf_Line_Context line_context = 0;
149
1.24k
  Dwarf_Signed i = 0;
150
1.24k
  Dwarf_Signed baseindex = 0;
151
1.24k
  Dwarf_Signed endindex = 0;
152
1.24k
  Dwarf_Signed file_count = 0;
153
1.24k
  Dwarf_Unsigned dirindex = 0;
154
155
1.24k
  (void)dbg;
156
1.24k
  res = dwarf_srclines_b(td->td_cu_die, &line_version, &table_type,
157
1.24k
                         &line_context, errp);
158
1.24k
  if (res != DW_DLV_OK) {
159
940
    return res;
160
940
  }
161
304
  if (table_type == 0) {
162
9
    int sres = 0;
163
164
9
    sres = dwarf_srclines_files_indexes(line_context, &baseindex, &file_count,
165
9
                                        &endindex, errp);
166
9
    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
100
    for (i = baseindex; i < endindex; i++) {
172
91
      Dwarf_Unsigned modtime = 0;
173
91
      Dwarf_Unsigned flength = 0;
174
91
      Dwarf_Form_Data16 *md5data = 0;
175
91
      int vres = 0;
176
91
      const char *name = 0;
177
178
91
      vres = dwarf_srclines_files_data_b(line_context, i, &name, &dirindex,
179
91
                                         &modtime, &flength, &md5data, errp);
180
91
      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
91
    }
186
9
    dwarf_srclines_dealloc_b(line_context);
187
9
    return DW_DLV_OK;
188
295
  } else if (table_type == 1) {
189
294
    const char *dir_name = 0;
190
294
    int sres = 0;
191
294
    Dwarf_Line *linebuf = 0;
192
294
    Dwarf_Signed linecount = 0;
193
294
    Dwarf_Signed dir_count = 0;
194
294
    Dwarf_Addr prev_lineaddr = 0;
195
294
    Dwarf_Unsigned prev_lineno = 0;
196
294
    char *prev_linesrcfile = 0;
197
198
294
    sres = dwarf_srclines_files_indexes(line_context, &baseindex, &file_count,
199
294
                                        &endindex, errp);
200
294
    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
17.6k
    for (i = baseindex; i < endindex; i++) {
206
17.3k
      Dwarf_Unsigned dirindexb = 0;
207
17.3k
      Dwarf_Unsigned modtime = 0;
208
17.3k
      Dwarf_Unsigned flength = 0;
209
17.3k
      Dwarf_Form_Data16 *md5data = 0;
210
17.3k
      int vres = 0;
211
17.3k
      const char *name = 0;
212
213
17.3k
      vres = dwarf_srclines_files_data_b(line_context, i, &name, &dirindexb,
214
17.3k
                                         &modtime, &flength, &md5data, errp);
215
17.3k
      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
17.3k
    }
221
294
    sres = dwarf_srclines_include_dir_count(line_context, &dir_count, errp);
222
294
    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
3.42k
    for (i = 1; i <= dir_count; ++i) {
229
3.12k
      dir_name = 0;
230
3.12k
      sres = dwarf_srclines_include_dir_data(line_context, i, &dir_name, errp);
231
3.12k
      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
3.12k
    }
237
238
294
    sres = dwarf_srclines_from_linecontext(line_context, &linebuf, &linecount,
239
294
                                           errp);
240
294
    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
290k
    for (i = 0; i < linecount; ++i) {
246
290k
      Dwarf_Addr lineaddr = 0;
247
290k
      Dwarf_Unsigned filenum = 0;
248
290k
      Dwarf_Unsigned lineno = 0;
249
290k
      char *linesrcfile = 0;
250
251
290k
      sres = dwarf_lineno(linebuf[i], &lineno, errp);
252
290k
      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
290k
      sres = dwarf_line_srcfileno(linebuf[i], &filenum, errp);
259
290k
      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
290k
      if (filenum) {
266
279k
        filenum -= 1;
267
279k
      }
268
290k
      sres = dwarf_lineaddr(linebuf[i], &lineaddr, errp);
269
290k
      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
290k
      sres = dwarf_linesrc(linebuf[i], &linesrcfile, errp);
276
290k
      if (sres == DW_DLV_ERROR) {
277
151
        if (prev_linesrcfile) {
278
129
          dwarf_dealloc(dbg, prev_linesrcfile, DW_DLA_STRING);
279
129
        }
280
151
        return sres;
281
151
      }
282
290k
      if (lineaddr > td->td_target_pc) {
283
85
        td->td_subprog_lineaddr = prev_lineaddr;
284
85
        td->td_subprog_lineno = prev_lineno;
285
85
        td->td_subprog_srcfile = prev_linesrcfile;
286
85
        dwarf_dealloc(dbg, linesrcfile, DW_DLA_STRING);
287
85
        return DW_DLV_OK;
288
85
      }
289
290k
      prev_lineaddr = lineaddr;
290
290k
      prev_lineno = lineno;
291
290k
      if (prev_linesrcfile) {
292
278k
        dwarf_dealloc(dbg, prev_linesrcfile, DW_DLA_STRING);
293
278k
      }
294
290k
      prev_linesrcfile = linesrcfile;
295
290k
    }
296
58
    td->td_subprog_lineaddr = prev_lineaddr;
297
58
    td->td_subprog_lineno = prev_lineno;
298
58
    td->td_subprog_srcfile = prev_linesrcfile;
299
58
    dwarf_srclines_dealloc_b(line_context);
300
58
    return DW_DLV_OK;
301
294
  }
302
1
  return DW_DLV_ERROR;
303
304
}
304
305
static int look_for_our_target(Dwarf_Debug dbg, struct target_data_s *td,
306
10.3k
                               Dwarf_Error *errp) {
307
10.3k
  Dwarf_Unsigned cu_header_length = 0;
308
10.3k
  Dwarf_Unsigned abbrev_offset = 0;
309
10.3k
  Dwarf_Half address_size = 0;
310
10.3k
  Dwarf_Half version_stamp = 0;
311
10.3k
  Dwarf_Half offset_size = 0;
312
10.3k
  Dwarf_Half extension_size = 0;
313
10.3k
  Dwarf_Unsigned typeoffset = 0;
314
10.3k
  Dwarf_Half header_cu_type = unittype;
315
10.3k
  Dwarf_Bool is_info = g_is_info;
316
10.3k
  int cu_number = 0;
317
318
10.3k
  for (;; ++cu_number) {
319
10.3k
    Dwarf_Die no_die = 0;
320
10.3k
    Dwarf_Die cu_die = 0;
321
10.3k
    int res = DW_DLV_ERROR;
322
10.3k
    Dwarf_Sig8 signature;
323
324
10.3k
    memset(&signature, 0, sizeof(signature));
325
10.3k
    res = dwarf_next_cu_header_d(dbg, is_info, &cu_header_length,
326
10.3k
                                 &version_stamp, &abbrev_offset, &address_size,
327
10.3k
                                 &offset_size, &extension_size, &signature,
328
10.3k
                                 &typeoffset, 0, &header_cu_type, errp);
329
10.3k
    if (res == DW_DLV_ERROR) {
330
3.84k
      if (errp) {
331
3.84k
        char *em = dwarf_errmsg(*errp);
332
3.84k
      }
333
3.84k
      return DW_DLV_NO_ENTRY;
334
3.84k
    }
335
6.50k
    if (res == DW_DLV_NO_ENTRY) {
336
608
      return DW_DLV_NO_ENTRY;
337
608
    }
338
5.89k
    cu_version_stamp = version_stamp;
339
5.89k
    cu_offset_size = offset_size;
340
5.89k
    res = dwarf_siblingof_b(dbg, no_die, is_info, &cu_die, errp);
341
5.89k
    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
5.89k
    if (res == DW_DLV_NO_ENTRY) {
348
355
      return res;
349
355
    }
350
351
5.53k
    td->td_cu_die = cu_die;
352
5.53k
    res = get_die_and_siblings(dbg, cu_die, is_info, 0, cu_number, td, errp);
353
5.53k
    if (res == FOUND_SUBPROG) {
354
1.24k
      read_line_data(dbg, td, errp);
355
1.24k
      if (td->td_reportallfound) {
356
0
        return res;
357
0
      }
358
1.24k
      return res;
359
4.29k
    } 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.29k
    } else if (res == DW_DLV_ERROR) {
365
2.26k
      if (errp) {
366
2.26k
        char *em = dwarf_errmsg(*errp);
367
2.26k
      }
368
2.26k
      return DW_DLV_ERROR;
369
2.26k
    }
370
2.02k
    return DW_DLV_NO_ENTRY;
371
5.53k
  }
372
10.3k
}
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
289k
                                struct target_data_s *td, Dwarf_Error *errp) {
377
289k
  int res = DW_DLV_ERROR;
378
289k
  Dwarf_Die cur_die = in_die;
379
289k
  Dwarf_Die child = 0;
380
381
289k
  td->td_cu_number = cu_number;
382
289k
  res = examine_die_data(dbg, is_info, in_die, in_level, td, errp);
383
289k
  if (res == DW_DLV_ERROR) {
384
453
    return res;
385
453
  }
386
288k
  if (res == DW_DLV_NO_ENTRY) {
387
8.05k
    return res;
388
8.05k
  }
389
280k
  if (res == NOT_THIS_CU) {
390
71
    return res;
391
280k
  } else if (res == FOUND_SUBPROG) {
392
216
    return res;
393
280k
  } else {
394
280k
  }
395
396
9.89M
  for (;;) {
397
9.89M
    Dwarf_Die sib_die = 0;
398
9.89M
    res = dwarf_child(cur_die, &child, errp);
399
9.89M
    if (res == DW_DLV_ERROR) {
400
562
      return res;
401
562
    }
402
9.89M
    if (res == DW_DLV_OK) {
403
283k
      int res2 = 0;
404
405
283k
      res2 = get_die_and_siblings(dbg, child, is_info, in_level + 1, cu_number,
406
283k
                                  td, errp);
407
283k
      if (child != td->td_cu_die && child != td->td_subprog_die) {
408
277k
        dwarf_dealloc(dbg, child, DW_DLA_DIE);
409
277k
      }
410
283k
      if (res2 == FOUND_SUBPROG) {
411
2.85k
        return res2;
412
280k
      } else if (res2 == IN_THIS_CU) {
413
280k
      } else if (res2 == NOT_THIS_CU) {
414
3.31k
        return res2;
415
277k
      } else if (res2 == DW_DLV_ERROR) {
416
56.4k
        return res2;
417
220k
      } else if (res2 == DW_DLV_NO_ENTRY) {
418
213k
      } else { /* DW_DLV_OK */
419
213k
      }
420
220k
      child = 0;
421
220k
    }
422
9.83M
    res = dwarf_siblingof_b(dbg, cur_die, is_info, &sib_die, errp);
423
9.83M
    if (res == DW_DLV_ERROR) {
424
999
      if (errp) {
425
999
          char *em = dwarf_errmsg(*errp);
426
999
      }
427
999
      return res;
428
999
    }
429
9.83M
    if (res == DW_DLV_NO_ENTRY) {
430
214k
      break;
431
214k
    }
432
9.61M
    if (cur_die != in_die) {
433
9.41M
      if (child != td->td_cu_die && child != td->td_subprog_die) {
434
3.80M
        dwarf_dealloc(dbg, cur_die, DW_DLA_DIE);
435
3.80M
      }
436
9.41M
      cur_die = 0;
437
9.41M
    }
438
9.61M
    cur_die = sib_die;
439
9.61M
    res = examine_die_data(dbg, is_info, cur_die, in_level, td, errp);
440
9.61M
    if (res == DW_DLV_ERROR) {
441
252
      return res;
442
9.61M
    } else if (res == DW_DLV_OK) {
443
4.86M
    } else if (res == FOUND_SUBPROG) {
444
1.02k
      return res;
445
4.74M
    } else if (res == NOT_THIS_CU) {
446
4.66M
    } else if (res == IN_THIS_CU) {
447
83.4k
    } else {
448
83.4k
    }
449
9.61M
  }
450
214k
  return DW_DLV_OK;
451
280k
}
452
453
static void dealloc_rest_of_list(Dwarf_Debug dbg, Dwarf_Attribute *attrbuf,
454
78.1k
                                 Dwarf_Signed attrcount, Dwarf_Signed i) {
455
426k
  for (; i < attrcount; ++i) {
456
348k
    dwarf_dealloc_attribute(attrbuf[i]);
457
348k
  }
458
78.1k
  dwarf_dealloc(dbg, attrbuf, DW_DLA_LIST);
459
78.1k
}
460
461
static int getlowhighpc(Dwarf_Die die, int *have_pc_range,
462
                        Dwarf_Addr *lowpc_out, Dwarf_Addr *highpc_out,
463
118k
                        Dwarf_Error *error) {
464
118k
  Dwarf_Addr hipc = 0;
465
118k
  int res = 0;
466
118k
  Dwarf_Half form = 0;
467
118k
  enum Dwarf_Form_Class formclass = 0;
468
469
118k
  *have_pc_range = FALSE;
470
118k
  res = dwarf_lowpc(die, lowpc_out, error);
471
118k
  if (res == DW_DLV_OK) {
472
82.8k
    res = dwarf_highpc_b(die, &hipc, &form, &formclass, error);
473
82.8k
    if (res == DW_DLV_OK) {
474
71.5k
      if (formclass == DW_FORM_CLASS_CONSTANT) {
475
8.49k
        hipc += *lowpc_out;
476
8.49k
      }
477
71.5k
      *highpc_out = hipc;
478
71.5k
      *have_pc_range = TRUE;
479
71.5k
      return DW_DLV_OK;
480
71.5k
    }
481
82.8k
  }
482
46.5k
  return DW_DLV_NO_ENTRY;
483
118k
}
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.42k
                                          Dwarf_Error *errp) {
491
6.42k
  int res = 0;
492
6.42k
  Dwarf_Ranges *ranges;
493
6.42k
  Dwarf_Signed ranges_count;
494
6.42k
  Dwarf_Unsigned byte_count;
495
6.42k
  Dwarf_Signed i = 0;
496
6.42k
  Dwarf_Addr baseaddr = 0;
497
6.42k
  Dwarf_Off actualoffset = 0;
498
6.42k
  int done = FALSE;
499
500
6.42k
  res = dwarf_get_ranges_b(dbg, td->td_ranges_offset, die, &actualoffset,
501
6.42k
                           &ranges, &ranges_count, &byte_count, errp);
502
6.42k
  if (res != DW_DLV_OK) {
503
5.92k
    return res;
504
5.92k
  }
505
6.24k
  for (i = 0; i < ranges_count && !done; ++i) {
506
5.73k
    Dwarf_Ranges *cur = ranges + i;
507
5.73k
    Dwarf_Addr lowpc = 0;
508
5.73k
    Dwarf_Addr highpc = 0;
509
5.73k
    switch (cur->dwr_type) {
510
5.10k
    case DW_RANGES_ENTRY:
511
5.10k
      lowpc = cur->dwr_addr1 + baseaddr;
512
5.10k
      highpc = cur->dwr_addr2 + baseaddr;
513
5.10k
      if (td->td_target_pc < lowpc || td->td_target_pc >= highpc) {
514
5.03k
        break;
515
5.03k
      }
516
70
      *lowpc_out = lowpc;
517
70
      *highpc_out = highpc;
518
70
      *have_pc_range = TRUE;
519
70
      done = TRUE;
520
70
      res = FOUND_SUBPROG;
521
70
      break;
522
336
    case DW_RANGES_ADDRESS_SELECTION:
523
336
      baseaddr = cur->dwr_addr2;
524
336
      break;
525
297
    case DW_RANGES_END:
526
297
      break;
527
0
    default:
528
0
      return DW_DLV_ERROR;
529
5.73k
    }
530
5.73k
  }
531
501
  dwarf_dealloc_ranges(dbg, ranges, ranges_count);
532
501
  return res;
533
501
}
534
535
static int get_name_from_abstract_origin(Dwarf_Debug dbg, int is_info,
536
                                         Dwarf_Die die, char **name,
537
53.9k
                                         Dwarf_Error *errp) {
538
53.9k
  int res = 0;
539
53.9k
  Dwarf_Die abrootdie = 0;
540
53.9k
  Dwarf_Attribute ab_attr = 0;
541
53.9k
  Dwarf_Off ab_offset = 0;
542
543
53.9k
  res = dwarf_attr(die, DW_AT_abstract_origin, &ab_attr, errp);
544
53.9k
  if (res != DW_DLV_OK) {
545
1.82k
    return res;
546
1.82k
  }
547
548
52.1k
  res = dwarf_global_formref(ab_attr, &ab_offset, errp);
549
52.1k
  if (res != DW_DLV_OK) {
550
10.0k
    dwarf_dealloc(dbg, ab_attr, DW_DLA_ATTR);
551
10.0k
    return res;
552
10.0k
  }
553
554
42.0k
  dwarf_dealloc(dbg, ab_attr, DW_DLA_ATTR);
555
42.0k
  res = dwarf_offdie_b(dbg, ab_offset, is_info, &abrootdie, errp);
556
42.0k
  if (res != DW_DLV_OK) {
557
34.0k
    return res;
558
34.0k
  }
559
7.98k
  res = dwarf_diename(abrootdie, name, errp);
560
7.98k
  dwarf_dealloc_die(abrootdie);
561
7.98k
  return res;
562
42.0k
}
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
104k
                                 Dwarf_Addr *highpc_out, Dwarf_Error *errp) {
568
104k
  int res = 0;
569
104k
  Dwarf_Addr lowpc = 0;
570
104k
  Dwarf_Addr highpc = 0;
571
104k
  int finalres = 0;
572
104k
  int have_pc_range = FALSE;
573
574
104k
  res = getlowhighpc(die, &have_pc_range, &lowpc, &highpc, errp);
575
104k
  if (res == DW_DLV_OK) {
576
69.7k
    if (have_pc_range) {
577
69.7k
      int res2 = DW_DLV_OK;
578
69.7k
      char *name = 0;
579
580
69.7k
      if (td->td_target_pc < lowpc || td->td_target_pc >= highpc) {
581
15.4k
        finalres = DW_DLV_OK;
582
54.2k
      } else {
583
54.2k
        td->td_subprog_die = die;
584
54.2k
        td->td_subprog_lowpc = lowpc;
585
54.2k
        *lowpc_out = lowpc;
586
54.2k
        *highpc_out = highpc;
587
54.2k
        *have_pc_range_out = have_pc_range;
588
54.2k
        td->td_subprog_highpc = highpc;
589
54.2k
        td->td_subprog_haslowhighpc = have_pc_range;
590
54.2k
        res2 = dwarf_diename(die, &name, errp);
591
54.2k
        if (res2 == DW_DLV_OK) {
592
300
          td->td_subprog_name = name;
593
53.9k
        } else {
594
53.9k
          get_name_from_abstract_origin(dbg, is_info, die, &name, errp);
595
53.9k
        }
596
54.2k
        td->td_subprog_name = name;
597
54.2k
        name = 0;
598
54.2k
        finalres = FOUND_SUBPROG;
599
54.2k
      }
600
69.7k
    }
601
69.7k
  }
602
104k
  {
603
104k
    Dwarf_Signed i = 0;
604
104k
    Dwarf_Signed atcount = 0;
605
104k
    Dwarf_Attribute *atlist = 0;
606
607
104k
    res = dwarf_attrlist(die, &atlist, &atcount, errp);
608
104k
    if (res != DW_DLV_OK) {
609
2.55k
      return res;
610
2.55k
    }
611
284k
    for (i = 0; i < atcount; ++i) {
612
260k
      Dwarf_Half atr = 0;
613
260k
      Dwarf_Attribute attrib = atlist[i];
614
615
260k
      res = dwarf_whatattr(attrib, &atr, errp);
616
260k
      if (res != DW_DLV_OK) {
617
0
        dealloc_rest_of_list(dbg, atlist, atcount, i);
618
0
        return res;
619
0
      }
620
260k
      if (atr == DW_AT_ranges) {
621
84.5k
        int res2 = 0;
622
84.5k
        int res4 = 0;
623
84.5k
        Dwarf_Off ret_offset = 0;
624
84.5k
        int has_low_hi = FALSE;
625
84.5k
        Dwarf_Addr low = 0;
626
84.5k
        Dwarf_Addr high = 0;
627
628
84.5k
        res2 = dwarf_global_formref(attrib, &ret_offset, errp);
629
84.5k
        if (res2 != DW_DLV_OK) {
630
78.1k
          dealloc_rest_of_list(dbg, atlist, atcount, i);
631
78.1k
          return res2;
632
78.1k
        }
633
6.42k
        td->td_ranges_offset = ret_offset + td->td_cu_ranges_base;
634
6.42k
        res4 = check_subprog_ranges_for_match(dbg, die, td, &has_low_hi, &low,
635
6.42k
                                              &high, errp);
636
6.42k
        if (res4 == DW_DLV_OK) {
637
431
          continue;
638
431
        }
639
5.99k
        if (res4 == DW_DLV_NO_ENTRY) {
640
5.90k
          continue;
641
5.90k
        }
642
85
        if (res4 == FOUND_SUBPROG) {
643
70
          td->td_subprog_lowpc = lowpc;
644
70
          td->td_subprog_highpc = highpc;
645
70
          td->td_subprog_haslowhighpc = has_low_hi;
646
70
          finalres = FOUND_SUBPROG;
647
70
          continue;
648
70
        }
649
15
        dealloc_rest_of_list(dbg, atlist, atcount, i);
650
15
        return res4;
651
176k
      } else if (atr == DW_AT_decl_file) {
652
7.09k
        int res5 = 0;
653
7.09k
        Dwarf_Unsigned file_index = 0;
654
655
7.09k
        res5 = dwarf_formudata(attrib, &file_index, errp);
656
7.09k
        if (res5 != DW_DLV_OK) {
657
74
          dealloc_rest_of_list(dbg, atlist, atcount, i);
658
74
          return res5;
659
74
        }
660
7.02k
        td->td_subprog_fileindex = file_index;
661
7.02k
      }
662
176k
      dwarf_dealloc(dbg, attrib, DW_DLA_ATTR);
663
176k
    }
664
23.7k
    dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
665
23.7k
  }
666
0
  return finalres;
667
101k
}
668
669
static int check_comp_dir(Dwarf_Debug dbg, Dwarf_Die die,
670
13.5k
                          struct target_data_s *td, Dwarf_Error *errp) {
671
13.5k
  int res = 0;
672
13.5k
  int finalres = DW_DLV_NO_ENTRY;
673
13.5k
  int have_pc_range = FALSE;
674
13.5k
  Dwarf_Addr lowpc = 0;
675
13.5k
  Dwarf_Addr highpc = 0;
676
13.5k
  Dwarf_Off real_ranges_offset = 0;
677
13.5k
  int rdone = FALSE;
678
679
13.5k
  res = getlowhighpc(die, &have_pc_range, &lowpc, &highpc, errp);
680
13.5k
  if (res == DW_DLV_OK) {
681
1.74k
    if (have_pc_range) {
682
1.74k
      if (td->td_target_pc < lowpc || td->td_target_pc >= highpc) {
683
542
        res = NOT_THIS_CU;
684
1.20k
      } else {
685
1.20k
        td->td_cu_lowpc = lowpc;
686
1.20k
        td->td_cu_highpc = highpc;
687
1.20k
        res = IN_THIS_CU;
688
1.20k
      }
689
1.74k
    }
690
1.74k
  }
691
13.5k
  finalres = res;
692
13.5k
  {
693
13.5k
    Dwarf_Signed atcount = 0;
694
13.5k
    Dwarf_Attribute *atlist = 0;
695
13.5k
    Dwarf_Signed j = 0;
696
13.5k
    int alres = 0;
697
698
13.5k
    alres = dwarf_attrlist(die, &atlist, &atcount, errp);
699
13.5k
    if (alres != DW_DLV_OK) {
700
1.92k
      return alres;
701
1.92k
    }
702
61.3k
    for (j = 0; j < atcount; ++j) {
703
49.9k
      Dwarf_Half atr = 0;
704
49.9k
      Dwarf_Attribute attrib = atlist[j];
705
49.9k
      int resb = 0;
706
707
49.9k
      resb = dwarf_whatattr(attrib, &atr, errp);
708
49.9k
      if (resb != DW_DLV_OK) {
709
0
        dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
710
0
        return resb;
711
0
      }
712
49.9k
      if (atr == DW_AT_name) {
713
9.52k
        char *name = 0;
714
9.52k
        resb = dwarf_formstring(attrib, &name, errp);
715
9.52k
        if (resb == DW_DLV_OK) {
716
362
          td->td_cu_name = name;
717
362
        }
718
40.4k
      } else if (atr == DW_AT_comp_dir) {
719
5.12k
        char *name = 0;
720
5.12k
        resb = dwarf_formstring(attrib, &name, errp);
721
5.12k
        if (resb == DW_DLV_OK) {
722
132
          td->td_cu_comp_dir = name;
723
132
        }
724
35.3k
      } else if (atr == DW_AT_rnglists_base || atr == DW_AT_GNU_ranges_base) {
725
1.00k
        Dwarf_Off rbase = 0;
726
727
1.00k
        resb = dwarf_global_formref(attrib, &rbase, errp);
728
1.00k
        if (resb != DW_DLV_OK) {
729
154
          dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
730
154
          return resb;
731
154
        }
732
855
        td->td_cu_ranges_base = rbase;
733
34.3k
      } else if (atr == DW_AT_ranges) {
734
        /* we have actual ranges. */
735
1.60k
        Dwarf_Off rbase = 0;
736
737
1.60k
        resb = dwarf_global_formref(attrib, &rbase, errp);
738
1.60k
        if (resb != DW_DLV_OK) {
739
63
          dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
740
63
          return resb;
741
63
        }
742
1.53k
        real_ranges_offset = rbase;
743
1.53k
        rdone = TRUE;
744
1.53k
      }
745
49.7k
      dwarf_dealloc(dbg, attrib, DW_DLA_ATTR);
746
49.7k
    }
747
11.3k
    dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
748
11.3k
  }
749
11.3k
  if (rdone) {
750
1.53k
    int resr = 0;
751
1.53k
    Dwarf_Ranges *ranges = 0;
752
1.53k
    Dwarf_Signed ranges_count = 0;
753
1.53k
    Dwarf_Unsigned byte_count = 0;
754
1.53k
    Dwarf_Off actualoffset = 0;
755
1.53k
    Dwarf_Signed k = 0;
756
1.53k
    int done = FALSE;
757
758
1.53k
    resr = dwarf_get_ranges_b(dbg, real_ranges_offset, die, &actualoffset,
759
1.53k
                              &ranges, &ranges_count, &byte_count, errp);
760
1.53k
    if (resr != DW_DLV_OK) {
761
740
      return res;
762
740
    }
763
8.91k
    for (k = 0; k < ranges_count && !done; ++k) {
764
8.12k
      Dwarf_Ranges *cur = ranges + k;
765
8.12k
      Dwarf_Addr lowpcr = 0;
766
8.12k
      Dwarf_Addr highpcr = 0;
767
8.12k
      Dwarf_Addr baseaddr = td->td_cu_ranges_base;
768
769
8.12k
      switch (cur->dwr_type) {
770
7.66k
      case DW_RANGES_ENTRY:
771
7.66k
        lowpc = cur->dwr_addr1 + baseaddr;
772
7.66k
        highpc = cur->dwr_addr2 + baseaddr;
773
7.66k
        if (td->td_target_pc < lowpc || td->td_target_pc >= highpc) {
774
7.28k
          break;
775
7.28k
        }
776
379
        td->td_cu_lowpc = lowpcr;
777
379
        td->td_cu_highpc = highpcr;
778
379
        td->td_cu_haslowhighpc = TRUE;
779
379
        done = TRUE;
780
379
        finalres = IN_THIS_CU;
781
379
        break;
782
125
      case DW_RANGES_ADDRESS_SELECTION:
783
125
        baseaddr = cur->dwr_addr2;
784
125
        break;
785
330
      case DW_RANGES_END:
786
330
        break;
787
0
      default:
788
0
        return DW_DLV_ERROR;
789
8.12k
      }
790
8.12k
    }
791
797
    dwarf_dealloc_ranges(dbg, ranges, ranges_count);
792
797
  }
793
10.6k
  return finalres;
794
11.3k
}
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.90M
                            Dwarf_Error *errp) {
799
9.90M
  Dwarf_Half tag = 0;
800
9.90M
  int res = 0;
801
802
9.90M
  res = dwarf_tag(die, &tag, errp);
803
9.90M
  if (res != DW_DLV_OK) {
804
0
    return res;
805
0
  }
806
9.90M
  if (tag == DW_TAG_subprogram || tag == DW_TAG_inlined_subroutine) {
807
104k
    int have_pc_range = 0;
808
104k
    Dwarf_Addr lowpc = 0;
809
104k
    Dwarf_Addr highpc = 0;
810
811
104k
    res = check_subprog_details(dbg, is_info, die, td, &have_pc_range, &lowpc,
812
104k
                                &highpc, errp);
813
104k
    if (res == FOUND_SUBPROG) {
814
1.24k
      td->td_subprog_die = die;
815
1.24k
      return res;
816
103k
    } else if (res == DW_DLV_ERROR) {
817
562
      return res;
818
102k
    } else if (res == DW_DLV_NO_ENTRY) {
819
      /* impossible? */
820
80.1k
      return res;
821
80.1k
    } else if (res == NOT_THIS_CU) {
822
      /* impossible */
823
0
      return res;
824
22.5k
    } else if (res == IN_THIS_CU) {
825
      /* impossible */
826
0
      return res;
827
22.5k
    } else {
828
      /* DW_DLV_OK */
829
22.5k
    }
830
22.5k
    return DW_DLV_OK;
831
9.80M
  } else if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit ||
832
9.78M
             tag == DW_TAG_type_unit) {
833
834
4.67M
    if (level) {
835
4.66M
      return NOT_THIS_CU;
836
4.66M
    }
837
13.5k
    res = check_comp_dir(dbg, die, td, errp);
838
13.5k
    return res;
839
4.67M
  }
840
5.12M
  return DW_DLV_OK;
841
9.90M
}