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 3249 2015-10-04 08:11:30Z kaiwang27 $"); 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 | --exe=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, char **rlt_func) 127 { 128 Dwarf_Die ret_die, spec_die; 129 Dwarf_Error de; 130 Dwarf_Half tag; 131 Dwarf_Unsigned lopc, hipc; 132 Dwarf_Off ref; 133 Dwarf_Attribute sub_at, spec_at; 134 char *func0; 135 const char *func1; 136 int ret; 137 138 if (*rlt_func != NULL) 139 goto done; 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 if ((*rlt_func = strdup(unknown)) == NULL) 157 err(EXIT_FAILURE, "strdup"); 158 ret = dwarf_attr(die, DW_AT_name, &sub_at, &de); 159 if (ret == DW_DLV_ERROR) 160 goto done; 161 if (ret == DW_DLV_OK) { 162 if (dwarf_formstring(sub_at, &func0, &de) == 163 DW_DLV_OK) { 164 free(*rlt_func); 165 if ((*rlt_func = strdup(func0)) == NULL) 166 err(EXIT_FAILURE, "strdup"); 167 } 168 goto done; 169 } 170 171 /* 172 * If DW_AT_name is not present, but DW_AT_specification is 173 * present, then probably the actual name is in the DIE 174 * referenced by DW_AT_specification. 175 */ 176 if (dwarf_attr(die, DW_AT_specification, &spec_at, &de)) 177 goto done; 178 if (dwarf_global_formref(spec_at, &ref, &de)) 179 goto done; 180 if (dwarf_offdie(dbg, ref, &spec_die, &de)) 181 goto done; 182 if (dwarf_attrval_string(spec_die, DW_AT_name, &func1, &de) == 183 DW_DLV_OK) { 184 free(*rlt_func); 185 if ((*rlt_func = strdup(func1)) == NULL) 186 err(EXIT_FAILURE, "strdup"); 187 } 188 189 goto done; 190 } 191 192 cont_search: 193 194 /* Search children. */ 195 ret = dwarf_child(die, &ret_die, &de); 196 if (ret == DW_DLV_ERROR) 197 errx(EXIT_FAILURE, "dwarf_child: %s", dwarf_errmsg(de)); 198 else if (ret == DW_DLV_OK) 199 search_func(dbg, ret_die, addr, rlt_func); 200 201 /* Search sibling. */ 202 ret = dwarf_siblingof(dbg, die, &ret_die, &de); 203 if (ret == DW_DLV_ERROR) 204 errx(EXIT_FAILURE, "dwarf_siblingof: %s", dwarf_errmsg(de)); 205 else if (ret == DW_DLV_OK) 206 search_func(dbg, ret_die, addr, rlt_func); 207 208 done: 209 dwarf_dealloc(dbg, die, DW_DLA_DIE); 210 } 211 212 static void 213 translate(Dwarf_Debug dbg, const char* addrstr) 214 { 215 Dwarf_Die die, ret_die; 216 Dwarf_Line *lbuf; 217 Dwarf_Error de; 218 Dwarf_Half tag; 219 Dwarf_Unsigned lopc, hipc, addr, lineno, plineno; 220 Dwarf_Signed lcount; 221 Dwarf_Addr lineaddr, plineaddr; 222 char *funcname; 223 char *file, *file0, *pfile; 224 char demangled[1024]; 225 int i, ret; 226 227 addr = strtoull(addrstr, NULL, 16); 228 addr += section_base; 229 lineno = 0; 230 file = unknown; 231 die = NULL; 232 lbuf = NULL; 233 lcount = 0; 234 235 while ((ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL, 236 &de)) == DW_DLV_OK) { 237 die = NULL; 238 while (dwarf_siblingof(dbg, die, &ret_die, &de) == DW_DLV_OK) { 239 if (die != NULL) 240 dwarf_dealloc(dbg, die, DW_DLA_DIE); 241 die = ret_die; 242 if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { 243 warnx("dwarf_tag failed: %s", 244 dwarf_errmsg(de)); 245 goto next_cu; 246 } 247 248 /* XXX: What about DW_TAG_partial_unit? */ 249 if (tag == DW_TAG_compile_unit) 250 break; 251 } 252 if (ret_die == NULL) { 253 warnx("could not find DW_TAG_compile_unit die"); 254 goto next_cu; 255 } 256 if (!dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) && 257 !dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de)) { 258 /* 259 * Check if the address falls into the PC range of 260 * this CU. 261 */ 262 if (handle_high_pc(die, lopc, &hipc) != DW_DLV_OK) 263 goto next_cu; 264 if (addr < lopc || addr >= hipc) 265 goto next_cu; 266 } 267 268 switch (dwarf_srclines(die, &lbuf, &lcount, &de)) { 269 case DW_DLV_OK: 270 break; 271 case DW_DLV_NO_ENTRY: 272 /* If a CU lacks debug info, just skip it. */ 273 goto next_cu; 274 default: 275 warnx("dwarf_srclines: %s", dwarf_errmsg(de)); 276 goto out; 277 } 278 279 plineaddr = ~0ULL; 280 plineno = 0; 281 pfile = unknown; 282 for (i = 0; i < lcount; i++) { 283 if (dwarf_lineaddr(lbuf[i], &lineaddr, &de)) { 284 warnx("dwarf_lineaddr: %s", 285 dwarf_errmsg(de)); 286 goto out; 287 } 288 if (dwarf_lineno(lbuf[i], &lineno, &de)) { 289 warnx("dwarf_lineno: %s", 290 dwarf_errmsg(de)); 291 goto out; 292 } 293 if (dwarf_linesrc(lbuf[i], &file0, &de)) { 294 warnx("dwarf_linesrc: %s", 295 dwarf_errmsg(de)); 296 } else 297 file = file0; 298 if (addr == lineaddr) 299 goto out; 300 else if (addr < lineaddr && addr > plineaddr) { 301 lineno = plineno; 302 file = pfile; 303 goto out; 304 } 305 plineaddr = lineaddr; 306 plineno = lineno; 307 pfile = file; 308 } 309 next_cu: 310 if (die != NULL) { 311 dwarf_dealloc(dbg, die, DW_DLA_DIE); 312 die = NULL; 313 } 314 } 315 316 out: 317 funcname = NULL; 318 if (ret == DW_DLV_OK && func) { 319 search_func(dbg, die, addr, &funcname); 320 die = NULL; 321 } 322 323 if (func) { 324 if (funcname == NULL) 325 if ((funcname = strdup(unknown)) == NULL) 326 err(EXIT_FAILURE, "strdup"); 327 if (demangle && 328 !elftc_demangle(funcname, demangled, sizeof(demangled), 0)) 329 printf("%s\n", demangled); 330 else 331 printf("%s\n", funcname); 332 free(funcname); 333 } 334 335 (void) printf("%s:%ju\n", base ? basename(file) : file, lineno); 336 337 if (die != NULL) 338 dwarf_dealloc(dbg, die, DW_DLA_DIE); 339 340 /* 341 * Reset internal CU pointer, so we will start from the first CU 342 * next round. 343 */ 344 while (ret != DW_DLV_NO_ENTRY) { 345 if (ret == DW_DLV_ERROR) 346 errx(EXIT_FAILURE, "dwarf_next_cu_header: %s", 347 dwarf_errmsg(de)); 348 ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL, 349 &de); 350 } 351 } 352 353 static void 354 find_section_base(const char *exe, Elf *e, const char *section) 355 { 356 Dwarf_Addr off; 357 Elf_Scn *scn; 358 GElf_Ehdr eh; 359 GElf_Shdr sh; 360 size_t shstrndx; 361 int elferr; 362 const char *name; 363 364 if (gelf_getehdr(e, &eh) != &eh) { 365 warnx("gelf_getehdr failed: %s", elf_errmsg(-1)); 366 return; 367 } 368 369 if (!elf_getshstrndx(e, &shstrndx)) { 370 warnx("elf_getshstrndx failed: %s", elf_errmsg(-1)); 371 return; 372 } 373 374 (void) elf_errno(); 375 off = 0; 376 scn = NULL; 377 while ((scn = elf_nextscn(e, scn)) != NULL) { 378 if (gelf_getshdr(scn, &sh) == NULL) { 379 warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); 380 continue; 381 } 382 if ((name = elf_strptr(e, shstrndx, sh.sh_name)) == NULL) 383 goto next; 384 if (!strcmp(section, name)) { 385 if (eh.e_type == ET_EXEC || eh.e_type == ET_DYN) { 386 /* 387 * For executables, section base is the virtual 388 * address of the specified section. 389 */ 390 section_base = sh.sh_addr; 391 } else if (eh.e_type == ET_REL) { 392 /* 393 * For relocatables, section base is the 394 * relative offset of the specified section 395 * to the start of the first section. 396 */ 397 section_base = off; 398 } else 399 warnx("unknown e_type %u", eh.e_type); 400 return; 401 } 402 next: 403 off += sh.sh_size; 404 } 405 elferr = elf_errno(); 406 if (elferr != 0) 407 warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); 408 409 errx(EXIT_FAILURE, "%s: cannot find section %s", exe, section); 410 } 411 412 int 413 main(int argc, char **argv) 414 { 415 Elf *e; 416 Dwarf_Debug dbg; 417 Dwarf_Error de; 418 const char *exe, *section; 419 char line[1024]; 420 int fd, i, opt; 421 422 exe = NULL; 423 section = NULL; 424 while ((opt = getopt_long(argc, argv, "b:Ce:fj:sHV", longopts, NULL)) != 425 -1) { 426 switch (opt) { 427 case 'b': 428 /* ignored */ 429 break; 430 case 'C': 431 demangle = 1; 432 break; 433 case 'e': 434 exe = optarg; 435 break; 436 case 'f': 437 func = 1; 438 break; 439 case 'j': 440 section = optarg; 441 break; 442 case 's': 443 base = 1; 444 break; 445 case 'H': 446 usage(); 447 case 'V': 448 version(); 449 default: 450 usage(); 451 } 452 } 453 454 argv += optind; 455 argc -= optind; 456 457 if (exe == NULL) 458 exe = "a.out"; 459 460 if ((fd = open(exe, O_RDONLY)) < 0) 461 err(EXIT_FAILURE, "%s", exe); 462 463 if (dwarf_init(fd, DW_DLC_READ, NULL, NULL, &dbg, &de)) 464 errx(EXIT_FAILURE, "dwarf_init: %s", dwarf_errmsg(de)); 465 466 if (dwarf_get_elf(dbg, &e, &de) != DW_DLV_OK) 467 errx(EXIT_FAILURE, "dwarf_get_elf: %s", dwarf_errmsg(de)); 468 469 if (section) 470 find_section_base(exe, e, section); 471 else 472 section_base = 0; 473 474 if (argc > 0) 475 for (i = 0; i < argc; i++) 476 translate(dbg, argv[i]); 477 else 478 while (fgets(line, sizeof(line), stdin) != NULL) { 479 translate(dbg, line); 480 fflush(stdout); 481 } 482 483 dwarf_finish(dbg, &de); 484 485 (void) elf_end(e); 486 487 exit(0); 488 } 489