This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

--gc-section leftovers workaround.


With --gc-sections, gnu ld zeros out the start addresses of
unreferences FDEs, but leaves them behind.  On targets where
addresses near 0 are valid, GDB can easily confuse these
leftovers for the valid FDEs, ending up with invalid debug
info loaded for such low addresses.  Since  this is a problem
that has beein in the field for a while, an FSF GDB
workaround seems appropriate, given that it is a simple
workaround --- give preference to FDEs that do not
start at zero when overlaps are detected.

Given that we now sort and bsearch FDEs, GDB is already giving
such preference as a side effect, but the code that discards
duplicate FDEs could be discarding the valid FDEs at 0, and
keep an FDE that should have been garbage collected.  This patch
makes the overlap check explicit so as to avoid that.   Tested on
arm-none-eabi where it fixed the problem, and on
x86_64-unknown-linux-gnu.  Applied.

-- 
Pedro Alves

2009-10-28  Pedro Alves  <pedro@codesourcery.com>

        * dwarf2-frame.c (dwarf2_build_frame_info): Discard --gc-section
	leftover FDEs.

---
 gdb/dwarf2-frame.c |   44 +++++++++++++++++++++++++++++++-------------
 1 file changed, 31 insertions(+), 13 deletions(-)

Index: src/gdb/dwarf2-frame.c
===================================================================
--- src.orig/gdb/dwarf2-frame.c	2009-10-23 19:05:16.000000000 +0100
+++ src/gdb/dwarf2-frame.c	2009-10-28 17:15:10.000000000 +0000
@@ -2101,7 +2101,8 @@ dwarf2_build_frame_info (struct objfile 
   if (fde_table.num_entries != 0)
     {
       struct dwarf2_fde_table *fde_table2;
-      int i, j;
+      struct dwarf2_fde *fde_prev = NULL;
+      int i;
 
       /* Prepare FDE table for lookups.  */
       qsort (fde_table.entries, fde_table.num_entries,
@@ -2110,22 +2111,39 @@ dwarf2_build_frame_info (struct objfile 
       /* Copy fde_table to obstack: it is needed at runtime.  */
       fde_table2 = (struct dwarf2_fde_table *)
           obstack_alloc (&objfile->objfile_obstack, sizeof (*fde_table2));
+      fde_table2->num_entries = 0;
 
       /* Since we'll be doing bsearch, squeeze out identical (except for
          eh_frame_p) fde entries so bsearch result is predictable.  */
-      for (i = 0, j = 0; j < fde_table.num_entries; ++i)
-        {
-          const int k = j;
-
-          obstack_grow (&objfile->objfile_obstack, &fde_table.entries[j],
-                        sizeof (fde_table.entries[0]));
-          while (++j < fde_table.num_entries
-                 && (fde_table.entries[k]->initial_location
-                     == fde_table.entries[j]->initial_location))
-            /* Skip.  */;
-        }
+      for (i = 0; i < fde_table.num_entries; i++)
+	{
+	  struct dwarf2_fde *fde = fde_table.entries[i];
+
+	  /* Check for leftovers from --gc-sections.  The GNU linker
+	     sets the relevant symbols to zero, but doesn't zero the
+	     FDE *end* ranges because there's no relocation there.
+	     It's (offset, length), not (start, end).  On targets
+	     where address zero is just another valid address this can
+	     be a problem, since the FDEs appear to be non-empty in
+	     the output --- we could pick out the wrong FDE.  To work
+	     around this, when overlaps are detected, we prefer FDEs
+	     that do not start at zero.  */
+	  if (fde->initial_location == 0
+	      && (i + 1) < fde_table.num_entries
+	      && ((fde_table.entries[i + 1])->initial_location
+		  < fde->initial_location + fde->address_range))
+	    continue;
+
+	  if (fde_prev != NULL
+	      && fde_prev->initial_location == fde->initial_location)
+	    continue;
+
+	  obstack_grow (&objfile->objfile_obstack, &fde_table.entries[i],
+			sizeof (fde_table.entries[0]));
+	  ++fde_table2->num_entries;
+	  fde_prev = fde;
+	}
       fde_table2->entries = obstack_finish (&objfile->objfile_obstack);
-      fde_table2->num_entries = i;
       set_objfile_data (objfile, dwarf2_frame_objfile_data, fde_table2);
 
       /* Discard the original fde_table.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]