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
46ELFTC_VCSID("$Id: addr2line.c 3499 2016-11-25 16:06:29Z emaste $");
47
48struct 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
60struct 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
72static 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
87static int demangle, func, base, inlines, print_addr, pretty_print;
88static char unknown[] = { '?', '?', '\0' };
89static Dwarf_Addr section_base;
90/* Need a new curlopc that stores last lopc value. */
91static Dwarf_Unsigned curlopc = ~0ULL;
92static RB_HEAD(cutree, range) cuhead = RB_INITIALIZER(&cuhead);
93
94static int
95lopccmp(struct range *e1, struct range *e2)
96{
97	return (e1->lopc < e2->lopc ? -1 : e1->lopc > e2->lopc);
98}
99
100RB_PROTOTYPE(cutree, range, entry, lopccmp);
101RB_GENERATE(cutree, range, entry, lopccmp)
102
103#define	USAGE_MESSAGE	"\
104Usage: %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
120static void
121usage(void)
122{
123	(void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
124	exit(1);
125}
126
127static void
128version(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 */
149static int
150handle_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
173static struct Func *
174search_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
218static void
219collect_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
337cont_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
368static void
369print_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
405static struct range *
406culookup(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 */
430static int
431check_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 */
567static int
568check_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
658static void
659translate(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;
729next_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
739status_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
779out:
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
840static void
841find_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
899int
900main(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