1/* Locate source files and line information for given addresses 2 Copyright (C) 2005-2010, 2012, 2013 Red Hat, Inc. 3 This file is part of elfutils. 4 Written by Ulrich Drepper <drepper@redhat.com>, 2005. 5 6 This file is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 elfutils is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 18 19#ifdef HAVE_CONFIG_H 20# include <config.h> 21#endif 22 23#include <argp.h> 24#include <assert.h> 25#include <errno.h> 26#include <error.h> 27#include <fcntl.h> 28#include <inttypes.h> 29#include <libdwfl.h> 30#include <dwarf.h> 31#include <libintl.h> 32#include <locale.h> 33#include <mcheck.h> 34#include <stdbool.h> 35#include <stdio.h> 36#include <stdio_ext.h> 37#include <stdlib.h> 38#include <string.h> 39#include <unistd.h> 40 41#include <system.h> 42 43 44/* Name and version of program. */ 45static void print_version (FILE *stream, struct argp_state *state); 46ARGP_PROGRAM_VERSION_HOOK_DEF = print_version; 47 48/* Bug report address. */ 49ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT; 50 51 52/* Values for the parameters which have no short form. */ 53#define OPT_DEMANGLER 0x100 54 55/* Definitions of arguments for argp functions. */ 56static const struct argp_option options[] = 57{ 58 { NULL, 0, NULL, 0, N_("Output selection options:"), 2 }, 59 { "basenames", 's', NULL, 0, N_("Show only base names of source files"), 0 }, 60 { "absolute", 'A', NULL, 0, 61 N_("Show absolute file names using compilation directory"), 0 }, 62 { "functions", 'f', NULL, 0, N_("Also show function names"), 0 }, 63 { "symbols", 'S', NULL, 0, N_("Also show symbol or section names"), 0 }, 64 { "symbols-sections", 'x', NULL, 0, N_("Also show symbol and the section names"), 0 }, 65 { "flags", 'F', NULL, 0, N_("Also show line table flags"), 0 }, 66 { "section", 'j', "NAME", 0, 67 N_("Treat addresses as offsets relative to NAME section."), 0 }, 68 { "inlines", 'i', NULL, 0, 69 N_("Show all source locations that caused inline expansion of subroutines at the address."), 70 0 }, 71 72 { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 }, 73 /* Unsupported options. */ 74 { "target", 'b', "ARG", OPTION_HIDDEN, NULL, 0 }, 75 { "demangle", 'C', "ARG", OPTION_HIDDEN | OPTION_ARG_OPTIONAL, NULL, 0 }, 76 { "demangler", OPT_DEMANGLER, "ARG", OPTION_HIDDEN, NULL, 0 }, 77 { NULL, 0, NULL, 0, NULL, 0 } 78}; 79 80/* Short description of program. */ 81static const char doc[] = N_("\ 82Locate source files and line information for ADDRs (in a.out by default)."); 83 84/* Strings for arguments in help texts. */ 85static const char args_doc[] = N_("[ADDR...]"); 86 87/* Prototype for option handler. */ 88static error_t parse_opt (int key, char *arg, struct argp_state *state); 89 90static struct argp_child argp_children[2]; /* [0] is set in main. */ 91 92/* Data structure to communicate with argp functions. */ 93static const struct argp argp = 94{ 95 options, parse_opt, args_doc, doc, argp_children, NULL, NULL 96}; 97 98 99/* Handle ADDR. */ 100static int handle_address (const char *addr, Dwfl *dwfl); 101 102 103/* True if only base names of files should be shown. */ 104static bool only_basenames; 105 106/* True if absolute file names based on DW_AT_comp_dir should be shown. */ 107static bool use_comp_dir; 108 109/* True if line flags should be shown. */ 110static bool show_flags; 111 112/* True if function names should be shown. */ 113static bool show_functions; 114 115/* True if ELF symbol or section info should be shown. */ 116static bool show_symbols; 117 118/* True if section associated with a symbol address should be shown. */ 119static bool show_symbol_sections; 120 121/* If non-null, take address parameters as relative to named section. */ 122static const char *just_section; 123 124/* True if all inlined subroutines of the current address should be shown. */ 125static bool show_inlines; 126 127 128int 129main (int argc, char *argv[]) 130{ 131 int remaining; 132 int result = 0; 133 134 /* Make memory leak detection possible. */ 135 mtrace (); 136 137 /* We use no threads here which can interfere with handling a stream. */ 138 (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER); 139 140 /* Set locale. */ 141 (void) setlocale (LC_ALL, ""); 142 143 /* Make sure the message catalog can be found. */ 144 (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR); 145 146 /* Initialize the message catalog. */ 147 (void) textdomain (PACKAGE_TARNAME); 148 149 /* Parse and process arguments. This includes opening the modules. */ 150 argp_children[0].argp = dwfl_standard_argp (); 151 argp_children[0].group = 1; 152 Dwfl *dwfl = NULL; 153 (void) argp_parse (&argp, argc, argv, 0, &remaining, &dwfl); 154 assert (dwfl != NULL); 155 156 /* Now handle the addresses. In case none are given on the command 157 line, read from stdin. */ 158 if (remaining == argc) 159 { 160 /* We use no threads here which can interfere with handling a stream. */ 161 (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER); 162 163 char *buf = NULL; 164 size_t len = 0; 165 ssize_t chars; 166 while (!feof_unlocked (stdin)) 167 { 168 if ((chars = getline (&buf, &len, stdin)) < 0) 169 break; 170 171 if (buf[chars - 1] == '\n') 172 buf[chars - 1] = '\0'; 173 174 result = handle_address (buf, dwfl); 175 } 176 177 free (buf); 178 } 179 else 180 { 181 do 182 result = handle_address (argv[remaining], dwfl); 183 while (++remaining < argc); 184 } 185 186 dwfl_end (dwfl); 187 return result; 188} 189 190 191/* Print the version information. */ 192static void 193print_version (FILE *stream, struct argp_state *state __attribute__ ((unused))) 194{ 195 fprintf (stream, "addr2line (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION); 196 fprintf (stream, gettext ("\ 197Copyright (C) %s Red Hat, Inc.\n\ 198This is free software; see the source for copying conditions. There is NO\n\ 199warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ 200"), "2012"); 201 fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper"); 202} 203 204 205/* Handle program arguments. */ 206static error_t 207parse_opt (int key, char *arg, struct argp_state *state) 208{ 209 switch (key) 210 { 211 case ARGP_KEY_INIT: 212 state->child_inputs[0] = state->input; 213 break; 214 215 case 'b': 216 case 'C': 217 case OPT_DEMANGLER: 218 /* Ignored for compatibility. */ 219 break; 220 221 case 's': 222 only_basenames = true; 223 break; 224 225 case 'A': 226 use_comp_dir = true; 227 break; 228 229 case 'f': 230 show_functions = true; 231 break; 232 233 case 'F': 234 show_flags = true; 235 break; 236 237 case 'S': 238 show_symbols = true; 239 break; 240 241 case 'x': 242 show_symbols = true; 243 show_symbol_sections = true; 244 break; 245 246 case 'j': 247 just_section = arg; 248 break; 249 250 case 'i': 251 show_inlines = true; 252 break; 253 254 default: 255 return ARGP_ERR_UNKNOWN; 256 } 257 return 0; 258} 259 260 261static const char * 262get_diename (Dwarf_Die *die) 263{ 264 Dwarf_Attribute attr; 265 const char *name; 266 267 name = dwarf_formstring (dwarf_attr_integrate (die, DW_AT_MIPS_linkage_name, 268 &attr) 269 ?: dwarf_attr_integrate (die, DW_AT_linkage_name, 270 &attr)); 271 272 if (name == NULL) 273 name = dwarf_diename (die) ?: "??"; 274 275 return name; 276} 277 278static bool 279print_dwarf_function (Dwfl_Module *mod, Dwarf_Addr addr) 280{ 281 Dwarf_Addr bias = 0; 282 Dwarf_Die *cudie = dwfl_module_addrdie (mod, addr, &bias); 283 284 Dwarf_Die *scopes; 285 int nscopes = dwarf_getscopes (cudie, addr - bias, &scopes); 286 if (nscopes <= 0) 287 return false; 288 289 for (int i = 0; i < nscopes; ++i) 290 switch (dwarf_tag (&scopes[i])) 291 { 292 case DW_TAG_subprogram: 293 { 294 const char *name = get_diename (&scopes[i]); 295 if (name == NULL) 296 return false; 297 puts (name); 298 return true; 299 } 300 301 case DW_TAG_inlined_subroutine: 302 { 303 const char *name = get_diename (&scopes[i]); 304 if (name == NULL) 305 return false; 306 printf ("%s inlined", name); 307 308 Dwarf_Files *files; 309 if (dwarf_getsrcfiles (cudie, &files, NULL) == 0) 310 { 311 Dwarf_Attribute attr_mem; 312 Dwarf_Word val; 313 if (dwarf_formudata (dwarf_attr (&scopes[i], 314 DW_AT_call_file, 315 &attr_mem), &val) == 0) 316 { 317 const char *file = dwarf_filesrc (files, val, NULL, NULL); 318 unsigned int lineno = 0; 319 unsigned int colno = 0; 320 if (dwarf_formudata (dwarf_attr (&scopes[i], 321 DW_AT_call_line, 322 &attr_mem), &val) == 0) 323 lineno = val; 324 if (dwarf_formudata (dwarf_attr (&scopes[i], 325 DW_AT_call_column, 326 &attr_mem), &val) == 0) 327 colno = val; 328 329 const char *comp_dir = ""; 330 const char *comp_dir_sep = ""; 331 332 if (file == NULL) 333 file = "???"; 334 else if (only_basenames) 335 file = basename (file); 336 else if (use_comp_dir && file[0] != '/') 337 { 338 const char *const *dirs; 339 size_t ndirs; 340 if (dwarf_getsrcdirs (files, &dirs, &ndirs) == 0 341 && dirs[0] != NULL) 342 { 343 comp_dir = dirs[0]; 344 comp_dir_sep = "/"; 345 } 346 } 347 348 if (lineno == 0) 349 printf (" from %s%s%s", 350 comp_dir, comp_dir_sep, file); 351 else if (colno == 0) 352 printf (" at %s%s%s:%u", 353 comp_dir, comp_dir_sep, file, lineno); 354 else 355 printf (" at %s%s%s:%u:%u", 356 comp_dir, comp_dir_sep, file, lineno, colno); 357 } 358 } 359 printf (" in "); 360 continue; 361 } 362 } 363 364 return false; 365} 366 367static void 368print_addrsym (Dwfl_Module *mod, GElf_Addr addr) 369{ 370 GElf_Sym s; 371 GElf_Off off; 372 const char *name = dwfl_module_addrinfo (mod, addr, &off, &s, 373 NULL, NULL, NULL); 374 if (name == NULL) 375 { 376 /* No symbol name. Get a section name instead. */ 377 int i = dwfl_module_relocate_address (mod, &addr); 378 if (i >= 0) 379 name = dwfl_module_relocation_info (mod, i, NULL); 380 if (name == NULL) 381 puts ("??"); 382 else 383 printf ("(%s)+%#" PRIx64 "\n", name, addr); 384 } 385 else 386 { 387 if (off == 0) 388 printf ("%s", name); 389 else 390 printf ("%s+%#" PRIx64 "", name, off); 391 392 // Also show section name for address. 393 if (show_symbol_sections) 394 { 395 Dwarf_Addr ebias; 396 Elf_Scn *scn = dwfl_module_address_section (mod, &addr, &ebias); 397 if (scn != NULL) 398 { 399 GElf_Shdr shdr_mem; 400 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 401 if (shdr != NULL) 402 { 403 Elf *elf = dwfl_module_getelf (mod, &ebias); 404 GElf_Ehdr ehdr; 405 if (gelf_getehdr (elf, &ehdr) != NULL) 406 printf (" (%s)", elf_strptr (elf, ehdr.e_shstrndx, 407 shdr->sh_name)); 408 } 409 } 410 } 411 puts (""); 412 } 413} 414 415static int 416see_one_module (Dwfl_Module *mod, 417 void **userdata __attribute__ ((unused)), 418 const char *name __attribute__ ((unused)), 419 Dwarf_Addr start __attribute__ ((unused)), 420 void *arg) 421{ 422 Dwfl_Module **result = arg; 423 if (*result != NULL) 424 return DWARF_CB_ABORT; 425 *result = mod; 426 return DWARF_CB_OK; 427} 428 429static int 430find_symbol (Dwfl_Module *mod, 431 void **userdata __attribute__ ((unused)), 432 const char *name __attribute__ ((unused)), 433 Dwarf_Addr start __attribute__ ((unused)), 434 void *arg) 435{ 436 const char *looking_for = ((void **) arg)[0]; 437 GElf_Sym *symbol = ((void **) arg)[1]; 438 GElf_Addr *value = ((void **) arg)[2]; 439 440 int n = dwfl_module_getsymtab (mod); 441 for (int i = 1; i < n; ++i) 442 { 443 const char *symbol_name = dwfl_module_getsym_info (mod, i, symbol, 444 value, NULL, NULL, 445 NULL); 446 if (symbol_name == NULL || symbol_name[0] == '\0') 447 continue; 448 switch (GELF_ST_TYPE (symbol->st_info)) 449 { 450 case STT_SECTION: 451 case STT_FILE: 452 case STT_TLS: 453 break; 454 default: 455 if (!strcmp (symbol_name, looking_for)) 456 { 457 ((void **) arg)[0] = NULL; 458 return DWARF_CB_ABORT; 459 } 460 } 461 } 462 463 return DWARF_CB_OK; 464} 465 466static bool 467adjust_to_section (const char *name, uintmax_t *addr, Dwfl *dwfl) 468{ 469 /* It was (section)+offset. This makes sense if there is 470 only one module to look in for a section. */ 471 Dwfl_Module *mod = NULL; 472 if (dwfl_getmodules (dwfl, &see_one_module, &mod, 0) != 0 473 || mod == NULL) 474 error (EXIT_FAILURE, 0, gettext ("Section syntax requires" 475 " exactly one module")); 476 477 int nscn = dwfl_module_relocations (mod); 478 for (int i = 0; i < nscn; ++i) 479 { 480 GElf_Word shndx; 481 const char *scn = dwfl_module_relocation_info (mod, i, &shndx); 482 if (unlikely (scn == NULL)) 483 break; 484 if (!strcmp (scn, name)) 485 { 486 /* Found the section. */ 487 GElf_Shdr shdr_mem; 488 GElf_Addr shdr_bias; 489 GElf_Shdr *shdr = gelf_getshdr 490 (elf_getscn (dwfl_module_getelf (mod, &shdr_bias), shndx), 491 &shdr_mem); 492 if (unlikely (shdr == NULL)) 493 break; 494 495 if (*addr >= shdr->sh_size) 496 error (0, 0, 497 gettext ("offset %#" PRIxMAX " lies outside" 498 " section '%s'"), 499 *addr, scn); 500 501 *addr += shdr->sh_addr + shdr_bias; 502 return true; 503 } 504 } 505 506 return false; 507} 508 509static void 510print_src (const char *src, int lineno, int linecol, Dwarf_Die *cu) 511{ 512 const char *comp_dir = ""; 513 const char *comp_dir_sep = ""; 514 515 if (only_basenames) 516 src = basename (src); 517 else if (use_comp_dir && src[0] != '/') 518 { 519 Dwarf_Attribute attr; 520 comp_dir = dwarf_formstring (dwarf_attr (cu, DW_AT_comp_dir, &attr)); 521 if (comp_dir != NULL) 522 comp_dir_sep = "/"; 523 } 524 525 if (linecol != 0) 526 printf ("%s%s%s:%d:%d", 527 comp_dir, comp_dir_sep, src, lineno, linecol); 528 else 529 printf ("%s%s%s:%d", 530 comp_dir, comp_dir_sep, src, lineno); 531} 532 533static int 534handle_address (const char *string, Dwfl *dwfl) 535{ 536 char *endp; 537 uintmax_t addr = strtoumax (string, &endp, 0); 538 if (endp == string) 539 { 540 bool parsed = false; 541 int i, j; 542 char *name = NULL; 543 if (sscanf (string, "(%m[^)])%" PRIiMAX "%n", &name, &addr, &i) == 2 544 && string[i] == '\0') 545 parsed = adjust_to_section (name, &addr, dwfl); 546 switch (sscanf (string, "%m[^-+]%n%" PRIiMAX "%n", &name, &i, &addr, &j)) 547 { 548 default: 549 break; 550 case 1: 551 addr = 0; 552 j = i; 553 case 2: 554 if (string[j] != '\0') 555 break; 556 557 /* It was symbol[+offset]. */ 558 GElf_Sym sym; 559 GElf_Addr value = 0; 560 void *arg[3] = { name, &sym, &value }; 561 (void) dwfl_getmodules (dwfl, &find_symbol, arg, 0); 562 if (arg[0] != NULL) 563 error (0, 0, gettext ("cannot find symbol '%s'"), name); 564 else 565 { 566 if (sym.st_size != 0 && addr >= sym.st_size) 567 error (0, 0, 568 gettext ("offset %#" PRIxMAX " lies outside" 569 " contents of '%s'"), 570 addr, name); 571 addr += value; 572 parsed = true; 573 } 574 break; 575 } 576 577 free (name); 578 if (!parsed) 579 return 1; 580 } 581 else if (just_section != NULL 582 && !adjust_to_section (just_section, &addr, dwfl)) 583 return 1; 584 585 Dwfl_Module *mod = dwfl_addrmodule (dwfl, addr); 586 587 if (show_functions) 588 { 589 /* First determine the function name. Use the DWARF information if 590 possible. */ 591 if (! print_dwarf_function (mod, addr) && !show_symbols) 592 puts (dwfl_module_addrname (mod, addr) ?: "??"); 593 } 594 595 if (show_symbols) 596 print_addrsym (mod, addr); 597 598 Dwfl_Line *line = dwfl_module_getsrc (mod, addr); 599 600 const char *src; 601 int lineno, linecol; 602 603 if (line != NULL && (src = dwfl_lineinfo (line, &addr, &lineno, &linecol, 604 NULL, NULL)) != NULL) 605 { 606 print_src (src, lineno, linecol, dwfl_linecu (line)); 607 if (show_flags) 608 { 609 Dwarf_Addr bias; 610 Dwarf_Line *info = dwfl_dwarf_line (line, &bias); 611 assert (info != NULL); 612 613 inline void show (int (*get) (Dwarf_Line *, bool *), 614 const char *note) 615 { 616 bool flag; 617 if ((*get) (info, &flag) == 0 && flag) 618 fputs (note, stdout); 619 } 620 inline void show_int (int (*get) (Dwarf_Line *, unsigned int *), 621 const char *name) 622 { 623 unsigned int val; 624 if ((*get) (info, &val) == 0 && val != 0) 625 printf (" (%s %u)", name, val); 626 } 627 628 show (&dwarf_linebeginstatement, " (is_stmt)"); 629 show (&dwarf_lineblock, " (basic_block)"); 630 show (&dwarf_lineprologueend, " (prologue_end)"); 631 show (&dwarf_lineepiloguebegin, " (epilogue_begin)"); 632 show_int (&dwarf_lineisa, "isa"); 633 show_int (&dwarf_linediscriminator, "discriminator"); 634 } 635 putchar ('\n'); 636 } 637 else 638 puts ("??:0"); 639 640 if (show_inlines) 641 { 642 Dwarf_Addr bias = 0; 643 Dwarf_Die *cudie = dwfl_module_addrdie (mod, addr, &bias); 644 645 Dwarf_Die *scopes = NULL; 646 int nscopes = dwarf_getscopes (cudie, addr - bias, &scopes); 647 if (nscopes < 0) 648 return 1; 649 650 if (nscopes > 0) 651 { 652 Dwarf_Die subroutine; 653 Dwarf_Off dieoff = dwarf_dieoffset (&scopes[0]); 654 dwarf_offdie (dwfl_module_getdwarf (mod, &bias), 655 dieoff, &subroutine); 656 free (scopes); 657 658 nscopes = dwarf_getscopes_die (&subroutine, &scopes); 659 if (nscopes > 1) 660 { 661 Dwarf_Die cu; 662 Dwarf_Files *files; 663 if (dwarf_diecu (&scopes[0], &cu, NULL, NULL) != NULL 664 && dwarf_getsrcfiles (cudie, &files, NULL) == 0) 665 { 666 for (int i = 0; i < nscopes - 1; i++) 667 { 668 Dwarf_Word val; 669 Dwarf_Attribute attr; 670 Dwarf_Die *die = &scopes[i]; 671 if (dwarf_tag (die) != DW_TAG_inlined_subroutine) 672 continue; 673 674 if (show_functions) 675 { 676 /* Search for the parent inline or function. It 677 might not be directly above this inline -- e.g. 678 there could be a lexical_block in between. */ 679 for (int j = i + 1; j < nscopes; j++) 680 { 681 Dwarf_Die *parent = &scopes[j]; 682 int tag = dwarf_tag (parent); 683 if (tag == DW_TAG_inlined_subroutine 684 || tag == DW_TAG_entry_point 685 || tag == DW_TAG_subprogram) 686 { 687 puts (get_diename (parent)); 688 break; 689 } 690 } 691 } 692 693 src = NULL; 694 lineno = 0; 695 linecol = 0; 696 if (dwarf_formudata (dwarf_attr (die, DW_AT_call_file, 697 &attr), &val) == 0) 698 src = dwarf_filesrc (files, val, NULL, NULL); 699 700 if (dwarf_formudata (dwarf_attr (die, DW_AT_call_line, 701 &attr), &val) == 0) 702 lineno = val; 703 704 if (dwarf_formudata (dwarf_attr (die, DW_AT_call_column, 705 &attr), &val) == 0) 706 linecol = val; 707 708 if (src != NULL) 709 { 710 print_src (src, lineno, linecol, &cu); 711 putchar ('\n'); 712 } 713 else 714 puts ("??:0"); 715 } 716 } 717 } 718 } 719 free (scopes); 720 } 721 722 return 0; 723} 724 725 726#include "debugpred.h" 727