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