diff options
Diffstat (limited to 'binutils/addr2line.c')
-rw-r--r-- | binutils/addr2line.c | 67 |
1 files changed, 54 insertions, 13 deletions
diff --git a/binutils/addr2line.c b/binutils/addr2line.c index aae69ca..7cd67bc 100644 --- a/binutils/addr2line.c +++ b/binutils/addr2line.c @@ -1,5 +1,5 @@ /* addr2line.c -- convert addresses to line number and function name - Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 + Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006 Free Software Foundation, Inc. Contributed by Ulrich Lauther <Ulrich.Lauther@mchp.siemens.de> @@ -56,6 +56,7 @@ static struct option long_options[] = {"exe", required_argument, NULL, 'e'}, {"functions", no_argument, NULL, 'f'}, {"inlines", no_argument, NULL, 'i'}, + {"section", required_argument, NULL, 'j'}, {"target", required_argument, NULL, 'b'}, {"help", no_argument, NULL, 'H'}, {"version", no_argument, NULL, 'V'}, @@ -65,8 +66,9 @@ static struct option long_options[] = static void usage (FILE *, int); static void slurp_symtab (bfd *); static void find_address_in_section (bfd *, asection *, void *); -static void translate_addresses (bfd *); -static void process_file (const char *, const char *); +static void find_offset_in_section (bfd *, asection *); +static void translate_addresses (bfd *, asection *); +static void process_file (const char *, const char *, const char *); /* Print a usage message to STREAM and exit with STATUS. */ @@ -80,7 +82,8 @@ usage (FILE *stream, int status) @<file> Read options from <file>\n\ -b --target=<bfdname> Set the binary file format\n\ -e --exe=<executable> Set the input file name (default is a.out)\n\ - -i --inlines Unwind inlined functions\n\ + -i --inlines Unwind inlined functions\n\ + -j --section=<name> Read section-relative offsets instead of addresses\n\ -s --basenames Strip directory names\n\ -f --functions Show function names\n\ -C --demangle[=style] Demangle function names\n\ @@ -150,11 +153,32 @@ find_address_in_section (bfd *abfd, asection *section, &filename, &functionname, &line); } +/* Look for an offset in a section. This is directly called. */ + +static void +find_offset_in_section (bfd *abfd, asection *section) +{ + bfd_size_type size; + + if (found) + return; + + if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0) + return; + + size = bfd_get_section_size (section); + if (pc >= size) + return; + + found = bfd_find_nearest_line (abfd, section, syms, pc, + &filename, &functionname, &line); +} + /* Read hexadecimal addresses from stdin, translate into file_name:line_number and optionally function name. */ static void -translate_addresses (bfd *abfd) +translate_addresses (bfd *abfd, asection *section) { int read_stdin = (naddr == 0); @@ -177,7 +201,10 @@ translate_addresses (bfd *abfd) } found = FALSE; - bfd_map_over_sections (abfd, find_address_in_section, NULL); + if (section) + find_offset_in_section (abfd, section); + else + bfd_map_over_sections (abfd, find_address_in_section, NULL); if (! found) { @@ -237,9 +264,11 @@ translate_addresses (bfd *abfd) /* Process a file. */ static void -process_file (const char *file_name, const char *target) +process_file (const char *file_name, const char *section_name, + const char *target) { bfd *abfd; + asection *section; char **matching; if (get_file_size (file_name) < 1) @@ -250,7 +279,7 @@ process_file (const char *file_name, const char *target) bfd_fatal (file_name); if (bfd_check_format (abfd, bfd_archive)) - fatal (_("%s: can not get addresses from archive"), file_name); + fatal (_("%s: cannot get addresses from archive"), file_name); if (! bfd_check_format_matches (abfd, bfd_object, &matching)) { @@ -263,9 +292,18 @@ process_file (const char *file_name, const char *target) xexit (1); } + if (section_name != NULL) + { + section = bfd_get_section_by_name (abfd, section_name); + if (section == NULL) + fatal (_("%s: cannot find section %s"), file_name, section_name); + } + else + section = NULL; + slurp_symtab (abfd); - translate_addresses (abfd); + translate_addresses (abfd, section); if (syms != NULL) { @@ -276,12 +314,11 @@ process_file (const char *file_name, const char *target) bfd_close (abfd); } -int main (int, char **); - int main (int argc, char **argv) { const char *file_name; + const char *section_name; char *target; int c; @@ -303,8 +340,9 @@ main (int argc, char **argv) set_default_bfd_target (); file_name = NULL; + section_name = NULL; target = NULL; - while ((c = getopt_long (argc, argv, "b:Ce:sfHhiVv", long_options, (int *) 0)) + while ((c = getopt_long (argc, argv, "b:Ce:sfHhij:Vv", long_options, (int *) 0)) != EOF) { switch (c) @@ -348,6 +386,9 @@ main (int argc, char **argv) case 'i': unwind_inlines = TRUE; break; + case 'j': + section_name = optarg; + break; default: usage (stderr, 1); break; @@ -360,7 +401,7 @@ main (int argc, char **argv) addr = argv + optind; naddr = argc - optind; - process_file (file_name, target); + process_file (file_name, section_name, target); return 0; } |