X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=binutils%2Faddr2line.c;h=7cd67bc0a1b08e1b742537d4bf80c3f09f4849c0;hb=9b3f89ee006eb0681730769be5146edc38e6e83f;hp=354153eadb13c3e87e2c3c4432cca55eb1ea4550;hpb=f24ddbddc5177a930b867626b12d2bb8b3757223;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/addr2line.c b/binutils/addr2line.c index 354153eadb..7cd67bc0a1 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 + Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006 Free Software Foundation, Inc. Contributed by Ulrich Lauther @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ /* Derived from objdump.c and nm.c by Ulrich.Lauther@mchp.siemens.de @@ -29,6 +29,7 @@ both forms write results to stdout, the second form reads addresses to be converted from stdin. */ +#include "config.h" #include #include "bfd.h" @@ -38,6 +39,7 @@ #include "bucomm.h" #include "budemang.h" +static bfd_boolean unwind_inlines; /* -i, unwind inlined functions. */ static bfd_boolean with_functions; /* -f, show function names. */ static bfd_boolean do_demangle; /* -C, demangle names. */ static bfd_boolean base_names; /* -s, strip directory names. */ @@ -53,6 +55,8 @@ static struct option long_options[] = {"demangle", optional_argument, NULL, 'C'}, {"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'}, @@ -62,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. */ @@ -74,8 +79,11 @@ usage (FILE *stream, int status) fprintf (stream, _(" Convert addresses into line number/file name pairs.\n")); fprintf (stream, _(" If no addresses are specified on the command line, they will be read from stdin\n")); fprintf (stream, _(" The options are:\n\ + @ Read options from \n\ -b --target= Set the binary file format\n\ -e --exe= Set the input file name (default is a.out)\n\ + -i --inlines Unwind inlined functions\n\ + -j --section= 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\ @@ -137,7 +145,7 @@ find_address_in_section (bfd *abfd, asection *section, if (pc < vma) return; - size = bfd_get_section_size_before_reloc (section); + size = bfd_get_section_size (section); if (pc >= vma + size) return; @@ -145,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); @@ -172,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) { @@ -182,36 +214,43 @@ translate_addresses (bfd *abfd) } else { - if (with_functions) - { - const char *name; - char *alloc = NULL; - - name = functionname; - if (name == NULL || *name == '\0') - name = "??"; - else if (do_demangle) - { - alloc = demangle (abfd, name); - name = alloc; - } - - printf ("%s\n", name); - - if (alloc != NULL) - free (alloc); - } - - if (base_names && filename != NULL) - { - char *h; - - h = strrchr (filename, '/'); - if (h != NULL) - filename = h + 1; - } + do { + if (with_functions) + { + const char *name; + char *alloc = NULL; + + name = functionname; + if (name == NULL || *name == '\0') + name = "??"; + else if (do_demangle) + { + alloc = demangle (abfd, name); + name = alloc; + } + + printf ("%s\n", name); + + if (alloc != NULL) + free (alloc); + } + + if (base_names && filename != NULL) + { + char *h; + + h = strrchr (filename, '/'); + if (h != NULL) + filename = h + 1; + } + + printf ("%s:%u\n", filename ? filename : "??", line); + if (!unwind_inlines) + found = FALSE; + else + found = bfd_find_inliner_info (abfd, &filename, &functionname, &line); + } while (found); - printf ("%s:%u\n", filename ? filename : "??", line); } /* fflush() is essential for using this command as a server @@ -225,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) @@ -238,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)) { @@ -251,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) { @@ -264,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; @@ -285,12 +334,15 @@ main (int argc, char **argv) program_name = *argv; xmalloc_set_program_name (program_name); + expandargv (&argc, &argv); + bfd_init (); set_default_bfd_target (); file_name = NULL; + section_name = NULL; target = NULL; - while ((c = getopt_long (argc, argv, "b:Ce:sfHhVv", long_options, (int *) 0)) + while ((c = getopt_long (argc, argv, "b:Ce:sfHhij:Vv", long_options, (int *) 0)) != EOF) { switch (c) @@ -331,6 +383,12 @@ main (int argc, char **argv) case 'H': usage (stdout, 0); break; + case 'i': + unwind_inlines = TRUE; + break; + case 'j': + section_name = optarg; + break; default: usage (stderr, 1); break; @@ -343,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; }