Coverage Report

Created: 2026-08-13 07:12

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