Extend objdump's --dwarf=follow-links option so that separate debug info files will...
authorNick Clifton <nickc@redhat.com>
Mon, 25 Feb 2019 12:15:41 +0000 (12:15 +0000)
committerNick Clifton <nickc@redhat.com>
Mon, 25 Feb 2019 12:15:41 +0000 (12:15 +0000)
* objdump.c (sym_ok): New function.
(find_symbol_for_address): Use new function.
(disassemble_section): Compare sections by name, not pointer.
(dump_dwarf): Move code to initialise byte_get pointer and iterate
over separate debug files from here to ...
(dump_bfd): ... here.  Add parameter indicating that a separate
debug info file is being dumped.  For main file, pull in the
symbol tables from all separate debug info files.
(display_object): Update call to dump_bfd.
* doc/binutils.texi: Document extened behaviour of the
--dwarf=follow-links option.
* NEWS: Mention this new feature.
* testsuite/binutils-all/objdump.WK2: Update expected output.
* testsuite/binutils-all/objdump.exp (test_follow_debuglink): Add
options and dump file parameters.
Add extra test.
* testsuite/binutils-all/objdump.WK3: New file.
* testsuite/binutils-all/readelf.exp: Change expected output for
readelf -wKis test.
* testsuite/binutils-all/readelf.wKis: New file.

13 files changed:
binutils/ChangeLog
binutils/NEWS
binutils/doc/binutils.texi
binutils/dwarf.c
binutils/dwarf.h
binutils/objdump.c
binutils/testsuite/binutils-all/debuglink.s
binutils/testsuite/binutils-all/linkdebug.s
binutils/testsuite/binutils-all/objdump.WK2
binutils/testsuite/binutils-all/objdump.WK3 [new file with mode: 0644]
binutils/testsuite/binutils-all/objdump.exp
binutils/testsuite/binutils-all/readelf.exp
binutils/testsuite/binutils-all/readelf.wKis [new file with mode: 0644]

index 65316ee9dedcc8bd65ccaa38bf9334870faf12b9..f3d8fa2a5ccb9a02d3ce1090b7f5635f5d0f7202 100644 (file)
@@ -1,3 +1,26 @@
+2019-02-25  Nick Clifton  <nickc@redhat.com>
+
+       * objdump.c (sym_ok): New function.
+       (find_symbol_for_address): Use new function.
+       (disassemble_section): Compare sections by name, not pointer.
+       (dump_dwarf): Move code to initialise byte_get pointer and iterate
+       over separate debug files from here to ...
+       (dump_bfd): ... here.  Add parameter indicating that a separate
+       debug info file is being dumped.  For main file, pull in the
+       symbol tables from all separate debug info files.
+       (display_object): Update call to dump_bfd.
+       * doc/binutils.texi: Document extened behaviour of the
+       --dwarf=follow-links option.
+       * NEWS: Mention this new feature.
+       * testsuite/binutils-all/objdump.WK2: Update expected output.
+       * testsuite/binutils-all/objdump.exp (test_follow_debuglink): Add
+       options and dump file parameters.
+       Add extra test.
+       * testsuite/binutils-all/objdump.WK3: New file.
+       * testsuite/binutils-all/readelf.exp: Change expected output for
+       readelf -wKis test.
+       * testsuite/binutils-all/readelf.wKis: New file.
+
 2019-02-22  Nick Clifton  <nickc@redhat.com>
 
        PR 23843
index 5413321b4baf0d433b69752223d0c8e6a0d060fd..7c9d7bef30b024bdb03bc0d86b1ffbc1506ffe66 100644 (file)
@@ -6,6 +6,13 @@
   more than one are present in a file.  (This usually happens when gcc's
   -gsplit-dwarf option is used).
 
+  In addition objdump's --dwarf=follow-links now also affects its other
+  display options, so that for example, when combined with --syms it will
+  cause the symbol tables in any linked debug info files to also be
+  displayed.  In addition when combined with --disassemble the --dwarf=
+  follow-links option will ensure that any symbol tables in the linked
+  files are read and used when disassembling code in the main file.
+  
 Changes in 2.32:
 
 * The addr2line, c++filt, nm and objdump tools now have a limit on the
index 01f1e5f56db99e98f6863623e37ab97c93a0244a..eb5c3e87a3c8ad2c64ebb7fb995174a0679f37f1 100644 (file)
@@ -2236,6 +2236,10 @@ will stop at the end of the function, otherwise it will stop when the
 next symbol is encountered.  If there are no matches for @var{symbol}
 then nothing will be displayed.
 
+Note if the @option{--dwarf=follow-links} option has also been enabled
+then any symbol tables in linked debug info files will be read in and
+used when disassembling.
+
 @item -D
 @itemx --disassemble-all
 Like @option{-d}, but disassemble the contents of all sections, not just
@@ -2254,6 +2258,10 @@ If the target is an ARM architecture this switch also has the effect
 of forcing the disassembler to decode pieces of data found in code
 sections as if they were instructions.
 
+Note if the @option{--dwarf=follow-links} option has also been enabled
+then any symbol tables in linked debug info files will be read in and
+used when disassembling.
+
 @item --prefix-addresses
 When disassembling, print the complete address on each line.  This is
 the older disassembly format.
index 07142af747e282cc00715e080fd837928c7f06d3..9f17af9ff823bc1517118c8d58b9cc42431bcbad 100644 (file)
@@ -9826,6 +9826,7 @@ parse_gnu_debuglink (struct dwarf_section * section, void * data)
      The CRC value is stored after the filename, aligned up to 4 bytes.  */
   name = (const char *) section->start;
 
+  
   crc_offset = strnlen (name, section->size) + 1;
   crc_offset = (crc_offset + 3) & ~3;
   if (crc_offset + 4 > section->size)
@@ -9981,6 +9982,11 @@ load_separate_debug_info (const char *            main_filename,
   sprintf (debug_filename, "%s/%s", EXTRA_DEBUG_ROOT1, separate_filename);
   if (check_func (debug_filename, func_data))
     goto found;
+
+  /* Try the first extra debug file root.  */
+  sprintf (debug_filename, "%s/%s/%s", EXTRA_DEBUG_ROOT1, canon_dir, separate_filename);
+  if (check_func (debug_filename, func_data))
+    goto found;
 #endif
 
 #ifdef EXTRA_DEBUG_ROOT2
@@ -10010,6 +10016,9 @@ load_separate_debug_info (const char *            main_filename,
 #endif
 
 #ifdef EXTRA_DEBUG_ROOT1
+  sprintf (debug_filename, "%s/%s/%s", EXTRA_DEBUG_ROOT1, canon_dir, separate_filename);
+  warn (_("tried: %s\n"), debug_filename);
+
   sprintf (debug_filename, "%s/%s", EXTRA_DEBUG_ROOT1, separate_filename);
   warn (_("tried: %s\n"), debug_filename);
 #endif
index a0287fc0bc54846f295243bc5aeacfeba693e842..ca2f062efb752448cd5ed2dcfb987322a63faf31 100644 (file)
@@ -218,6 +218,7 @@ extern int do_debug_addr;
 extern int do_debug_cu_index;
 extern int do_wide;
 extern int do_debug_links;
+extern int do_follow_links;
 
 extern int dwarf_cutoff_level;
 extern unsigned long dwarf_start_die;
index 19365b67a0157af776d379f75df8ecf60b958d7a..ab091c10d4bfcffef991026ab2b9469d2362965c 100644 (file)
@@ -987,6 +987,30 @@ objdump_print_symname (bfd *abfd, struct disassemble_info *inf,
     free (alloc);
 }
 
+static inline bfd_boolean
+sym_ok (bfd_boolean               want_section,
+       bfd *                     abfd ATTRIBUTE_UNUSED,
+       long                      place,
+       asection *                sec,
+       struct disassemble_info * inf)
+{
+  if (want_section)
+    {
+      /* Note - we cannot just compare section pointers because they could
+        be different, but the same...  Ie the symbol that we are trying to
+        find could have come from a separate debug info file.  Under such
+        circumstances the symbol will be associated with a section in the
+        debug info file, whilst the section we want is in a normal file.
+        So the section pointers will be different, but the section names
+        will be the same.  */
+      if (strcmp (bfd_section_name (abfd, sorted_syms[place]->section),
+                 bfd_section_name (abfd, sec)) != 0)
+       return FALSE;
+    }
+
+  return inf->symbol_is_valid (sorted_syms[place], inf);
+}
+
 /* Locate a symbol given a bfd and a section (from INFO->application_data),
    and a VMA.  If INFO->application_data->require_sec is TRUE, then always
    require the symbol to be in the section.  Returns NULL if there is no
@@ -1062,8 +1086,7 @@ find_symbol_for_address (bfd_vma vma,
         && (bfd_asymbol_value (sorted_syms[min])
             == bfd_asymbol_value (sorted_syms[thisplace])))
     {
-      if (sorted_syms[min]->section == sec
-         && inf->symbol_is_valid (sorted_syms[min], inf))
+      if (sym_ok (TRUE, abfd, min, sec, inf))
        {
          thisplace = min;
 
@@ -1090,16 +1113,15 @@ find_symbol_for_address (bfd_vma vma,
                      && vma >= bfd_get_section_vma (abfd, sec)
                      && vma < (bfd_get_section_vma (abfd, sec)
                                + bfd_section_size (abfd, sec) / opb)));
-  if ((sorted_syms[thisplace]->section != sec && want_section)
-      || ! inf->symbol_is_valid (sorted_syms[thisplace], inf))
+  
+  if (! sym_ok (want_section, abfd, thisplace, sec, inf))
     {
       long i;
       long newplace = sorted_symcount;
 
       for (i = min - 1; i >= 0; i--)
        {
-         if ((sorted_syms[i]->section == sec || !want_section)
-             && inf->symbol_is_valid (sorted_syms[i], inf))
+         if (sym_ok (want_section, abfd, i, sec, inf))
            {
              if (newplace == sorted_symcount)
                newplace = i;
@@ -1122,8 +1144,7 @@ find_symbol_for_address (bfd_vma vma,
             Look for one with a larger value.  */
          for (i = thisplace + 1; i < sorted_symcount; i++)
            {
-             if ((sorted_syms[i]->section == sec || !want_section)
-                 && inf->symbol_is_valid (sorted_syms[i], inf))
+             if (sym_ok (want_section, abfd, i, sec, inf))
                {
                  thisplace = i;
                  break;
@@ -1131,8 +1152,7 @@ find_symbol_for_address (bfd_vma vma,
            }
        }
 
-      if ((sorted_syms[thisplace]->section != sec && want_section)
-         || ! inf->symbol_is_valid (sorted_syms[thisplace], inf))
+      if (! sym_ok (want_section, abfd, thisplace, sec, inf))
        /* There is no suitable symbol.  */
        return NULL;
     }
@@ -2460,7 +2480,7 @@ disassemble_section (bfd *abfd, asection *section, void *inf)
       else
        {
 #define is_valid_next_sym(SYM) \
-  ((SYM)->section == section \
+  (strcmp (bfd_section_name (abfd, (SYM)->section), bfd_section_name (abfd, section)) == 0 \
    && (bfd_asymbol_value (SYM) > bfd_asymbol_value (sym)) \
    && pinfo->symbol_is_valid (SYM, pinfo))
 
@@ -2882,24 +2902,18 @@ dump_dwarf_section (bfd *abfd, asection *section,
 static void
 dump_dwarf (bfd *abfd)
 {
-  bfd_boolean have_separates;
-
-  is_relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0;
-
-  eh_addr_size = bfd_arch_bits_per_address (abfd) / 8;
-
-  if (bfd_big_endian (abfd))
-    byte_get = byte_get_big_endian;
-  else if (bfd_little_endian (abfd))
-    byte_get = byte_get_little_endian;
-  else
-    /* PR 17512: file: objdump-s-endless-loop.tekhex.  */
+  /* The byte_get pointer should have been set at the start of dump_bfd().  */
+  if (byte_get == NULL)
     {
       warn (_("File %s does not contain any dwarf debug information\n"),
            bfd_get_filename (abfd));
       return;
     }
 
+  is_relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0;
+
+  eh_addr_size = bfd_arch_bits_per_address (abfd) / 8;
+
   switch (bfd_get_arch (abfd))
     {
     case bfd_arch_i386:
@@ -2946,21 +2960,7 @@ dump_dwarf (bfd *abfd)
       break;
     }
 
-  have_separates = load_separate_debug_files (abfd, bfd_get_filename (abfd));
-
   bfd_map_over_sections (abfd, dump_dwarf_section, NULL);
-
-  if (have_separates)
-    {
-      separate_info * i;
-
-      for (i = first_separate_info; i != NULL; i = i->next)
-       bfd_map_over_sections (i->handle, dump_dwarf_section, NULL);
-
-      /* The file handles are closed by the call to free_debug_memory() below.  */
-    }
-
-  free_debug_memory ();
 }
 \f
 /* Read ABFD's stabs section STABSECT_NAME, and return a pointer to
@@ -3768,8 +3768,38 @@ adjust_addresses (bfd *abfd ATTRIBUTE_UNUSED,
 /* Dump selected contents of ABFD.  */
 
 static void
-dump_bfd (bfd *abfd)
+dump_bfd (bfd *abfd, bfd_boolean is_mainfile)
 {
+  if (bfd_big_endian (abfd))
+    byte_get = byte_get_big_endian;
+  else if (bfd_little_endian (abfd))
+    byte_get = byte_get_little_endian;
+  else
+    byte_get = NULL;
+
+  /* Load any separate debug information files.
+     We do this now and without checking do_follow_links because separate
+     debug info files may contain symbol tables that we will need when
+     displaying information about the main file.  Any memory allocated by
+     load_separate_debug_files will be released when we call
+     free_debug_memory below.
+     
+     The test on is_mainfile is there because the chain of separate debug
+     info files is a global variable shared by all invocations of dump_bfd.  */
+  if (is_mainfile)
+    {
+      load_separate_debug_files (abfd, bfd_get_filename (abfd));
+
+      /* If asked to do so, recursively dump the separate files.  */
+      if (do_follow_links)
+       {
+         separate_info * i;
+
+         for (i = first_separate_info; i != NULL; i = i->next)
+           dump_bfd (i->handle, FALSE);
+       }
+    }
+
   /* If we are adjusting section VMA's, change them all now.  Changing
      the BFD information is a hack.  However, we must do it, or
      bfd_find_nearest_line will not do the right thing.  */
@@ -3799,7 +3829,40 @@ dump_bfd (bfd *abfd)
       || disassemble
       || dump_debugging
       || dump_dwarf_section_info)
-    syms = slurp_symtab (abfd);
+    {
+      syms = slurp_symtab (abfd);
+
+      /* If following links, load any symbol tables from the linked files as well.  */
+      if (do_follow_links && is_mainfile)
+       {
+         separate_info * i;
+
+         for (i = first_separate_info; i != NULL; i = i->next)
+           {
+             asymbol **  extra_syms;
+             long        old_symcount = symcount;
+             
+             extra_syms = slurp_symtab (i->handle);
+
+             if (extra_syms)
+               {
+                 if (old_symcount == 0)
+                   {
+                     syms = extra_syms;
+                   }
+                 else
+                   {
+                     syms = xrealloc (syms, (symcount + old_symcount) * sizeof (asymbol *));
+                     memcpy (syms + old_symcount,
+                             extra_syms,
+                             symcount * sizeof (asymbol *));
+                   }
+               }
+
+             symcount += old_symcount;
+           }
+       }
+    }
 
   if (dump_section_headers)
     dump_headers (abfd);
@@ -3807,6 +3870,7 @@ dump_bfd (bfd *abfd)
   if (dump_dynamic_symtab || dump_dynamic_reloc_info
       || (disassemble && bfd_get_dynamic_symtab_upper_bound (abfd) > 0))
     dynsyms = slurp_dynamic_symtab (abfd);
+
   if (disassemble)
     {
       synthcount = bfd_get_synthetic_symtab (abfd, symcount, syms,
@@ -3880,6 +3944,9 @@ dump_bfd (bfd *abfd)
   symcount = 0;
   dynsymcount = 0;
   synthcount = 0;
+
+  if (is_mainfile)
+    free_debug_memory ();
 }
 
 static void
@@ -3889,7 +3956,7 @@ display_object_bfd (bfd *abfd)
 
   if (bfd_check_format_matches (abfd, bfd_object, &matching))
     {
-      dump_bfd (abfd);
+      dump_bfd (abfd, TRUE);
       return;
     }
 
@@ -3909,7 +3976,7 @@ display_object_bfd (bfd *abfd)
 
   if (bfd_check_format_matches (abfd, bfd_core, &matching))
     {
-      dump_bfd (abfd);
+      dump_bfd (abfd, TRUE);
       return;
     }
 
index 9cadc67da24afd16b1c05475a78c120c39c977cc..b51500ddd27d4c44e622b2ae4954740d03010dbe 100644 (file)
@@ -64,4 +64,3 @@ debugS:
        ;# will be started.
        .balign 2, 0
 debugE:
-
index 6b43bbe38aa7ecc1adfff1d1c36e3453d653601d..7d8db73592f0c7f3947ce504573419b759f54e46 100644 (file)
@@ -51,4 +51,3 @@ string3:
        .asciz  "string-4"
        .balign 2
 string_end:
-       
index c98fdc15b58db2da00c59177bc3b947f7bb422f4..539a0875cfedb3e6adb331f6e810691726ac93e7 100644 (file)
@@ -1,5 +1,11 @@
 #...
 .*debuglink.o: Found separate debug info file:.*linkdebug.debug
+#...
+Contents of the .debug_str section \(loaded from .*linkdebug.debug\):
+
+  0x00000000 73747269 6e672d33 00737472 696e672d string-3.string-
+  0x00000010 3400                                4.
+
 #...
 Contents of the .debug_str section \(loaded from .*debuglink.o\):
 
@@ -17,9 +23,4 @@ Contents of the .debug_info section \(loaded from .*debuglink.o\):
     <c>   DW_AT_name        : \(indirect string, offset: 0x0\): string-1
  <0><10>: Abbrev Number: 2 \(DW_TAG_subprogram\)
     <11>   DW_AT_name        : \(alt indirect string, offset: 0x0\) string-3
-
-Contents of the .debug_str section \(loaded from .*linkdebug.debug\):
-
-  0x00000000 73747269 6e672d33 00737472 696e672d string-3.string-
-  0x00000010 3400                                4.
-
+#pass
diff --git a/binutils/testsuite/binutils-all/objdump.WK3 b/binutils/testsuite/binutils-all/objdump.WK3
new file mode 100644 (file)
index 0000000..399cf52
--- /dev/null
@@ -0,0 +1,17 @@
+#...
+.*debuglink.o: Found separate debug info file:.*linkdebug.debug
+#...
+.*linkdebug.debug:.*
+#...
+ .* .debug_abbrev .*
+ .* .debug_str .*
+#...
+.*debuglink.o:.*
+#...
+ .* .gnu_debuglink .*
+ .* .gnu_debugaltlink .*
+ .* .debug_str .*
+ .* .debug_info .*
+#...
+ .* .debug_line .*
+#pass
index dd2e9bb02d036887c77697ac7bb1d51089a6ce20..81a061f70c1f8d9131aa570a86a4f2804400f761 100644 (file)
@@ -623,12 +623,12 @@ if { [is_elf_format] } then {
 # Very similar to proc test_build_id_debuglink except this time we
 # display some of the contents of the separate debug info file.
 
-proc test_follow_debuglink {} {
+proc test_follow_debuglink { options dumpfile } {
     global srcdir
     global subdir
     global OBJDUMP
     
-    set test "follow-debuglink"
+    set test "follow-debuglink ($options)"
 
     if {![binutils_assemble $srcdir/$subdir/debuglink.s tmpdir/debuglink.o]} then {
        fail "$test (reason: assemble first source file)"
@@ -647,13 +647,13 @@ proc test_follow_debuglink {} {
        set tempfile [remote_download host tmpdir/debuglink.o]
     }
     
-    set got [remote_exec host "$OBJDUMP --dwarf=follow-links --dwarf=info --dwarf=str $tempfile" "" "/dev/null" "tmpdir/objdump.out"]
+    set got [remote_exec host "$OBJDUMP $options $tempfile" "" "/dev/null" "tmpdir/objdump.out"]
     if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
        fail "$test (reason: unexpected error output from objdump)"
        return
     }
 
-    if { [regexp_diff tmpdir/objdump.out $srcdir/$subdir/objdump.WK2] } then {
+    if { [regexp_diff tmpdir/objdump.out $srcdir/$subdir/$dumpfile] } then {
        fail $test
        verbose "output is \n[file_contents objdump.out]" 2
        return
@@ -668,7 +668,8 @@ proc test_follow_debuglink {} {
 }
 
 if {[is_elf_format]} then {
-    test_follow_debuglink
+    test_follow_debuglink "--dwarf=follow-links --dwarf=info --dwarf=str" objdump.WK2
+    test_follow_debuglink "--dwarf=follow-links --headers --wide" objdump.WK3
 }
 
 # Options which are not tested: -a -D -R -T -x -l --stabs
index e41e22bf26d7c85845c528eb68bf76a63e70ad0c..0d9a42fba8332777f3509d850c660c9dd9893058 100644 (file)
@@ -489,7 +489,7 @@ if {![binutils_assemble $srcdir/$subdir/debuglink.s tmpdir/debuglink.o]} then {
            set tempfile2 [remote_download host tmpdir/linkdebug.debug]
        }
 
-       readelf_test {-wKis} $tempfile objdump.WK2  {}
+       readelf_test {-wKis} $tempfile readelf.wKis  {}
     }
 }
 
diff --git a/binutils/testsuite/binutils-all/readelf.wKis b/binutils/testsuite/binutils-all/readelf.wKis
new file mode 100644 (file)
index 0000000..5c7c0b2
--- /dev/null
@@ -0,0 +1,25 @@
+#...
+.*debuglink.o: Found separate debug info file:.*linkdebug.debug
+#...
+Contents of the .debug_str section \(loaded from .*debuglink.o\):
+
+  0x00000000 73747269 6e672d31 00737472 696e672d string-1.string-
+  0x00000010 3200                                2.
+#...
+Contents of the .debug_info section \(loaded from .*debuglink.o\):
+
+  Compilation Unit @ offset 0x0:
+   Length:        0x12 \(32-bit\)
+   Version:       4
+   Abbrev Offset: 0x0
+   Pointer Size:  4
+ <0><b>: Abbrev Number: 1 \(DW_TAG_compile_unit\)
+    <c>   DW_AT_name        : \(indirect string, offset: 0x0\): string-1
+ <0><10>: Abbrev Number: 2 \(DW_TAG_subprogram\)
+    <11>   DW_AT_name        : \(alt indirect string, offset: 0x0\) string-3
+#...
+Contents of the .debug_str section \(loaded from .*linkdebug.debug\):
+
+  0x00000000 73747269 6e672d33 00737472 696e672d string-3.string-
+  0x00000010 3400                                4.
+#pass