summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2009-04-20 00:49:33 -0700
committerRoland McGrath <roland@redhat.com>2009-04-20 00:49:33 -0700
commitd86e183403704a287d33c99badcf8bea303c0fd7 (patch)
tree2db30559a3c18eb76720abc635a096ce9dc8ab80
parenta605a3c8f354895f4cca56aca8f8aa468b506fdf (diff)
downloadelfutils-d86e183403704a287d33c99badcf8bea303c0fd7.tar.gz
Support -j option in addr2line to match binutils.
-rw-r--r--NEWS5
-rw-r--r--src/ChangeLog7
-rw-r--r--src/addr2line.c98
3 files changed, 69 insertions, 41 deletions
diff --git a/NEWS b/NEWS
index 5effc77a..c0f60bca 100644
--- a/NEWS
+++ b/NEWS
@@ -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);