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]

Re: --gc-section leftovers workaround.


On Wednesday 28 October 2009 18:51:00, Pedro Alves wrote:
> 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.

I managed to post and apply the wrong patch.  I've reverted
it already.

Here's the correct patch that I'll (re-)apply in a bit.

-- 
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 |   64 ++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 49 insertions(+), 15 deletions(-)

Index: src/gdb/dwarf2-frame.c
===================================================================
--- src.orig/gdb/dwarf2-frame.c	2009-10-28 18:59:53.000000000 +0000
+++ src/gdb/dwarf2-frame.c	2009-10-28 19:07:29.000000000 +0000
@@ -2101,7 +2101,9 @@ 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;
+      struct dwarf2_fde *first_non_zero_fde = NULL;
+      int i;
 
       /* Prepare FDE table for lookups.  */
       qsort (fde_table.entries, fde_table.num_entries,
@@ -2110,22 +2112,54 @@ 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.  */;
-        }
+      /* 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.
+
+	 Start by finding the first FDE with non-zero start.  Below
+	 we'll discard all FDEs that start at zero and overlap this
+	 one.  */
+      for (i = 0; i < fde_table.num_entries; i++)
+	{
+	  struct dwarf2_fde *fde = fde_table.entries[i];
+
+	  if (fde->initial_location != 0)
+	    {
+	      first_non_zero_fde = fde;
+	      break;
+	    }
+	}
+
+      /* Since we'll be doing bsearch, squeeze out identical (except
+	 for eh_frame_p) fde entries so bsearch result is predictable.
+	 Also discard leftovers from --gc-sections.  */
+      for (i = 0; i < fde_table.num_entries; i++)
+	{
+	  struct dwarf2_fde *fde = fde_table.entries[i];
+
+	  if (fde->initial_location == 0
+	      && first_non_zero_fde != NULL
+	      && (first_non_zero_fde->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]