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 405 dwarf_finish(dbg, &de); 406 407 (void) elf_end(e); 408 409 exit(0); 410 } 411