Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/elftoolchain/addr2line/addr2line.c
39507 views
1
/*-
2
* Copyright (c) 2009 Kai Wang
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
*
14
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
* SUCH DAMAGE.
25
*/
26
27
#include <sys/param.h>
28
#include <sys/tree.h>
29
30
#include <capsicum_helpers.h>
31
#include <dwarf.h>
32
#include <err.h>
33
#include <fcntl.h>
34
#include <gelf.h>
35
#include <getopt.h>
36
#include <libdwarf.h>
37
#include <libelftc.h>
38
#include <libgen.h>
39
#include <stdbool.h>
40
#include <stdio.h>
41
#include <stdlib.h>
42
#include <string.h>
43
44
#include "_elftc.h"
45
46
ELFTC_VCSID("$Id: addr2line.c 3499 2016-11-25 16:06:29Z emaste $");
47
48
struct Func {
49
char *name;
50
Dwarf_Unsigned lopc;
51
Dwarf_Unsigned hipc;
52
Dwarf_Unsigned call_file;
53
Dwarf_Unsigned call_line;
54
Dwarf_Ranges *ranges;
55
Dwarf_Signed ranges_cnt;
56
struct Func *inlined_caller;
57
STAILQ_ENTRY(Func) next;
58
};
59
60
struct range {
61
RB_ENTRY(range) entry;
62
Dwarf_Off off;
63
Dwarf_Unsigned lopc;
64
Dwarf_Unsigned hipc;
65
char **srcfiles;
66
Dwarf_Signed nsrcfiles;
67
STAILQ_HEAD(, Func) funclist;
68
Dwarf_Die die;
69
Dwarf_Debug dbg;
70
};
71
72
static struct option longopts[] = {
73
{"addresses", no_argument, NULL, 'a'},
74
{"target" , required_argument, NULL, 'b'},
75
{"demangle", no_argument, NULL, 'C'},
76
{"exe", required_argument, NULL, 'e'},
77
{"functions", no_argument, NULL, 'f'},
78
{"inlines", no_argument, NULL, 'i'},
79
{"section", required_argument, NULL, 'j'},
80
{"pretty-print", no_argument, NULL, 'p'},
81
{"basename", no_argument, NULL, 's'},
82
{"help", no_argument, NULL, 'H'},
83
{"version", no_argument, NULL, 'V'},
84
{NULL, 0, NULL, 0}
85
};
86
87
static int demangle, func, base, inlines, print_addr, pretty_print;
88
static char unknown[] = { '?', '?', '\0' };
89
static Dwarf_Addr section_base;
90
/* Need a new curlopc that stores last lopc value. */
91
static Dwarf_Unsigned curlopc = ~0ULL;
92
static RB_HEAD(cutree, range) cuhead = RB_INITIALIZER(&cuhead);
93
94
static int
95
lopccmp(struct range *e1, struct range *e2)
96
{
97
return (e1->lopc < e2->lopc ? -1 : e1->lopc > e2->lopc);
98
}
99
100
RB_PROTOTYPE(cutree, range, entry, lopccmp);
101
RB_GENERATE(cutree, range, entry, lopccmp)
102
103
#define USAGE_MESSAGE "\
104
Usage: %s [options] hexaddress...\n\
105
Map program addresses to source file names and line numbers.\n\n\
106
Options:\n\
107
-a | --addresses Display address prior to line number info.\n\
108
-b TGT | --target=TGT (Accepted but ignored).\n\
109
-e EXE | --exe=EXE Use program \"EXE\" to translate addresses.\n\
110
-f | --functions Display function names.\n\
111
-i | --inlines Display caller info for inlined functions.\n\
112
-j NAME | --section=NAME Values are offsets into section \"NAME\".\n\
113
-p | --pretty-print Display line number info and function name\n\
114
in human readable manner.\n\
115
-s | --basename Only show the base name for each file name.\n\
116
-C | --demangle Demangle C++ names.\n\
117
-H | --help Print a help message.\n\
118
-V | --version Print a version identifier and exit.\n"
119
120
static void
121
usage(void)
122
{
123
(void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
124
exit(1);
125
}
126
127
static void
128
version(void)
129
{
130
131
fprintf(stderr, "%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version());
132
exit(0);
133
}
134
135
/*
136
* Handle DWARF 4 'offset from' DW_AT_high_pc. Although we don't
137
* fully support DWARF 4, some compilers (like FreeBSD Clang 3.5.1)
138
* generate DW_AT_high_pc as an offset from DW_AT_low_pc.
139
*
140
* "If the value of the DW_AT_high_pc is of class address, it is the
141
* relocated address of the first location past the last instruction
142
* associated with the entity; if it is of class constant, the value
143
* is an unsigned integer offset which when added to the low PC gives
144
* the address of the first location past the last instruction
145
* associated with the entity."
146
*
147
* DWARF4 spec, section 2.17.2.
148
*/
149
static int
150
handle_high_pc(Dwarf_Die die, Dwarf_Unsigned lopc, Dwarf_Unsigned *hipc)
151
{
152
Dwarf_Error de;
153
Dwarf_Half form;
154
Dwarf_Attribute at;
155
int ret;
156
157
ret = dwarf_attr(die, DW_AT_high_pc, &at, &de);
158
if (ret == DW_DLV_ERROR) {
159
warnx("dwarf_attr failed: %s", dwarf_errmsg(de));
160
return (ret);
161
}
162
ret = dwarf_whatform(at, &form, &de);
163
if (ret == DW_DLV_ERROR) {
164
warnx("dwarf_whatform failed: %s", dwarf_errmsg(de));
165
return (ret);
166
}
167
if (dwarf_get_form_class(2, 0, 0, form) == DW_FORM_CLASS_CONSTANT)
168
*hipc += lopc;
169
170
return (DW_DLV_OK);
171
}
172
173
static struct Func *
174
search_func(struct range *range, Dwarf_Unsigned addr)
175
{
176
struct Func *f, *f0;
177
Dwarf_Unsigned lopc, hipc, addr_base;
178
int i;
179
180
f0 = NULL;
181
182
STAILQ_FOREACH(f, &range->funclist, next) {
183
if (f->ranges != NULL) {
184
addr_base = 0;
185
for (i = 0; i < f->ranges_cnt; i++) {
186
if (f->ranges[i].dwr_type == DW_RANGES_END)
187
break;
188
if (f->ranges[i].dwr_type ==
189
DW_RANGES_ADDRESS_SELECTION) {
190
addr_base = f->ranges[i].dwr_addr2;
191
continue;
192
}
193
194
/* DW_RANGES_ENTRY */
195
lopc = f->ranges[i].dwr_addr1 + addr_base;
196
hipc = f->ranges[i].dwr_addr2 + addr_base;
197
if (addr >= lopc && addr < hipc) {
198
if (f0 == NULL ||
199
(lopc >= f0->lopc &&
200
hipc <= f0->hipc)) {
201
f0 = f;
202
f0->lopc = lopc;
203
f0->hipc = hipc;
204
break;
205
}
206
}
207
}
208
} else if (addr >= f->lopc && addr < f->hipc) {
209
if (f0 == NULL ||
210
(f->lopc >= f0->lopc && f->hipc <= f0->hipc))
211
f0 = f;
212
}
213
}
214
215
return (f0);
216
}
217
218
static void
219
collect_func(Dwarf_Debug dbg, Dwarf_Die die, struct Func *parent,
220
struct range *range)
221
{
222
Dwarf_Die ret_die, abst_die, spec_die;
223
Dwarf_Error de;
224
Dwarf_Half tag;
225
Dwarf_Unsigned lopc, hipc, ranges_off;
226
Dwarf_Signed ranges_cnt;
227
Dwarf_Off ref;
228
Dwarf_Attribute abst_at, spec_at;
229
Dwarf_Ranges *ranges;
230
const char *funcname;
231
struct Func *f;
232
int found_ranges, ret;
233
234
f = NULL;
235
abst_die = spec_die = NULL;
236
237
if (dwarf_tag(die, &tag, &de)) {
238
warnx("dwarf_tag: %s", dwarf_errmsg(de));
239
goto cont_search;
240
}
241
if (tag == DW_TAG_subprogram || tag == DW_TAG_entry_point ||
242
tag == DW_TAG_inlined_subroutine || tag == DW_TAG_label) {
243
/*
244
* Function address range can be specified by either
245
* a DW_AT_ranges attribute which points to a range list or
246
* by a pair of DW_AT_low_pc and DW_AT_high_pc attributes.
247
*/
248
ranges = NULL;
249
ranges_cnt = 0;
250
found_ranges = 0;
251
if (dwarf_attrval_unsigned(die, DW_AT_ranges, &ranges_off,
252
&de) == DW_DLV_OK &&
253
dwarf_get_ranges(dbg, (Dwarf_Off) ranges_off, &ranges,
254
&ranges_cnt, NULL, &de) == DW_DLV_OK) {
255
if (ranges != NULL && ranges_cnt > 0) {
256
found_ranges = 1;
257
goto get_func_name;
258
}
259
}
260
261
/*
262
* Ranges pointer not found. Search for DW_AT_low_pc, and
263
* DW_AT_high_pc iff die is not a label. Labels doesn't have
264
* hipc attr. */
265
if (tag == DW_TAG_label) {
266
if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc,
267
&de) != DW_DLV_OK)
268
goto cont_search;
269
} else {
270
if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc,
271
&de) || dwarf_attrval_unsigned(die, DW_AT_high_pc,
272
&hipc, &de))
273
goto cont_search;
274
if (handle_high_pc(die, lopc, &hipc) != DW_DLV_OK)
275
goto cont_search;
276
}
277
278
get_func_name:
279
/*
280
* Most common case the function name is stored in DW_AT_name
281
* attribute.
282
*/
283
if (dwarf_attrval_string(die, DW_AT_name, &funcname, &de) ==
284
DW_DLV_OK)
285
goto add_func;
286
287
/*
288
* For inlined function, the actual name is probably in the DIE
289
* referenced by DW_AT_abstract_origin. (if present)
290
*/
291
if (dwarf_attr(die, DW_AT_abstract_origin, &abst_at, &de) ==
292
DW_DLV_OK &&
293
dwarf_global_formref(abst_at, &ref, &de) == DW_DLV_OK &&
294
dwarf_offdie(dbg, ref, &abst_die, &de) == DW_DLV_OK &&
295
dwarf_attrval_string(abst_die, DW_AT_name, &funcname,
296
&de) == DW_DLV_OK)
297
goto add_func;
298
299
/*
300
* If DW_AT_name is not present, but DW_AT_specification is
301
* present, then probably the actual name is in the DIE
302
* referenced by DW_AT_specification.
303
*/
304
if (dwarf_attr(die, DW_AT_specification, &spec_at, &de) ==
305
DW_DLV_OK &&
306
dwarf_global_formref(spec_at, &ref, &de) == DW_DLV_OK &&
307
dwarf_offdie(dbg, ref, &spec_die, &de) == DW_DLV_OK &&
308
dwarf_attrval_string(spec_die, DW_AT_name, &funcname,
309
&de) == DW_DLV_OK)
310
goto add_func;
311
312
/* Skip if no name associated with this DIE. */
313
goto cont_search;
314
315
add_func:
316
if ((f = calloc(1, sizeof(*f))) == NULL)
317
err(EXIT_FAILURE, "calloc");
318
if ((f->name = strdup(funcname)) == NULL)
319
err(EXIT_FAILURE, "strdup");
320
if (found_ranges) {
321
f->ranges = ranges;
322
f->ranges_cnt = ranges_cnt;
323
} else {
324
f->lopc = lopc;
325
f->hipc = hipc;
326
}
327
if (tag == DW_TAG_inlined_subroutine) {
328
f->inlined_caller = parent;
329
dwarf_attrval_unsigned(die, DW_AT_call_file,
330
&f->call_file, &de);
331
dwarf_attrval_unsigned(die, DW_AT_call_line,
332
&f->call_line, &de);
333
}
334
STAILQ_INSERT_TAIL(&range->funclist, f, next);
335
}
336
337
cont_search:
338
339
/* Search children. */
340
ret = dwarf_child(die, &ret_die, &de);
341
if (ret == DW_DLV_ERROR)
342
warnx("dwarf_child: %s", dwarf_errmsg(de));
343
else if (ret == DW_DLV_OK) {
344
if (f != NULL)
345
collect_func(dbg, ret_die, f, range);
346
else
347
collect_func(dbg, ret_die, parent, range);
348
}
349
350
/* Search sibling. */
351
ret = dwarf_siblingof(dbg, die, &ret_die, &de);
352
if (ret == DW_DLV_ERROR)
353
warnx("dwarf_siblingof: %s", dwarf_errmsg(de));
354
else if (ret == DW_DLV_OK)
355
collect_func(dbg, ret_die, parent, range);
356
357
/* Cleanup */
358
if (die != range->die)
359
dwarf_dealloc(dbg, die, DW_DLA_DIE);
360
361
if (abst_die != NULL)
362
dwarf_dealloc(dbg, abst_die, DW_DLA_DIE);
363
364
if (spec_die != NULL)
365
dwarf_dealloc(dbg, spec_die, DW_DLA_DIE);
366
}
367
368
static void
369
print_inlines(struct range *range, struct Func *f, Dwarf_Unsigned call_file,
370
Dwarf_Unsigned call_line)
371
{
372
char demangled[1024];
373
char *file;
374
375
if (call_file > 0 && (Dwarf_Signed) call_file <= range->nsrcfiles)
376
file = range->srcfiles[call_file - 1];
377
else
378
file = unknown;
379
380
if (pretty_print)
381
printf(" (inlined by) ");
382
383
if (func) {
384
if (demangle && !elftc_demangle(f->name, demangled,
385
sizeof(demangled), 0)) {
386
if (pretty_print)
387
printf("%s at ", demangled);
388
else
389
printf("%s\n", demangled);
390
} else {
391
if (pretty_print)
392
printf("%s at ", f->name);
393
else
394
printf("%s\n", f->name);
395
}
396
}
397
(void) printf("%s:%ju\n", base ? basename(file) : file,
398
(uintmax_t) call_line);
399
400
if (f->inlined_caller != NULL)
401
print_inlines(range, f->inlined_caller, f->call_file,
402
f->call_line);
403
}
404
405
static struct range *
406
culookup(Dwarf_Unsigned addr)
407
{
408
struct range find, *res;
409
410
find.lopc = addr;
411
res = RB_NFIND(cutree, &cuhead, &find);
412
if (res != NULL) {
413
if (res->lopc != addr)
414
res = RB_PREV(cutree, &cuhead, res);
415
if (res != NULL && addr >= res->lopc && addr < res->hipc)
416
return (res);
417
} else {
418
res = RB_MAX(cutree, &cuhead);
419
if (res != NULL && addr >= res->lopc && addr < res->hipc)
420
return (res);
421
}
422
return (NULL);
423
}
424
425
/*
426
* When DW_AT_ranges, DW_AT_low_pc/DW_AT_high_pc are all absent, we check the
427
* children of cu die for labels. If the address falls into one of the labels
428
* ranges(aranges), return the label DIE.
429
*/
430
static int
431
check_labels(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Unsigned addr,
432
struct range **range) {
433
Dwarf_Addr start;
434
Dwarf_Arange *aranges;
435
Dwarf_Die prev_die, ret_die;
436
Dwarf_Error de;
437
Dwarf_Half tag;
438
Dwarf_Off die_off;
439
Dwarf_Unsigned lopc, length;
440
Dwarf_Signed arcnt;
441
struct range *labelp, **labels;
442
int i, j, label_cnt, ret;
443
444
prev_die = ret_die = NULL;
445
labels = NULL;
446
i = label_cnt = 0;
447
448
/* Find aranges. */
449
ret = dwarf_get_aranges(dbg, &aranges, &arcnt, &de);
450
if (ret != DW_DLV_OK && ret != DW_DLV_NO_ENTRY)
451
warnx("dwarf_get_aranges failed: %s", dwarf_errmsg(de));
452
453
/* Child of current CU. */
454
ret = dwarf_child(die, &prev_die, &de);
455
if (ret == DW_DLV_ERROR)
456
warnx("dwarf_child: %s", dwarf_errmsg(de));
457
458
/* Count labels. */
459
while (1) {
460
if (dwarf_tag(prev_die, &tag, &de) != DW_DLV_OK) {
461
warnx("dwarf_tag failed: %s",
462
dwarf_errmsg(de));
463
return DW_DLV_ERROR;
464
}
465
if (tag == DW_TAG_label) {
466
if (dwarf_attrval_unsigned(prev_die, DW_AT_low_pc,
467
&lopc, &de) == DW_DLV_OK)
468
label_cnt++;
469
}
470
471
if (dwarf_siblingof(dbg, prev_die, &ret_die, &de) != DW_DLV_OK)
472
break;
473
474
if (prev_die != NULL)
475
dwarf_dealloc(dbg, prev_die, DW_DLA_DIE);
476
prev_die = ret_die;
477
}
478
479
if (label_cnt == 0)
480
return (DW_DLV_NO_ENTRY);
481
482
/* Allocate space for labels. */
483
if ((labels = calloc(label_cnt, sizeof(struct range *))) == NULL)
484
err(EXIT_FAILURE, "calloc");
485
486
/* Add labels to list. */
487
ret = dwarf_child(die, &prev_die, &de);
488
if (ret == DW_DLV_ERROR)
489
warnx("dwarf_child: %s", dwarf_errmsg(de));
490
while (1) {
491
if (dwarf_tag(prev_die, &tag, &de) != DW_DLV_OK) {
492
warnx("dwarf_tag failed: %s",
493
dwarf_errmsg(de));
494
free(labels);
495
return DW_DLV_ERROR;
496
}
497
if (tag == DW_TAG_label) {
498
if (dwarf_attrval_unsigned(prev_die, DW_AT_low_pc,
499
&lopc, &de) == DW_DLV_OK) {
500
if (curlopc == lopc) {
501
for (i = 0; i < label_cnt - 1; i++) {
502
if (labels[i] != *range)
503
free(labels[i]);
504
}
505
free(labels);
506
return DW_DLV_ERROR;
507
}
508
labelp = calloc(1, sizeof(struct range));
509
if (labelp == NULL)
510
err(EXIT_FAILURE, "calloc");
511
labelp->lopc = lopc;
512
labelp->die = prev_die;
513
labelp->dbg = dbg;
514
STAILQ_INIT(&labelp->funclist);
515
labels[i++] = labelp;
516
}
517
}
518
if (dwarf_siblingof(dbg, prev_die, &ret_die, &de) != DW_DLV_OK)
519
break;
520
if (prev_die != NULL && tag != DW_TAG_label)
521
dwarf_dealloc(dbg, prev_die, DW_DLA_DIE);
522
prev_die = ret_die;
523
}
524
525
/* Set hipc for each label using aranges */
526
for (i = 0; i < label_cnt; i++) {
527
for (j = 0; j < arcnt; j++) {
528
if (dwarf_get_arange_info(aranges[j], &start, &length,
529
&die_off, &de) != DW_DLV_OK) {
530
warnx("dwarf_get_arange_info failed: %s",
531
dwarf_errmsg(de));
532
continue;
533
}
534
if (labels[i]->lopc == (Dwarf_Unsigned)start) {
535
labels[i]->hipc = start + length;
536
break;
537
}
538
}
539
}
540
541
/* If addr in label's range, we have found the range for this label. */
542
for (i = 0; i < label_cnt; i++) {
543
if (addr >= labels[i]->lopc && addr < labels[i]->hipc) {
544
*range = labels[i];
545
RB_INSERT(cutree, &cuhead, (*range));
546
curlopc = (*range)->lopc;
547
break;
548
}
549
}
550
551
for (i = 0; i < label_cnt - 1; i++) {
552
if (labels[i] != *range)
553
free(labels[i]);
554
}
555
free(labels);
556
557
if (*range != NULL)
558
return (DW_DLV_OK);
559
else
560
return (DW_DLV_NO_ENTRY);
561
}
562
563
/*
564
* Check whether addr falls into range(s) of current CU.
565
* If so, save current CU to lookup tree.
566
*/
567
static int
568
check_range(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Unsigned addr,
569
struct range **range)
570
{
571
Dwarf_Error de;
572
Dwarf_Unsigned addr_base, lopc, hipc;
573
Dwarf_Off ranges_off;
574
Dwarf_Signed ranges_cnt;
575
Dwarf_Ranges *ranges;
576
int i, ret;
577
bool in_cu;
578
579
addr_base = 0;
580
ranges = NULL;
581
ranges_cnt = 0;
582
in_cu = false;
583
584
if (dwarf_attrval_unsigned(die, DW_AT_ranges, &ranges_off, &de) ==
585
DW_DLV_OK) {
586
ret = dwarf_get_ranges(dbg, ranges_off, &ranges,
587
&ranges_cnt, NULL, &de);
588
if (ret != DW_DLV_OK)
589
return (ret);
590
591
if (!ranges || ranges_cnt <= 0)
592
return (DW_DLV_ERROR);
593
594
for (i = 0; i < ranges_cnt; i++) {
595
if (ranges[i].dwr_type == DW_RANGES_END)
596
return (DW_DLV_NO_ENTRY);
597
598
if (ranges[i].dwr_type ==
599
DW_RANGES_ADDRESS_SELECTION) {
600
addr_base = ranges[i].dwr_addr2;
601
continue;
602
}
603
604
/* DW_RANGES_ENTRY */
605
lopc = ranges[i].dwr_addr1 + addr_base;
606
hipc = ranges[i].dwr_addr2 + addr_base;
607
608
if (lopc == curlopc)
609
return (DW_DLV_ERROR);
610
611
if (addr >= lopc && addr < hipc){
612
in_cu = true;
613
break;
614
}
615
}
616
} else if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) ==
617
DW_DLV_OK) {
618
if (lopc == curlopc)
619
return (DW_DLV_ERROR);
620
if (dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de) ==
621
DW_DLV_OK) {
622
/*
623
* Check if the address falls into the PC
624
* range of this CU.
625
*/
626
if (handle_high_pc(die, lopc, &hipc) != DW_DLV_OK)
627
return (DW_DLV_ERROR);
628
} else {
629
/* Assume ~0ULL if DW_AT_high_pc not present. */
630
hipc = ~0ULL;
631
}
632
633
if (addr >= lopc && addr < hipc) {
634
in_cu = true;
635
}
636
} else {
637
/* Addr not found above, try labels. */
638
ret = check_labels(dbg, die, addr, range);
639
return ret;
640
}
641
642
if (in_cu) {
643
if ((*range = calloc(1, sizeof(struct range))) == NULL)
644
err(EXIT_FAILURE, "calloc");
645
(*range)->lopc = lopc;
646
(*range)->hipc = hipc;
647
(*range)->die = die;
648
(*range)->dbg = dbg;
649
STAILQ_INIT(&(*range)->funclist);
650
RB_INSERT(cutree, &cuhead, *range);
651
curlopc = lopc;
652
return (DW_DLV_OK);
653
} else {
654
return (DW_DLV_NO_ENTRY);
655
}
656
}
657
658
static void
659
translate(Dwarf_Debug dbg, Elf *e, const char* addrstr)
660
{
661
Dwarf_Die die, ret_die;
662
Dwarf_Line *lbuf;
663
Dwarf_Error de;
664
Dwarf_Half tag;
665
Dwarf_Unsigned addr, lineno, plineno;
666
Dwarf_Signed lcount;
667
Dwarf_Addr lineaddr, plineaddr;
668
struct range *range;
669
struct Func *f;
670
const char *funcname;
671
char *file, *file0, *pfile;
672
char demangled[1024];
673
int ec, i, ret;
674
675
addr = strtoull(addrstr, NULL, 16);
676
addr += section_base;
677
lineno = 0;
678
file = unknown;
679
die = NULL;
680
ret = DW_DLV_OK;
681
682
range = culookup(addr);
683
if (range != NULL) {
684
die = range->die;
685
dbg = range->dbg;
686
goto status_ok;
687
}
688
689
while (true) {
690
/*
691
* We resume the CU scan from the last place we found a match.
692
* Because when we have 2 sequential addresses, and the second
693
* one is of the next CU, it is faster to just go to the next CU
694
* instead of starting from the beginning.
695
*/
696
ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL,
697
&de);
698
if (ret == DW_DLV_NO_ENTRY) {
699
if (curlopc == ~0ULL)
700
goto out;
701
ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL,
702
NULL, &de);
703
}
704
die = NULL;
705
while (dwarf_siblingof(dbg, die, &ret_die, &de) == DW_DLV_OK) {
706
if (die != NULL)
707
dwarf_dealloc(dbg, die, DW_DLA_DIE);
708
die = ret_die;
709
if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
710
warnx("dwarf_tag failed: %s",
711
dwarf_errmsg(de));
712
goto next_cu;
713
}
714
715
/* XXX: What about DW_TAG_partial_unit? */
716
if (tag == DW_TAG_compile_unit)
717
break;
718
}
719
720
if (ret_die == NULL) {
721
warnx("could not find DW_TAG_compile_unit die");
722
goto next_cu;
723
}
724
ret = check_range(dbg, die, addr, &range);
725
if (ret == DW_DLV_OK)
726
break;
727
if (ret == DW_DLV_ERROR)
728
goto out;
729
next_cu:
730
if (die != NULL) {
731
dwarf_dealloc(dbg, die, DW_DLA_DIE);
732
die = NULL;
733
}
734
}
735
736
if (ret != DW_DLV_OK || die == NULL)
737
goto out;
738
739
status_ok:
740
switch (dwarf_srclines(die, &lbuf, &lcount, &de)) {
741
case DW_DLV_OK:
742
break;
743
case DW_DLV_NO_ENTRY:
744
/* If a CU lacks debug info, just skip it. */
745
goto out;
746
default:
747
warnx("dwarf_srclines: %s", dwarf_errmsg(de));
748
goto out;
749
}
750
751
plineaddr = ~0ULL;
752
plineno = 0;
753
pfile = unknown;
754
for (i = 0; i < lcount; i++) {
755
if (dwarf_lineaddr(lbuf[i], &lineaddr, &de)) {
756
warnx("dwarf_lineaddr: %s", dwarf_errmsg(de));
757
goto out;
758
}
759
if (dwarf_lineno(lbuf[i], &lineno, &de)) {
760
warnx("dwarf_lineno: %s", dwarf_errmsg(de));
761
goto out;
762
}
763
if (dwarf_linesrc(lbuf[i], &file0, &de)) {
764
warnx("dwarf_linesrc: %s", dwarf_errmsg(de));
765
} else
766
file = file0;
767
if (addr == lineaddr)
768
goto out;
769
else if (addr < lineaddr && addr > plineaddr) {
770
lineno = plineno;
771
file = pfile;
772
goto out;
773
}
774
plineaddr = lineaddr;
775
plineno = lineno;
776
pfile = file;
777
}
778
779
out:
780
f = NULL;
781
funcname = NULL;
782
if (ret == DW_DLV_OK && (func || inlines) && range != NULL) {
783
if (range->srcfiles == NULL)
784
if (dwarf_srcfiles(die, &range->srcfiles,
785
&range->nsrcfiles, &de))
786
warnx("dwarf_srcfiles: %s", dwarf_errmsg(de));
787
if (STAILQ_EMPTY(&range->funclist)) {
788
collect_func(dbg, range->die, NULL, range);
789
die = NULL;
790
}
791
f = search_func(range, addr);
792
if (f != NULL)
793
funcname = f->name;
794
}
795
796
if (print_addr) {
797
if ((ec = gelf_getclass(e)) == ELFCLASSNONE) {
798
warnx("gelf_getclass failed: %s", elf_errmsg(-1));
799
ec = ELFCLASS64;
800
}
801
if (ec == ELFCLASS32) {
802
if (pretty_print)
803
printf("0x%08jx: ", (uintmax_t) addr);
804
else
805
printf("0x%08jx\n", (uintmax_t) addr);
806
} else {
807
if (pretty_print)
808
printf("0x%016jx: ", (uintmax_t) addr);
809
else
810
printf("0x%016jx\n", (uintmax_t) addr);
811
}
812
}
813
814
if (func) {
815
if (funcname == NULL)
816
funcname = unknown;
817
if (demangle && !elftc_demangle(funcname, demangled,
818
sizeof(demangled), 0)) {
819
if (pretty_print)
820
printf("%s at ", demangled);
821
else
822
printf("%s\n", demangled);
823
} else {
824
if (pretty_print)
825
printf("%s at ", funcname);
826
else
827
printf("%s\n", funcname);
828
}
829
}
830
831
(void) printf("%s:%ju\n", base ? basename(file) : file,
832
(uintmax_t) lineno);
833
834
if (ret == DW_DLV_OK && inlines && range != NULL &&
835
range->srcfiles != NULL && f != NULL && f->inlined_caller != NULL)
836
print_inlines(range, f->inlined_caller, f->call_file,
837
f->call_line);
838
}
839
840
static void
841
find_section_base(const char *exe, Elf *e, const char *section)
842
{
843
Dwarf_Addr off;
844
Elf_Scn *scn;
845
GElf_Ehdr eh;
846
GElf_Shdr sh;
847
size_t shstrndx;
848
int elferr;
849
const char *name;
850
851
if (gelf_getehdr(e, &eh) != &eh) {
852
warnx("gelf_getehdr failed: %s", elf_errmsg(-1));
853
return;
854
}
855
856
if (!elf_getshstrndx(e, &shstrndx)) {
857
warnx("elf_getshstrndx failed: %s", elf_errmsg(-1));
858
return;
859
}
860
861
(void) elf_errno();
862
off = 0;
863
scn = NULL;
864
while ((scn = elf_nextscn(e, scn)) != NULL) {
865
if (gelf_getshdr(scn, &sh) == NULL) {
866
warnx("gelf_getshdr failed: %s", elf_errmsg(-1));
867
continue;
868
}
869
if ((name = elf_strptr(e, shstrndx, sh.sh_name)) == NULL)
870
goto next;
871
if (!strcmp(section, name)) {
872
if (eh.e_type == ET_EXEC || eh.e_type == ET_DYN) {
873
/*
874
* For executables, section base is the virtual
875
* address of the specified section.
876
*/
877
section_base = sh.sh_addr;
878
} else if (eh.e_type == ET_REL) {
879
/*
880
* For relocatables, section base is the
881
* relative offset of the specified section
882
* to the start of the first section.
883
*/
884
section_base = off;
885
} else
886
warnx("unknown e_type %u", eh.e_type);
887
return;
888
}
889
next:
890
off += sh.sh_size;
891
}
892
elferr = elf_errno();
893
if (elferr != 0)
894
warnx("elf_nextscn failed: %s", elf_errmsg(elferr));
895
896
errx(EXIT_FAILURE, "%s: cannot find section %s", exe, section);
897
}
898
899
int
900
main(int argc, char **argv)
901
{
902
cap_rights_t rights;
903
Elf *e;
904
Dwarf_Debug dbg;
905
Dwarf_Error de;
906
const char *exe, *section;
907
char line[1024];
908
int fd, i, opt;
909
910
exe = NULL;
911
section = NULL;
912
while ((opt = getopt_long(argc, argv, "ab:Ce:fij:psHV", longopts,
913
NULL)) != -1) {
914
switch (opt) {
915
case 'a':
916
print_addr = 1;
917
break;
918
case 'b':
919
/* ignored */
920
break;
921
case 'C':
922
demangle = 1;
923
break;
924
case 'e':
925
exe = optarg;
926
break;
927
case 'f':
928
func = 1;
929
break;
930
case 'i':
931
inlines = 1;
932
break;
933
case 'j':
934
section = optarg;
935
break;
936
case 'p':
937
pretty_print = 1;
938
break;
939
case 's':
940
base = 1;
941
break;
942
case 'H':
943
usage();
944
case 'V':
945
version();
946
default:
947
usage();
948
}
949
}
950
951
argv += optind;
952
argc -= optind;
953
954
if (exe == NULL)
955
exe = "a.out";
956
957
if ((fd = open(exe, O_RDONLY)) < 0)
958
err(EXIT_FAILURE, "%s", exe);
959
960
if (caph_rights_limit(fd, cap_rights_init(&rights, CAP_FSTAT,
961
CAP_MMAP_R)) < 0)
962
errx(EXIT_FAILURE, "caph_rights_limit");
963
964
caph_cache_catpages();
965
if (caph_limit_stdio() < 0)
966
errx(EXIT_FAILURE, "failed to limit stdio rights");
967
if (caph_enter() < 0)
968
errx(EXIT_FAILURE, "failed to enter capability mode");
969
970
if (dwarf_init(fd, DW_DLC_READ, NULL, NULL, &dbg, &de))
971
errx(EXIT_FAILURE, "dwarf_init: %s", dwarf_errmsg(de));
972
973
if (dwarf_get_elf(dbg, &e, &de) != DW_DLV_OK)
974
errx(EXIT_FAILURE, "dwarf_get_elf: %s", dwarf_errmsg(de));
975
976
if (section)
977
find_section_base(exe, e, section);
978
else
979
section_base = 0;
980
981
if (argc > 0)
982
for (i = 0; i < argc; i++)
983
translate(dbg, e, argv[i]);
984
else {
985
setvbuf(stdout, NULL, _IOLBF, 0);
986
while (fgets(line, sizeof(line), stdin) != NULL)
987
translate(dbg, e, line);
988
}
989
990
dwarf_finish(dbg, &de);
991
992
(void) elf_end(e);
993
994
exit(0);
995
}
996
997