Coverage Report

Created: 2025-07-18 06:39

/src/libdwarf/fuzz/fuzz_findfuncbypc.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 <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.6k
#define TRUE 1
32
405k
#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
11.8M
#define NOT_THIS_CU 10
73
421k
#define IN_THIS_CU 11
74
6.43M
#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
14.5k
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
95
14.5k
  char filepath[256];
96
14.5k
  sprintf(filepath, "/tmp/libfuzzer.%d", getpid());
97
98
14.5k
  FILE *fp = fopen(filepath, "wb");
99
14.5k
  if (!fp) {
100
0
    return 0;
101
0
  }
102
14.5k
  fwrite(data, size, 1, fp);
103
14.5k
  fclose(fp);
104
105
14.5k
  Dwarf_Debug dbg = 0;
106
14.5k
  Dwarf_Error error = 0;
107
14.5k
  Dwarf_Handler errhand = 0;
108
14.5k
  Dwarf_Ptr errarg = 0;
109
14.5k
  int i = 0;
110
14.5k
  Dwarf_Unsigned target_pc = 0x1000;
111
14.5k
#define PATH_LEN 2000
112
14.5k
  char real_path[PATH_LEN];
113
14.5k
  struct target_data_s target_data;
114
115
  /*  Added 19 May 2023 so valgrind will not complain
116
      about testing uninitialized values in
117
      check_coup_dir (for example). */
118
14.5k
  memset(&target_data,0,sizeof(target_data));
119
14.5k
  int res =
120
14.5k
      dwarf_init_path(filepath, 0, 0, DW_GROUPNUMBER_ANY, 0, 0, &dbg, &error);
121
14.5k
  if (res == DW_DLV_ERROR) {
122
4.78k
    dwarf_dealloc_error(dbg, error);
123
4.78k
    dwarf_finish(dbg);
124
9.76k
  } else {
125
9.76k
    res = look_for_our_target(dbg, &target_data, &error);
126
9.76k
    res = dwarf_finish(dbg);
127
9.76k
  }
128
129
14.5k
  unlink(filepath);
130
14.5k
  return 0;
131
14.5k
}
132
133
static int read_line_data(Dwarf_Debug dbg, struct target_data_s *td,
134
1.30k
                          Dwarf_Error *errp) {
135
1.30k
  int res = 0;
136
1.30k
  Dwarf_Unsigned line_version = 0;
137
1.30k
  Dwarf_Small table_type = 0;
138
1.30k
  Dwarf_Line_Context line_context = 0;
139
1.30k
  Dwarf_Signed i = 0;
140
1.30k
  Dwarf_Signed baseindex = 0;
141
1.30k
  Dwarf_Signed endindex = 0;
142
1.30k
  Dwarf_Signed file_count = 0;
143
1.30k
  Dwarf_Unsigned dirindex = 0;
144
145
1.30k
  (void)dbg;
146
1.30k
  res = dwarf_srclines_b(td->td_cu_die, &line_version, &table_type,
147
1.30k
                         &line_context, errp);
148
1.30k
  if (res != DW_DLV_OK) {
149
977
    return res;
150
977
  }
151
323
  if (table_type == 0) {
152
9
    int sres = 0;
153
154
9
    sres = dwarf_srclines_files_indexes(line_context, &baseindex, &file_count,
155
9
                                        &endindex, errp);
156
9
    if (sres != DW_DLV_OK) {
157
0
      dwarf_srclines_dealloc_b(line_context);
158
0
      line_context = 0;
159
0
      return sres;
160
0
    }
161
92
    for (i = baseindex; i < endindex; i++) {
162
83
      Dwarf_Unsigned modtime = 0;
163
83
      Dwarf_Unsigned flength = 0;
164
83
      Dwarf_Form_Data16 *md5data = 0;
165
83
      int vres = 0;
166
83
      const char *name = 0;
167
168
83
      vres = dwarf_srclines_files_data_b(line_context, i, &name, &dirindex,
169
83
                                         &modtime, &flength, &md5data, errp);
170
83
      if (vres != DW_DLV_OK) {
171
0
        dwarf_srclines_dealloc_b(line_context);
172
0
        line_context = 0;
173
0
        return vres;
174
0
      }
175
83
    }
176
9
    dwarf_srclines_dealloc_b(line_context);
177
9
    return DW_DLV_OK;
178
314
  } else if (table_type == 1) {
179
313
    const char *dir_name = 0;
180
313
    int sres = 0;
181
313
    Dwarf_Line *linebuf = 0;
182
313
    Dwarf_Signed linecount = 0;
183
313
    Dwarf_Signed dir_count = 0;
184
313
    Dwarf_Addr prev_lineaddr = 0;
185
313
    Dwarf_Unsigned prev_lineno = 0;
186
313
    char *prev_linesrcfile = 0;
187
188
313
    sres = dwarf_srclines_files_indexes(line_context, &baseindex, &file_count,
189
313
                                        &endindex, errp);
190
313
    if (sres != DW_DLV_OK) {
191
0
      dwarf_srclines_dealloc_b(line_context);
192
0
      line_context = 0;
193
0
      return sres;
194
0
    }
195
19.6k
    for (i = baseindex; i < endindex; i++) {
196
19.3k
      Dwarf_Unsigned dirindexb = 0;
197
19.3k
      Dwarf_Unsigned modtime = 0;
198
19.3k
      Dwarf_Unsigned flength = 0;
199
19.3k
      Dwarf_Form_Data16 *md5data = 0;
200
19.3k
      int vres = 0;
201
19.3k
      const char *name = 0;
202
203
19.3k
      vres = dwarf_srclines_files_data_b(line_context, i, &name, &dirindexb,
204
19.3k
                                         &modtime, &flength, &md5data, errp);
205
19.3k
      if (vres != DW_DLV_OK) {
206
0
        dwarf_srclines_dealloc_b(line_context);
207
0
        line_context = 0;
208
0
        return vres;
209
0
      }
210
19.3k
    }
211
313
    sres = dwarf_srclines_include_dir_count(line_context, &dir_count, errp);
212
313
    if (sres != DW_DLV_OK) {
213
0
      dwarf_srclines_dealloc_b(line_context);
214
0
      line_context = 0;
215
0
      return sres;
216
0
    }
217
218
3.60k
    for (i = 1; i <= dir_count; ++i) {
219
3.28k
      dir_name = 0;
220
3.28k
      sres = dwarf_srclines_include_dir_data(line_context, i, &dir_name, errp);
221
3.28k
      if (sres == DW_DLV_ERROR) {
222
0
        dwarf_srclines_dealloc_b(line_context);
223
0
        line_context = 0;
224
0
        return sres;
225
0
      }
226
3.28k
    }
227
228
313
    sres = dwarf_srclines_from_linecontext(line_context, &linebuf, &linecount,
229
313
                                           errp);
230
313
    if (sres != DW_DLV_OK) {
231
0
      dwarf_srclines_dealloc_b(line_context);
232
0
      line_context = 0;
233
0
      return sres;
234
0
    }
235
540k
    for (i = 0; i < linecount; ++i) {
236
540k
      Dwarf_Addr lineaddr = 0;
237
540k
      Dwarf_Unsigned filenum = 0;
238
540k
      Dwarf_Unsigned lineno = 0;
239
540k
      char *linesrcfile = 0;
240
241
540k
      sres = dwarf_lineno(linebuf[i], &lineno, errp);
242
540k
      if (sres == DW_DLV_ERROR) {
243
0
        if (prev_linesrcfile) {
244
0
          dwarf_dealloc(dbg, prev_linesrcfile, DW_DLA_STRING);
245
0
        }
246
0
        return sres;
247
0
      }
248
540k
      sres = dwarf_line_srcfileno(linebuf[i], &filenum, errp);
249
540k
      if (sres == DW_DLV_ERROR) {
250
0
        if (prev_linesrcfile) {
251
0
          dwarf_dealloc(dbg, prev_linesrcfile, DW_DLA_STRING);
252
0
        }
253
0
        return sres;
254
0
      }
255
540k
      if (filenum) {
256
524k
        filenum -= 1;
257
524k
      }
258
540k
      sres = dwarf_lineaddr(linebuf[i], &lineaddr, errp);
259
540k
      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
540k
      sres = dwarf_linesrc(linebuf[i], &linesrcfile, errp);
266
540k
      if (sres == DW_DLV_ERROR) {
267
145
        if (prev_linesrcfile) {
268
129
          dwarf_dealloc(dbg, prev_linesrcfile, DW_DLA_STRING);
269
129
        }
270
145
        return sres;
271
145
      }
272
540k
      if (lineaddr > td->td_target_pc) {
273
98
        td->td_subprog_lineaddr = prev_lineaddr;
274
98
        td->td_subprog_lineno = prev_lineno;
275
98
        td->td_subprog_srcfile = prev_linesrcfile;
276
98
        dwarf_dealloc(dbg, linesrcfile, DW_DLA_STRING);
277
98
        return DW_DLV_OK;
278
98
      }
279
540k
      prev_lineaddr = lineaddr;
280
540k
      prev_lineno = lineno;
281
540k
      if (prev_linesrcfile) {
282
523k
        dwarf_dealloc(dbg, prev_linesrcfile, DW_DLA_STRING);
283
523k
      }
284
540k
      prev_linesrcfile = linesrcfile;
285
540k
    }
286
70
    td->td_subprog_lineaddr = prev_lineaddr;
287
70
    td->td_subprog_lineno = prev_lineno;
288
70
    td->td_subprog_srcfile = prev_linesrcfile;
289
70
    dwarf_srclines_dealloc_b(line_context);
290
70
    return DW_DLV_OK;
291
313
  }
292
1
  return DW_DLV_ERROR;
293
323
}
294
295
static int look_for_our_target(Dwarf_Debug dbg, struct target_data_s *td,
296
9.76k
                               Dwarf_Error *errp) {
297
9.76k
  Dwarf_Unsigned cu_header_length = 0;
298
9.76k
  Dwarf_Unsigned abbrev_offset = 0;
299
9.76k
  Dwarf_Half address_size = 0;
300
9.76k
  Dwarf_Half version_stamp = 0;
301
9.76k
  Dwarf_Half offset_size = 0;
302
9.76k
  Dwarf_Half extension_size = 0;
303
9.76k
  Dwarf_Unsigned typeoffset = 0;
304
9.76k
  Dwarf_Half header_cu_type = unittype;
305
9.76k
  Dwarf_Bool is_info = g_is_info;
306
9.76k
  int cu_number = 0;
307
308
9.76k
  for (;; ++cu_number) {
309
9.76k
    Dwarf_Die no_die = 0;
310
9.76k
    Dwarf_Die cu_die = 0;
311
9.76k
    int res = DW_DLV_ERROR;
312
9.76k
    Dwarf_Sig8 signature;
313
314
9.76k
    memset(&signature, 0, sizeof(signature));
315
9.76k
    res = dwarf_next_cu_header_d(dbg, is_info, &cu_header_length,
316
9.76k
                                 &version_stamp, &abbrev_offset, &address_size,
317
9.76k
                                 &offset_size, &extension_size, &signature,
318
9.76k
                                 &typeoffset, 0, &header_cu_type, errp);
319
9.76k
    if (res == DW_DLV_ERROR) {
320
3.42k
      if (errp) {
321
3.42k
        char *em = dwarf_errmsg(*errp);
322
3.42k
      }
323
3.42k
      return DW_DLV_NO_ENTRY;
324
3.42k
    }
325
6.33k
    if (res == DW_DLV_NO_ENTRY) {
326
644
      return DW_DLV_NO_ENTRY;
327
644
    }
328
5.69k
    cu_version_stamp = version_stamp;
329
5.69k
    cu_offset_size = offset_size;
330
5.69k
    res = dwarf_siblingof_b(dbg, no_die, is_info, &cu_die, errp);
331
5.69k
    if (res == DW_DLV_ERROR) {
332
0
      if (errp) {
333
0
        char *em = dwarf_errmsg(*errp);
334
0
      }
335
0
      return res;
336
0
    }
337
5.69k
    if (res == DW_DLV_NO_ENTRY) {
338
274
      return res;
339
274
    }
340
341
5.42k
    td->td_cu_die = cu_die;
342
5.42k
    res = get_die_and_siblings(dbg, cu_die, is_info, 0, cu_number, td, errp);
343
5.42k
    if (res == FOUND_SUBPROG) {
344
1.30k
      read_line_data(dbg, td, errp);
345
1.30k
      if (td->td_reportallfound) {
346
0
        return res;
347
0
      }
348
1.30k
      return res;
349
4.12k
    } else if (res == IN_THIS_CU) {
350
0
      if (errp) {
351
0
          char *em = dwarf_errmsg(*errp);
352
0
      }
353
0
      return res;
354
4.12k
    } else if (res == DW_DLV_ERROR) {
355
2.30k
      if (errp) {
356
2.30k
        char *em = dwarf_errmsg(*errp);
357
2.30k
      }
358
2.30k
      return DW_DLV_ERROR;
359
2.30k
    }
360
1.81k
    return DW_DLV_NO_ENTRY;
361
5.42k
  }
362
9.76k
}
363
364
static int get_die_and_siblings(Dwarf_Debug dbg, Dwarf_Die in_die, int is_info,
365
                                int in_level, int cu_number,
366
284k
                                struct target_data_s *td, Dwarf_Error *errp) {
367
284k
  int res = DW_DLV_ERROR;
368
284k
  Dwarf_Die cur_die = in_die;
369
284k
  Dwarf_Die child = 0;
370
371
284k
  td->td_cu_number = cu_number;
372
284k
  res = examine_die_data(dbg, is_info, in_die, in_level, td, errp);
373
284k
  if (res == DW_DLV_ERROR) {
374
546
    return res;
375
546
  }
376
283k
  if (res == DW_DLV_NO_ENTRY) {
377
6.34k
    return res;
378
6.34k
  }
379
277k
  if (res == NOT_THIS_CU) {
380
113
    return res;
381
277k
  } else if (res == FOUND_SUBPROG) {
382
203
    return res;
383
276k
  } else {
384
276k
  }
385
386
9.94M
  for (;;) {
387
9.94M
    Dwarf_Die sib_die = 0;
388
9.94M
    res = dwarf_child(cur_die, &child, errp);
389
9.94M
    if (res == DW_DLV_ERROR) {
390
517
      return res;
391
517
    }
392
9.94M
    if (res == DW_DLV_OK) {
393
278k
      int res2 = 0;
394
395
278k
      res2 = get_die_and_siblings(dbg, child, is_info, in_level + 1, cu_number,
396
278k
                                  td, errp);
397
278k
      if (child != td->td_cu_die && child != td->td_subprog_die) {
398
274k
        dwarf_dealloc(dbg, child, DW_DLA_DIE);
399
274k
      }
400
278k
      if (res2 == FOUND_SUBPROG) {
401
3.06k
        return res2;
402
275k
      } else if (res2 == IN_THIS_CU) {
403
275k
      } else if (res2 == NOT_THIS_CU) {
404
7.91k
        return res2;
405
267k
      } else if (res2 == DW_DLV_ERROR) {
406
61.2k
        return res2;
407
206k
      } else if (res2 == DW_DLV_NO_ENTRY) {
408
200k
      } else { /* DW_DLV_OK */
409
200k
      }
410
206k
      child = 0;
411
206k
    }
412
9.86M
    res = dwarf_siblingof_b(dbg, cur_die, is_info, &sib_die, errp);
413
9.86M
    if (res == DW_DLV_ERROR) {
414
1.01k
      if (errp) {
415
1.01k
          char *em = dwarf_errmsg(*errp);
416
1.01k
      }
417
1.01k
      return res;
418
1.01k
    }
419
9.86M
    if (res == DW_DLV_NO_ENTRY) {
420
201k
      break;
421
201k
    }
422
9.66M
    if (cur_die != in_die) {
423
9.47M
      if (child != td->td_cu_die && child != td->td_subprog_die) {
424
3.67M
        dwarf_dealloc(dbg, cur_die, DW_DLA_DIE);
425
3.67M
      }
426
9.47M
      cur_die = 0;
427
9.47M
    }
428
9.66M
    cur_die = sib_die;
429
9.66M
    res = examine_die_data(dbg, is_info, cur_die, in_level, td, errp);
430
9.66M
    if (res == DW_DLV_ERROR) {
431
236
      return res;
432
9.66M
    } else if (res == DW_DLV_OK) {
433
5.68M
    } else if (res == FOUND_SUBPROG) {
434
1.09k
      return res;
435
5.68M
    } else if (res == NOT_THIS_CU) {
436
5.56M
    } else if (res == IN_THIS_CU) {
437
113k
    } else {
438
113k
    }
439
9.66M
  }
440
201k
  return DW_DLV_OK;
441
276k
}
442
443
static void dealloc_rest_of_list(Dwarf_Debug dbg, Dwarf_Attribute *attrbuf,
444
74.4k
                                 Dwarf_Signed attrcount, Dwarf_Signed i) {
445
406k
  for (; i < attrcount; ++i) {
446
332k
    dwarf_dealloc_attribute(attrbuf[i]);
447
332k
  }
448
74.4k
  dwarf_dealloc(dbg, attrbuf, DW_DLA_LIST);
449
74.4k
}
450
451
static int getlowhighpc(Dwarf_Die die, int *have_pc_range,
452
                        Dwarf_Addr *lowpc_out, Dwarf_Addr *highpc_out,
453
150k
                        Dwarf_Error *error) {
454
150k
  Dwarf_Addr hipc = 0;
455
150k
  int res = 0;
456
150k
  Dwarf_Half form = 0;
457
150k
  enum Dwarf_Form_Class formclass = 0;
458
459
150k
  *have_pc_range = FALSE;
460
150k
  res = dwarf_lowpc(die, lowpc_out, error);
461
150k
  if (res == DW_DLV_OK) {
462
84.1k
    res = dwarf_highpc_b(die, &hipc, &form, &formclass, error);
463
84.1k
    if (res == DW_DLV_OK) {
464
71.7k
      if (formclass == DW_FORM_CLASS_CONSTANT) {
465
6.28k
        hipc += *lowpc_out;
466
6.28k
      }
467
71.7k
      *highpc_out = hipc;
468
71.7k
      *have_pc_range = TRUE;
469
71.7k
      return DW_DLV_OK;
470
71.7k
    }
471
84.1k
  }
472
79.0k
  return DW_DLV_NO_ENTRY;
473
150k
}
474
475
static int check_subprog_ranges_for_match(Dwarf_Debug dbg, Dwarf_Die die,
476
                                          struct target_data_s *td,
477
                                          int *have_pc_range,
478
                                          Dwarf_Addr *lowpc_out,
479
                                          Dwarf_Addr *highpc_out,
480
5.61k
                                          Dwarf_Error *errp) {
481
5.61k
  int res = 0;
482
5.61k
  Dwarf_Ranges *ranges;
483
5.61k
  Dwarf_Signed ranges_count;
484
5.61k
  Dwarf_Unsigned byte_count;
485
5.61k
  Dwarf_Signed i = 0;
486
5.61k
  Dwarf_Addr baseaddr = 0;
487
5.61k
  Dwarf_Off actualoffset = 0;
488
5.61k
  int done = FALSE;
489
490
5.61k
  res = dwarf_get_ranges_b(dbg, td->td_ranges_offset, die, &actualoffset,
491
5.61k
                           &ranges, &ranges_count, &byte_count, errp);
492
5.61k
  if (res != DW_DLV_OK) {
493
4.91k
    return res;
494
4.91k
  }
495
8.39k
  for (i = 0; i < ranges_count && !done; ++i) {
496
7.69k
    Dwarf_Ranges *cur = ranges + i;
497
7.69k
    Dwarf_Addr lowpc = 0;
498
7.69k
    Dwarf_Addr highpc = 0;
499
7.69k
    switch (cur->dwr_type) {
500
6.87k
    case DW_RANGES_ENTRY:
501
6.87k
      lowpc = cur->dwr_addr1 + baseaddr;
502
6.87k
      highpc = cur->dwr_addr2 + baseaddr;
503
6.87k
      if (td->td_target_pc < lowpc || td->td_target_pc >= highpc) {
504
6.80k
        break;
505
6.80k
      }
506
78
      *lowpc_out = lowpc;
507
78
      *highpc_out = highpc;
508
78
      *have_pc_range = TRUE;
509
78
      done = TRUE;
510
78
      res = FOUND_SUBPROG;
511
78
      break;
512
345
    case DW_RANGES_ADDRESS_SELECTION:
513
345
      baseaddr = cur->dwr_addr2;
514
345
      break;
515
470
    case DW_RANGES_END:
516
470
      break;
517
0
    default:
518
0
      return DW_DLV_ERROR;
519
7.69k
    }
520
7.69k
  }
521
703
  dwarf_dealloc_ranges(dbg, ranges, ranges_count);
522
703
  return res;
523
703
}
524
525
static int get_name_from_abstract_origin(Dwarf_Debug dbg, int is_info,
526
                                         Dwarf_Die die, char **name,
527
54.3k
                                         Dwarf_Error *errp) {
528
54.3k
  int res = 0;
529
54.3k
  Dwarf_Die abrootdie = 0;
530
54.3k
  Dwarf_Attribute ab_attr = 0;
531
54.3k
  Dwarf_Off ab_offset = 0;
532
533
54.3k
  res = dwarf_attr(die, DW_AT_abstract_origin, &ab_attr, errp);
534
54.3k
  if (res != DW_DLV_OK) {
535
1.51k
    return res;
536
1.51k
  }
537
538
52.8k
  res = dwarf_global_formref(ab_attr, &ab_offset, errp);
539
52.8k
  if (res != DW_DLV_OK) {
540
10.6k
    dwarf_dealloc(dbg, ab_attr, DW_DLA_ATTR);
541
10.6k
    return res;
542
10.6k
  }
543
544
42.1k
  dwarf_dealloc(dbg, ab_attr, DW_DLA_ATTR);
545
42.1k
  res = dwarf_offdie_b(dbg, ab_offset, is_info, &abrootdie, errp);
546
42.1k
  if (res != DW_DLV_OK) {
547
33.5k
    return res;
548
33.5k
  }
549
8.58k
  res = dwarf_diename(abrootdie, name, errp);
550
8.58k
  dwarf_dealloc_die(abrootdie);
551
8.58k
  return res;
552
42.1k
}
553
554
static int check_subprog_details(Dwarf_Debug dbg, int is_info, Dwarf_Die die,
555
                                 struct target_data_s *td,
556
                                 int *have_pc_range_out, Dwarf_Addr *lowpc_out,
557
133k
                                 Dwarf_Addr *highpc_out, Dwarf_Error *errp) {
558
133k
  int res = 0;
559
133k
  Dwarf_Addr lowpc = 0;
560
133k
  Dwarf_Addr highpc = 0;
561
133k
  int finalres = 0;
562
133k
  int have_pc_range = FALSE;
563
564
133k
  res = getlowhighpc(die, &have_pc_range, &lowpc, &highpc, errp);
565
133k
  if (res == DW_DLV_OK) {
566
69.1k
    if (have_pc_range) {
567
69.1k
      int res2 = DW_DLV_OK;
568
69.1k
      char *name = 0;
569
570
69.1k
      if (td->td_target_pc < lowpc || td->td_target_pc >= highpc) {
571
14.4k
        finalres = DW_DLV_OK;
572
54.6k
      } else {
573
54.6k
        td->td_subprog_die = die;
574
54.6k
        td->td_subprog_lowpc = lowpc;
575
54.6k
        *lowpc_out = lowpc;
576
54.6k
        *highpc_out = highpc;
577
54.6k
        *have_pc_range_out = have_pc_range;
578
54.6k
        td->td_subprog_highpc = highpc;
579
54.6k
        td->td_subprog_haslowhighpc = have_pc_range;
580
54.6k
        res2 = dwarf_diename(die, &name, errp);
581
54.6k
        if (res2 == DW_DLV_OK) {
582
287
          td->td_subprog_name = name;
583
54.3k
        } else {
584
54.3k
          get_name_from_abstract_origin(dbg, is_info, die, &name, errp);
585
54.3k
        }
586
54.6k
        td->td_subprog_name = name;
587
54.6k
        name = 0;
588
54.6k
        finalres = FOUND_SUBPROG;
589
54.6k
      }
590
69.1k
    }
591
69.1k
  }
592
133k
  {
593
133k
    Dwarf_Signed i = 0;
594
133k
    Dwarf_Signed atcount = 0;
595
133k
    Dwarf_Attribute *atlist = 0;
596
597
133k
    res = dwarf_attrlist(die, &atlist, &atcount, errp);
598
133k
    if (res != DW_DLV_OK) {
599
31.7k
      return res;
600
31.7k
    }
601
289k
    for (i = 0; i < atcount; ++i) {
602
262k
      Dwarf_Half atr = 0;
603
262k
      Dwarf_Attribute attrib = atlist[i];
604
605
262k
      res = dwarf_whatattr(attrib, &atr, errp);
606
262k
      if (res != DW_DLV_OK) {
607
0
        dealloc_rest_of_list(dbg, atlist, atcount, i);
608
0
        return res;
609
0
      }
610
262k
      if (atr == DW_AT_ranges) {
611
79.9k
        int res2 = 0;
612
79.9k
        int res4 = 0;
613
79.9k
        Dwarf_Off ret_offset = 0;
614
79.9k
        int has_low_hi = FALSE;
615
79.9k
        Dwarf_Addr low = 0;
616
79.9k
        Dwarf_Addr high = 0;
617
618
79.9k
        res2 = dwarf_global_formref(attrib, &ret_offset, errp);
619
79.9k
        if (res2 != DW_DLV_OK) {
620
74.3k
          dealloc_rest_of_list(dbg, atlist, atcount, i);
621
74.3k
          return res2;
622
74.3k
        }
623
5.61k
        td->td_ranges_offset = ret_offset + td->td_cu_ranges_base;
624
5.61k
        res4 = check_subprog_ranges_for_match(dbg, die, td, &has_low_hi, &low,
625
5.61k
                                              &high, errp);
626
5.61k
        if (res4 == DW_DLV_OK) {
627
625
          continue;
628
625
        }
629
4.99k
        if (res4 == DW_DLV_NO_ENTRY) {
630
4.87k
          continue;
631
4.87k
        }
632
116
        if (res4 == FOUND_SUBPROG) {
633
78
          td->td_subprog_lowpc = lowpc;
634
78
          td->td_subprog_highpc = highpc;
635
78
          td->td_subprog_haslowhighpc = has_low_hi;
636
78
          finalres = FOUND_SUBPROG;
637
78
          continue;
638
78
        }
639
38
        dealloc_rest_of_list(dbg, atlist, atcount, i);
640
38
        return res4;
641
182k
      } else if (atr == DW_AT_decl_file) {
642
6.77k
        int res5 = 0;
643
6.77k
        Dwarf_Unsigned file_index = 0;
644
645
6.77k
        res5 = dwarf_formudata(attrib, &file_index, errp);
646
6.77k
        if (res5 != DW_DLV_OK) {
647
34
          dealloc_rest_of_list(dbg, atlist, atcount, i);
648
34
          return res5;
649
34
        }
650
6.73k
        td->td_subprog_fileindex = file_index;
651
6.73k
      }
652
182k
      dwarf_dealloc(dbg, attrib, DW_DLA_ATTR);
653
182k
    }
654
26.9k
    dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
655
26.9k
  }
656
0
  return finalres;
657
101k
}
658
659
static int check_comp_dir(Dwarf_Debug dbg, Dwarf_Die die,
660
17.5k
                          struct target_data_s *td, Dwarf_Error *errp) {
661
17.5k
  int res = 0;
662
17.5k
  int finalres = DW_DLV_NO_ENTRY;
663
17.5k
  int have_pc_range = FALSE;
664
17.5k
  Dwarf_Addr lowpc = 0;
665
17.5k
  Dwarf_Addr highpc = 0;
666
17.5k
  Dwarf_Off real_ranges_offset = 0;
667
17.5k
  int rdone = FALSE;
668
669
17.5k
  res = getlowhighpc(die, &have_pc_range, &lowpc, &highpc, errp);
670
17.5k
  if (res == DW_DLV_OK) {
671
2.56k
    if (have_pc_range) {
672
2.56k
      if (td->td_target_pc < lowpc || td->td_target_pc >= highpc) {
673
1.11k
        res = NOT_THIS_CU;
674
1.44k
      } else {
675
1.44k
        td->td_cu_lowpc = lowpc;
676
1.44k
        td->td_cu_highpc = highpc;
677
1.44k
        res = IN_THIS_CU;
678
1.44k
      }
679
2.56k
    }
680
2.56k
  }
681
17.5k
  finalres = res;
682
17.5k
  {
683
17.5k
    Dwarf_Signed atcount = 0;
684
17.5k
    Dwarf_Attribute *atlist = 0;
685
17.5k
    Dwarf_Signed j = 0;
686
17.5k
    int alres = 0;
687
688
17.5k
    alres = dwarf_attrlist(die, &atlist, &atcount, errp);
689
17.5k
    if (alres != DW_DLV_OK) {
690
2.43k
      return alres;
691
2.43k
    }
692
79.0k
    for (j = 0; j < atcount; ++j) {
693
64.0k
      Dwarf_Half atr = 0;
694
64.0k
      Dwarf_Attribute attrib = atlist[j];
695
64.0k
      int resb = 0;
696
697
64.0k
      resb = dwarf_whatattr(attrib, &atr, errp);
698
64.0k
      if (resb != DW_DLV_OK) {
699
0
        dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
700
0
        return resb;
701
0
      }
702
64.0k
      if (atr == DW_AT_name) {
703
12.9k
        char *name = 0;
704
12.9k
        resb = dwarf_formstring(attrib, &name, errp);
705
12.9k
        if (resb == DW_DLV_OK) {
706
641
          td->td_cu_name = name;
707
641
        }
708
51.0k
      } else if (atr == DW_AT_comp_dir) {
709
6.65k
        char *name = 0;
710
6.65k
        resb = dwarf_formstring(attrib, &name, errp);
711
6.65k
        if (resb == DW_DLV_OK) {
712
136
          td->td_cu_comp_dir = name;
713
136
        }
714
44.4k
      } else if (atr == DW_AT_rnglists_base || atr == DW_AT_GNU_ranges_base) {
715
993
        Dwarf_Off rbase = 0;
716
717
993
        resb = dwarf_global_formref(attrib, &rbase, errp);
718
993
        if (resb != DW_DLV_OK) {
719
174
          dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
720
174
          return resb;
721
174
        }
722
819
        td->td_cu_ranges_base = rbase;
723
43.4k
      } else if (atr == DW_AT_ranges) {
724
        /* we have actual ranges. */
725
1.31k
        Dwarf_Off rbase = 0;
726
727
1.31k
        resb = dwarf_global_formref(attrib, &rbase, errp);
728
1.31k
        if (resb != DW_DLV_OK) {
729
41
          dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
730
41
          return resb;
731
41
        }
732
1.27k
        real_ranges_offset = rbase;
733
1.27k
        rdone = TRUE;
734
1.27k
      }
735
63.8k
      dwarf_dealloc(dbg, attrib, DW_DLA_ATTR);
736
63.8k
    }
737
14.9k
    dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
738
14.9k
  }
739
14.9k
  if (rdone) {
740
1.27k
    int resr = 0;
741
1.27k
    Dwarf_Ranges *ranges = 0;
742
1.27k
    Dwarf_Signed ranges_count = 0;
743
1.27k
    Dwarf_Unsigned byte_count = 0;
744
1.27k
    Dwarf_Off actualoffset = 0;
745
1.27k
    Dwarf_Signed k = 0;
746
1.27k
    int done = FALSE;
747
748
1.27k
    resr = dwarf_get_ranges_b(dbg, real_ranges_offset, die, &actualoffset,
749
1.27k
                              &ranges, &ranges_count, &byte_count, errp);
750
1.27k
    if (resr != DW_DLV_OK) {
751
734
      return res;
752
734
    }
753
8.04k
    for (k = 0; k < ranges_count && !done; ++k) {
754
7.50k
      Dwarf_Ranges *cur = ranges + k;
755
7.50k
      Dwarf_Addr lowpcr = 0;
756
7.50k
      Dwarf_Addr highpcr = 0;
757
7.50k
      Dwarf_Addr baseaddr = td->td_cu_ranges_base;
758
759
7.50k
      switch (cur->dwr_type) {
760
7.10k
      case DW_RANGES_ENTRY:
761
7.10k
        lowpc = cur->dwr_addr1 + baseaddr;
762
7.10k
        highpc = cur->dwr_addr2 + baseaddr;
763
7.10k
        if (td->td_target_pc < lowpc || td->td_target_pc >= highpc) {
764
6.85k
          break;
765
6.85k
        }
766
242
        td->td_cu_lowpc = lowpcr;
767
242
        td->td_cu_highpc = highpcr;
768
242
        td->td_cu_haslowhighpc = TRUE;
769
242
        done = TRUE;
770
242
        finalres = IN_THIS_CU;
771
242
        break;
772
220
      case DW_RANGES_ADDRESS_SELECTION:
773
220
        baseaddr = cur->dwr_addr2;
774
220
        break;
775
182
      case DW_RANGES_END:
776
182
        break;
777
0
      default:
778
0
        return DW_DLV_ERROR;
779
7.50k
      }
780
7.50k
    }
781
538
    dwarf_dealloc_ranges(dbg, ranges, ranges_count);
782
538
  }
783
14.2k
  return finalres;
784
14.9k
}
785
786
static int examine_die_data(Dwarf_Debug dbg, int is_info, Dwarf_Die die,
787
                            int level, struct target_data_s *td,
788
9.95M
                            Dwarf_Error *errp) {
789
9.95M
  Dwarf_Half tag = 0;
790
9.95M
  int res = 0;
791
792
9.95M
  res = dwarf_tag(die, &tag, errp);
793
9.95M
  if (res != DW_DLV_OK) {
794
0
    return res;
795
0
  }
796
9.95M
  if (tag == DW_TAG_subprogram || tag == DW_TAG_inlined_subroutine) {
797
133k
    int have_pc_range = 0;
798
133k
    Dwarf_Addr lowpc = 0;
799
133k
    Dwarf_Addr highpc = 0;
800
801
133k
    res = check_subprog_details(dbg, is_info, die, td, &have_pc_range, &lowpc,
802
133k
                                &highpc, errp);
803
133k
    if (res == FOUND_SUBPROG) {
804
1.30k
      td->td_subprog_die = die;
805
1.30k
      return res;
806
131k
    } else if (res == DW_DLV_ERROR) {
807
611
      return res;
808
131k
    } else if (res == DW_DLV_NO_ENTRY) {
809
      /* impossible? */
810
105k
      return res;
811
105k
    } else if (res == NOT_THIS_CU) {
812
      /* impossible */
813
0
      return res;
814
25.6k
    } else if (res == IN_THIS_CU) {
815
      /* impossible */
816
0
      return res;
817
25.6k
    } else {
818
      /* DW_DLV_OK */
819
25.6k
    }
820
25.6k
    return DW_DLV_OK;
821
9.81M
  } else if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit ||
822
9.81M
             tag == DW_TAG_type_unit) {
823
824
5.58M
    if (level) {
825
5.56M
      return NOT_THIS_CU;
826
5.56M
    }
827
17.5k
    res = check_comp_dir(dbg, die, td, errp);
828
17.5k
    return res;
829
5.58M
  }
830
4.23M
  return DW_DLV_OK;
831
9.95M
}