]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/elftoolchain/addr2line/addr2line.c
Merge llvm 3.6.0rc2 from ^/vendor/llvm/dist, merge clang 3.6.0rc2 from
[FreeBSD/FreeBSD.git] / contrib / elftoolchain / addr2line / addr2line.c
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/cdefs.h>
28 #include <sys/param.h>
29 #include <dwarf.h>
30 #include <err.h>
31 #include <fcntl.h>
32 #include <gelf.h>
33 #include <getopt.h>
34 #include <libdwarf.h>
35 #include <libelftc.h>
36 #include <libgen.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41 #include "_elftc.h"
42
43 ELFTC_VCSID("$Id: addr2line.c 2185 2011-11-19 16:07:16Z jkoshy $");
44
45 static struct option longopts[] = {
46         {"target" , required_argument, NULL, 'b'},
47         {"demangle", no_argument, NULL, 'C'},
48         {"exe", required_argument, NULL, 'e'},
49         {"functions", no_argument, NULL, 'f'},
50         {"section", required_argument, NULL, 'j'},
51         {"basename", no_argument, NULL, 's'},
52         {"help", no_argument, NULL, 'H'},
53         {"version", no_argument, NULL, 'V'},
54         {NULL, 0, NULL, 0}
55 };
56 static int demangle, func, base;
57 static char unknown[] = { '?', '?', '\0' };
58 static Dwarf_Addr section_base;
59
60 #define USAGE_MESSAGE   "\
61 Usage: %s [options] hexaddress...\n\
62   Map program addresses to source file names and line numbers.\n\n\
63   Options:\n\
64   -b TGT  | --target=TGT      (Accepted but ignored).\n\
65   -e EXE  | --exec=EXE        Use program \"EXE\" to translate addresses.\n\
66   -f      | --functions       Display function names.\n\
67   -j NAME | --section=NAME    Values are offsets into section \"NAME\".\n\
68   -s      | --basename        Only show the base name for each file name.\n\
69   -C      | --demangle        Demangle C++ names.\n\
70   -H      | --help            Print a help message.\n\
71   -V      | --version         Print a version identifier and exit.\n"
72
73 static void
74 usage(void)
75 {
76         (void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
77         exit(1);
78 }
79
80 static void
81 version(void)
82 {
83
84         fprintf(stderr, "%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version());
85         exit(0);
86 }
87
88 static void
89 search_func(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr addr,
90     const char **rlt_func)
91 {
92         Dwarf_Die ret_die, spec_die;
93         Dwarf_Error de;
94         Dwarf_Half tag;
95         Dwarf_Unsigned lopc, hipc;
96         Dwarf_Off ref;
97         Dwarf_Attribute sub_at, spec_at;
98         char *func0;
99         int ret;
100
101         if (*rlt_func != NULL)
102                 return;
103
104         if (dwarf_tag(die, &tag, &de)) {
105                 warnx("dwarf_tag: %s", dwarf_errmsg(de));
106                 goto cont_search;
107         }
108         if (tag == DW_TAG_subprogram) {
109                 if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) ||
110                     dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de))
111                         goto cont_search;
112                 if (addr < lopc || addr >= hipc)
113                         goto cont_search;
114
115                 /* Found it! */
116
117                 *rlt_func = unknown;
118                 ret = dwarf_attr(die, DW_AT_name, &sub_at, &de);
119                 if (ret == DW_DLV_ERROR)
120                         return;
121                 if (ret == DW_DLV_OK) {
122                         if (dwarf_formstring(sub_at, &func0, &de))
123                                 *rlt_func = unknown;
124                         else
125                                 *rlt_func = func0;
126                         return;
127                 }
128
129                 /*
130                  * If DW_AT_name is not present, but DW_AT_specification is
131                  * present, then probably the actual name is in the DIE
132                  * referenced by DW_AT_specification.
133                  */
134                 if (dwarf_attr(die, DW_AT_specification, &spec_at, &de))
135                         return;
136                 if (dwarf_global_formref(spec_at, &ref, &de))
137                         return;
138                 if (dwarf_offdie(dbg, ref, &spec_die, &de))
139                         return;
140                 if (dwarf_attrval_string(spec_die, DW_AT_name, rlt_func, &de))
141                         *rlt_func = unknown;
142
143                 return;
144         }
145
146 cont_search:
147
148         /* Search children. */
149         ret = dwarf_child(die, &ret_die, &de);
150         if (ret == DW_DLV_ERROR)
151                 errx(EXIT_FAILURE, "dwarf_child: %s", dwarf_errmsg(de));
152         else if (ret == DW_DLV_OK)
153                 search_func(dbg, ret_die, addr, rlt_func);
154
155         /* Search sibling. */
156         ret = dwarf_siblingof(dbg, die, &ret_die, &de);
157         if (ret == DW_DLV_ERROR)
158                 errx(EXIT_FAILURE, "dwarf_siblingof: %s", dwarf_errmsg(de));
159         else if (ret == DW_DLV_OK)
160                 search_func(dbg, ret_die, addr, rlt_func);
161 }
162
163 static void
164 translate(Dwarf_Debug dbg, const char* addrstr)
165 {
166         Dwarf_Die die;
167         Dwarf_Line *lbuf;
168         Dwarf_Error de;
169         Dwarf_Half tag;
170         Dwarf_Unsigned lopc, hipc, addr, lineno, plineno;
171         Dwarf_Signed lcount;
172         Dwarf_Addr lineaddr, plineaddr;
173         const char *funcname;
174         char *file, *file0, *pfile;
175         char demangled[1024];
176         int i, ret;
177
178         addr = strtoull(addrstr, NULL, 16);
179         addr += section_base;
180         lineno = 0;
181         file = unknown;
182
183         while ((ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL,
184             &de)) ==  DW_DLV_OK) {
185                 die = NULL;
186                 while (dwarf_siblingof(dbg, die, &die, &de) == DW_DLV_OK) {
187                         if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
188                                 warnx("dwarf_tag failed: %s",
189                                     dwarf_errmsg(de));
190                                 goto out;
191                         }
192                         /* XXX: What about DW_TAG_partial_unit? */
193                         if (tag == DW_TAG_compile_unit)
194                                 break;
195                 }
196                 if (die == NULL) {
197                         warnx("could not find DW_TAG_compile_unit die");
198                         goto out;
199                 }
200                 if (!dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) &&
201                     !dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de)) {
202                         /*
203                          * Check if the address falls into the PC range of
204                          * this CU.
205                          */
206                         if (addr < lopc || addr >= hipc)
207                                 continue;
208                 }
209
210                 if (dwarf_srclines(die, &lbuf, &lcount, &de) != DW_DLV_OK) {
211                         warnx("dwarf_srclines: %s", dwarf_errmsg(de));
212                         goto out;
213                 }
214
215                 plineaddr = ~0ULL;
216                 plineno = 0;
217                 pfile = unknown;
218                 for (i = 0; i < lcount; i++) {
219                         if (dwarf_lineaddr(lbuf[i], &lineaddr, &de)) {
220                                 warnx("dwarf_lineaddr: %s",
221                                     dwarf_errmsg(de));
222                                 goto out;
223                         }
224                         if (dwarf_lineno(lbuf[i], &lineno, &de)) {
225                                 warnx("dwarf_lineno: %s",
226                                     dwarf_errmsg(de));
227                                 goto out;
228                         }
229                         if (dwarf_linesrc(lbuf[i], &file0, &de)) {
230                                 warnx("dwarf_linesrc: %s",
231                                     dwarf_errmsg(de));
232                         } else
233                                 file = file0;
234                         if (addr == lineaddr)
235                                 goto out;
236                         else if (addr < lineaddr && addr > plineaddr) {
237                                 lineno = plineno;
238                                 file = pfile;
239                                 goto out;
240                         }
241                         plineaddr = lineaddr;
242                         plineno = lineno;
243                         pfile = file;
244                 }
245         }
246
247 out:
248         funcname = NULL;
249         if (ret == DW_DLV_OK && func)
250                 search_func(dbg, die, addr, &funcname);
251
252         if (func) {
253                 if (funcname == NULL)
254                         funcname = unknown;
255                 if (demangle &&
256                     !elftc_demangle(funcname, demangled, sizeof(demangled), 0))
257                         printf("%s\n", demangled);
258                 else
259                         printf("%s\n", funcname);
260         }
261
262         (void) printf("%s:%ju\n", base ? basename(file) : file, lineno);
263
264         /*
265          * Reset internal CU pointer, so we will start from the first CU
266          * next round.
267          */
268         while (ret != DW_DLV_NO_ENTRY) {
269                 if (ret == DW_DLV_ERROR)
270                         errx(EXIT_FAILURE, "dwarf_next_cu_header: %s",
271                             dwarf_errmsg(de));
272                 ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL,
273                     &de);
274         }
275 }
276
277 static void
278 find_section_base(const char *exe, Elf *e, const char *section)
279 {
280         Dwarf_Addr off;
281         Elf_Scn *scn;
282         GElf_Ehdr eh;
283         GElf_Shdr sh;
284         size_t shstrndx;
285         int elferr;
286         const char *name;
287
288         if (gelf_getehdr(e, &eh) != &eh) {
289                 warnx("gelf_getehdr failed: %s", elf_errmsg(-1));
290                 return;
291         }
292
293         if (!elf_getshstrndx(e, &shstrndx)) {
294                 warnx("elf_getshstrndx failed: %s", elf_errmsg(-1));
295                 return;
296         }
297
298         (void) elf_errno();
299         off = 0;
300         scn = NULL;
301         while ((scn = elf_nextscn(e, scn)) != NULL) {
302                 if (gelf_getshdr(scn, &sh) == NULL) {
303                         warnx("gelf_getshdr failed: %s", elf_errmsg(-1));
304                         continue;
305                 }
306                 if ((name = elf_strptr(e, shstrndx, sh.sh_name)) == NULL)
307                         goto next;
308                 if (!strcmp(section, name)) {
309                         if (eh.e_type == ET_EXEC || eh.e_type == ET_DYN) {
310                                 /*
311                                  * For executables, section base is the virtual
312                                  * address of the specified section.
313                                  */
314                                 section_base = sh.sh_addr;
315                         } else if (eh.e_type == ET_REL) {
316                                 /*
317                                  * For relocatables, section base is the
318                                  * relative offset of the specified section
319                                  * to the start of the first section.
320                                  */
321                                 section_base = off;
322                         } else
323                                 warnx("unknown e_type %u", eh.e_type);
324                         return;
325                 }
326         next:
327                 off += sh.sh_size;
328         }
329         elferr = elf_errno();
330         if (elferr != 0)
331                 warnx("elf_nextscn failed: %s", elf_errmsg(elferr));
332
333         errx(EXIT_FAILURE, "%s: cannot find section %s", exe, section);
334 }
335
336 int
337 main(int argc, char **argv)
338 {
339         Elf *e;
340         Dwarf_Debug dbg;
341         Dwarf_Error de;
342         const char *exe, *section;
343         char line[1024];
344         int fd, i, opt;
345
346         exe = NULL;
347         section = NULL;
348         while ((opt = getopt_long(argc, argv, "b:Ce:fj:sHV", longopts, NULL)) !=
349             -1) {
350                 switch (opt) {
351                 case 'b':
352                         /* ignored */
353                         break;
354                 case 'C':
355                         demangle = 1;
356                         break;
357                 case 'e':
358                         exe = optarg;
359                         break;
360                 case 'f':
361                         func = 1;
362                         break;
363                 case 'j':
364                         section = optarg;
365                         break;
366                 case 's':
367                         base = 1;
368                         break;
369                 case 'H':
370                         usage();
371                 case 'V':
372                         version();
373                 default:
374                         usage();
375                 }
376         }
377
378         argv += optind;
379         argc -= optind;
380
381         if (exe == NULL)
382                 exe = "a.out";
383
384         if ((fd = open(exe, O_RDONLY)) < 0)
385                 err(EXIT_FAILURE, "%s", exe);
386
387         if (dwarf_init(fd, DW_DLC_READ, NULL, NULL, &dbg, &de))
388                 errx(EXIT_FAILURE, "dwarf_init: %s", dwarf_errmsg(de));
389
390         if (dwarf_get_elf(dbg, &e, &de) != DW_DLV_OK)
391                 errx(EXIT_FAILURE, "dwarf_get_elf: %s", dwarf_errmsg(de));
392
393         if (section)
394                 find_section_base(exe, e, section);
395         else
396                 section_base = 0;
397
398         if (argc > 0)
399                 for (i = 0; i < argc; i++)
400                         translate(dbg, argv[i]);
401         else
402                 while (fgets(line, sizeof(line), stdin) != NULL) {
403                         translate(dbg, line);
404                         fflush(stdout);
405                 }
406
407         dwarf_finish(dbg, &de);
408
409         (void) elf_end(e);
410
411         exit(0);
412 }