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 3174 2015-03-27 17:13:41Z 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 static void 88 search_func(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr addr, 89 const char **rlt_func) 90 { 91 Dwarf_Die ret_die, spec_die; 92 Dwarf_Error de; 93 Dwarf_Half tag; 94 Dwarf_Unsigned lopc, hipc; 95 Dwarf_Off ref; 96 Dwarf_Attribute sub_at, spec_at; 97 char *func0; 98 int ret; 99 100 if (*rlt_func != NULL) 101 return; 102 103 if (dwarf_tag(die, &tag, &de)) { 104 warnx("dwarf_tag: %s", dwarf_errmsg(de)); 105 goto cont_search; 106 } 107 if (tag == DW_TAG_subprogram) { 108 if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) || 109 dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de)) 110 goto cont_search; 111 if (addr < lopc || addr >= hipc) 112 goto cont_search; 113 114 /* Found it! */ 115 116 *rlt_func = unknown; 117 ret = dwarf_attr(die, DW_AT_name, &sub_at, &de); 118 if (ret == DW_DLV_ERROR) 119 return; 120 if (ret == DW_DLV_OK) { 121 if (dwarf_formstring(sub_at, &func0, &de)) 122 *rlt_func = unknown; 123 else 124 *rlt_func = func0; 125 return; 126 } 127 128 /* 129 * If DW_AT_name is not present, but DW_AT_specification is 130 * present, then probably the actual name is in the DIE 131 * referenced by DW_AT_specification. 132 */ 133 if (dwarf_attr(die, DW_AT_specification, &spec_at, &de)) 134 return; 135 if (dwarf_global_formref(spec_at, &ref, &de)) 136 return; 137 if (dwarf_offdie(dbg, ref, &spec_die, &de)) 138 return; 139 if (dwarf_attrval_string(spec_die, DW_AT_name, rlt_func, &de)) 140 *rlt_func = unknown; 141 142 return; 143 } 144 145 cont_search: 146 147 /* Search children. */ 148 ret = dwarf_child(die, &ret_die, &de); 149 if (ret == DW_DLV_ERROR) 150 errx(EXIT_FAILURE, "dwarf_child: %s", dwarf_errmsg(de)); 151 else if (ret == DW_DLV_OK) 152 search_func(dbg, ret_die, addr, rlt_func); 153 154 /* Search sibling. */ 155 ret = dwarf_siblingof(dbg, die, &ret_die, &de); 156 if (ret == DW_DLV_ERROR) 157 errx(EXIT_FAILURE, "dwarf_siblingof: %s", dwarf_errmsg(de)); 158 else if (ret == DW_DLV_OK) 159 search_func(dbg, ret_die, addr, rlt_func); 160 } 161 162 static void 163 translate(Dwarf_Debug dbg, const char* addrstr) 164 { 165 Dwarf_Die die; 166 Dwarf_Line *lbuf; 167 Dwarf_Error de; 168 Dwarf_Half tag; 169 Dwarf_Unsigned lopc, hipc, addr, lineno, plineno; 170 Dwarf_Signed lcount; 171 Dwarf_Addr lineaddr, plineaddr; 172 const char *funcname; 173 char *file, *file0, *pfile; 174 char demangled[1024]; 175 int i, ret; 176 177 addr = strtoull(addrstr, NULL, 16); 178 addr += section_base; 179 lineno = 0; 180 file = unknown; 181 182 while ((ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL, 183 &de)) == DW_DLV_OK) { 184 die = NULL; 185 while (dwarf_siblingof(dbg, die, &die, &de) == DW_DLV_OK) { 186 if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { 187 warnx("dwarf_tag failed: %s", 188 dwarf_errmsg(de)); 189 goto out; 190 } 191 /* XXX: What about DW_TAG_partial_unit? */ 192 if (tag == DW_TAG_compile_unit) 193 break; 194 } 195 if (die == NULL) { 196 warnx("could not find DW_TAG_compile_unit die"); 197 goto out; 198 } 199 if (!dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) && 200 !dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de)) { 201 /* 202 * Check if the address falls into the PC range of 203 * this CU. 204 */ 205 if (addr < lopc || addr >= hipc) 206 continue; 207 } 208 209 if (dwarf_srclines(die, &lbuf, &lcount, &de) != DW_DLV_OK) { 210 warnx("dwarf_srclines: %s", dwarf_errmsg(de)); 211 goto out; 212 } 213 214 plineaddr = ~0ULL; 215 plineno = 0; 216 pfile = unknown; 217 for (i = 0; i < lcount; i++) { 218 if (dwarf_lineaddr(lbuf[i], &lineaddr, &de)) { 219 warnx("dwarf_lineaddr: %s", 220 dwarf_errmsg(de)); 221 goto out; 222 } 223 if (dwarf_lineno(lbuf[i], &lineno, &de)) { 224 warnx("dwarf_lineno: %s", 225 dwarf_errmsg(de)); 226 goto out; 227 } 228 if (dwarf_linesrc(lbuf[i], &file0, &de)) { 229 warnx("dwarf_linesrc: %s", 230 dwarf_errmsg(de)); 231 } else 232 file = file0; 233 if (addr == lineaddr) 234 goto out; 235 else if (addr < lineaddr && addr > plineaddr) { 236 lineno = plineno; 237 file = pfile; 238 goto out; 239 } 240 plineaddr = lineaddr; 241 plineno = lineno; 242 pfile = file; 243 } 244 } 245 246 out: 247 funcname = NULL; 248 if (ret == DW_DLV_OK && func) 249 search_func(dbg, die, addr, &funcname); 250 251 if (func) { 252 if (funcname == NULL) 253 funcname = unknown; 254 if (demangle && 255 !elftc_demangle(funcname, demangled, sizeof(demangled), 0)) 256 printf("%s\n", demangled); 257 else 258 printf("%s\n", funcname); 259 } 260 261 (void) printf("%s:%ju\n", base ? basename(file) : file, lineno); 262 263 /* 264 * Reset internal CU pointer, so we will start from the first CU 265 * next round. 266 */ 267 while (ret != DW_DLV_NO_ENTRY) { 268 if (ret == DW_DLV_ERROR) 269 errx(EXIT_FAILURE, "dwarf_next_cu_header: %s", 270 dwarf_errmsg(de)); 271 ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL, 272 &de); 273 } 274 } 275 276 static void 277 find_section_base(const char *exe, Elf *e, const char *section) 278 { 279 Dwarf_Addr off; 280 Elf_Scn *scn; 281 GElf_Ehdr eh; 282 GElf_Shdr sh; 283 size_t shstrndx; 284 int elferr; 285 const char *name; 286 287 if (gelf_getehdr(e, &eh) != &eh) { 288 warnx("gelf_getehdr failed: %s", elf_errmsg(-1)); 289 return; 290 } 291 292 if (!elf_getshstrndx(e, &shstrndx)) { 293 warnx("elf_getshstrndx failed: %s", elf_errmsg(-1)); 294 return; 295 } 296 297 (void) elf_errno(); 298 off = 0; 299 scn = NULL; 300 while ((scn = elf_nextscn(e, scn)) != NULL) { 301 if (gelf_getshdr(scn, &sh) == NULL) { 302 warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); 303 continue; 304 } 305 if ((name = elf_strptr(e, shstrndx, sh.sh_name)) == NULL) 306 goto next; 307 if (!strcmp(section, name)) { 308 if (eh.e_type == ET_EXEC || eh.e_type == ET_DYN) { 309 /* 310 * For executables, section base is the virtual 311 * address of the specified section. 312 */ 313 section_base = sh.sh_addr; 314 } else if (eh.e_type == ET_REL) { 315 /* 316 * For relocatables, section base is the 317 * relative offset of the specified section 318 * to the start of the first section. 319 */ 320 section_base = off; 321 } else 322 warnx("unknown e_type %u", eh.e_type); 323 return; 324 } 325 next: 326 off += sh.sh_size; 327 } 328 elferr = elf_errno(); 329 if (elferr != 0) 330 warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); 331 332 errx(EXIT_FAILURE, "%s: cannot find section %s", exe, section); 333 } 334 335 int 336 main(int argc, char **argv) 337 { 338 Elf *e; 339 Dwarf_Debug dbg; 340 Dwarf_Error de; 341 const char *exe, *section; 342 char line[1024]; 343 int fd, i, opt; 344 345 exe = NULL; 346 section = NULL; 347 while ((opt = getopt_long(argc, argv, "b:Ce:fj:sHV", longopts, NULL)) != 348 -1) { 349 switch (opt) { 350 case 'b': 351 /* ignored */ 352 break; 353 case 'C': 354 demangle = 1; 355 break; 356 case 'e': 357 exe = optarg; 358 break; 359 case 'f': 360 func = 1; 361 break; 362 case 'j': 363 section = optarg; 364 break; 365 case 's': 366 base = 1; 367 break; 368 case 'H': 369 usage(); 370 case 'V': 371 version(); 372 default: 373 usage(); 374 } 375 } 376 377 argv += optind; 378 argc -= optind; 379 380 if (exe == NULL) 381 exe = "a.out"; 382 383 if ((fd = open(exe, O_RDONLY)) < 0) 384 err(EXIT_FAILURE, "%s", exe); 385 386 if (dwarf_init(fd, DW_DLC_READ, NULL, NULL, &dbg, &de)) 387 errx(EXIT_FAILURE, "dwarf_init: %s", dwarf_errmsg(de)); 388 389 if (dwarf_get_elf(dbg, &e, &de) != DW_DLV_OK) 390 errx(EXIT_FAILURE, "dwarf_get_elf: %s", dwarf_errmsg(de)); 391 392 if (section) 393 find_section_base(exe, e, section); 394 else 395 section_base = 0; 396 397 if (argc > 0) 398 for (i = 0; i < argc; i++) 399 translate(dbg, argv[i]); 400 else 401 while (fgets(line, sizeof(line), stdin) != NULL) { 402 translate(dbg, line); 403 fflush(stdout); 404 } 405 406 dwarf_finish(dbg, &de); 407 408 (void) elf_end(e); 409 410 exit(0); 411 } 412