diff options
author | Roland McGrath <roland@redhat.com> | 2009-04-20 00:49:33 -0700 |
---|---|---|
committer | Roland McGrath <roland@redhat.com> | 2009-04-20 00:49:33 -0700 |
commit | d86e183403704a287d33c99badcf8bea303c0fd7 (patch) | |
tree | 2db30559a3c18eb76720abc635a096ce9dc8ab80 | |
parent | a605a3c8f354895f4cca56aca8f8aa468b506fdf (diff) | |
download | elfutils-d86e183403704a287d33c99badcf8bea303c0fd7.tar.gz |
Support -j option in addr2line to match binutils.
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | src/ChangeLog | 7 | ||||
-rw-r--r-- | src/addr2line.c | 98 |
3 files changed, 69 insertions, 41 deletions
@@ -2,11 +2,16 @@ Version 0.141: libebl: sparc backend fixes; some more arm backend support + libdwfl: fix dwfl_module_build_id for prelinked DSO case; fixes in core file support; dwfl_module_getsym interface improved for non-address symbols + strip: fix infinite loop on strange inputs with -f +addr2line: take -j/--section=NAME option for binutils compatibility + (same effect as '(NAME)0x123' syntax already supported) + Version 0.140: libelf: Fix regression in creation of section header diff --git a/src/ChangeLog b/src/ChangeLog index fe8b0362..20f5d987 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,10 @@ +2009-04-20 Roland McGrath <roland@redhat.com> + + * addr2line.c (just_section): New variable. + (adjust_to_section): New function, broken out of ... + (handle_address): ... here. + (options, parse_opt): Add -j/--section=NAME to set it. + 2009-04-15 Roland McGrath <roland@redhat.com> * readelf.c (print_debug_frame_section): Check for DW_CIE_ID_64 in diff --git a/src/addr2line.c b/src/addr2line.c index 5a7b0456..ccc10e8f 100644 --- a/src/addr2line.c +++ b/src/addr2line.c @@ -69,6 +69,8 @@ static const struct argp_option options[] = N_("Show absolute file names using compilation directory"), 0 }, { "functions", 'f', NULL, 0, N_("Also show function names"), 0 }, { "symbols", 'S', NULL, 0, N_("Also show symbol or section names"), 0 }, + { "section", 'j', "NAME", 0, + N_("Treat addresses as offsets relative to NAME section."), 0 }, { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 }, /* Unsupported options. */ @@ -113,6 +115,9 @@ static bool show_functions; /* True if ELF symbol or section info should be shown. */ static bool show_symbols; +/* If non-null, take address parameters as relative to named section. */ +static const char *just_section; + int main (int argc, char *argv[]) @@ -188,8 +193,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ /* Handle program arguments. */ static error_t -parse_opt (int key, char *arg __attribute__ ((unused)), - struct argp_state *state) +parse_opt (int key, char *arg, struct argp_state *state) { switch (key) { @@ -219,6 +223,10 @@ parse_opt (int key, char *arg __attribute__ ((unused)), show_symbols = true; break; + case 'j': + just_section = arg; + break; + default: return ARGP_ERR_UNKNOWN; } @@ -366,6 +374,49 @@ find_symbol (Dwfl_Module *mod, return DWARF_CB_OK; } +static bool +adjust_to_section (const char *name, uintmax_t *addr, Dwfl *dwfl) +{ + /* It was (section)+offset. This makes sense if there is + only one module to look in for a section. */ + Dwfl_Module *mod = NULL; + if (dwfl_getmodules (dwfl, &see_one_module, &mod, 0) != 0 + || mod == NULL) + error (EXIT_FAILURE, 0, gettext ("Section syntax requires" + " exactly one module")); + + int nscn = dwfl_module_relocations (mod); + for (int i = 0; i < nscn; ++i) + { + GElf_Word shndx; + const char *scn = dwfl_module_relocation_info (mod, i, &shndx); + if (unlikely (scn == NULL)) + break; + if (!strcmp (scn, name)) + { + /* Found the section. */ + GElf_Shdr shdr_mem; + GElf_Addr shdr_bias; + GElf_Shdr *shdr = gelf_getshdr + (elf_getscn (dwfl_module_getelf (mod, &shdr_bias), shndx), + &shdr_mem); + if (unlikely (shdr == NULL)) + break; + + if (*addr >= shdr->sh_size) + error (0, 0, + gettext ("offset %#" PRIxMAX " lies outside" + " section '%s'"), + *addr, scn); + + *addr += shdr->sh_addr + shdr_bias; + return true; + } + } + + return false; +} + static int handle_address (const char *string, Dwfl *dwfl) { @@ -378,45 +429,7 @@ handle_address (const char *string, Dwfl *dwfl) char *name = NULL; if (sscanf (string, "(%m[^)])%" PRIiMAX "%n", &name, &addr, &n) == 2 && string[n] == '\0') - { - /* It was (section)+offset. This makes sense if there is - only one module to look in for a section. */ - Dwfl_Module *mod = NULL; - if (dwfl_getmodules (dwfl, &see_one_module, &mod, 0) != 0 - || mod == NULL) - error (EXIT_FAILURE, 0, gettext ("Section syntax requires" - " exactly one module")); - - int nscn = dwfl_module_relocations (mod); - for (int i = 0; i < nscn; ++i) - { - GElf_Word shndx; - const char *scn = dwfl_module_relocation_info (mod, i, &shndx); - if (unlikely (scn == NULL)) - break; - if (!strcmp (scn, name)) - { - /* Found the section. */ - GElf_Shdr shdr_mem; - GElf_Addr shdr_bias; - GElf_Shdr *shdr = gelf_getshdr - (elf_getscn (dwfl_module_getelf (mod, &shdr_bias), shndx), - &shdr_mem); - if (unlikely (shdr == NULL)) - break; - - if (addr >= shdr->sh_size) - error (0, 0, - gettext ("offset %#" PRIxMAX " lies outside" - " section '%s'"), - addr, scn); - - addr += shdr->sh_addr + shdr_bias; - parsed = true; - break; - } - } - } + parsed = adjust_to_section (name, &addr, dwfl); else if (sscanf (string, "%m[^-+]%" PRIiMAX "%n", &name, &addr, &n) == 2 && string[n] == '\0') { @@ -442,6 +455,9 @@ handle_address (const char *string, Dwfl *dwfl) if (!parsed) return 1; } + else if (just_section != NULL + && !adjust_to_section (just_section, &addr, dwfl)) + return 1; Dwfl_Module *mod = dwfl_addrmodule (dwfl, addr); |