* dwarf2-frame.c (dwarf2_build_frame_info): Discard --gc-section
authorPedro Alves <palves@redhat.com>
Wed, 28 Oct 2009 19:28:57 +0000 (19:28 +0000)
committerPedro Alves <palves@redhat.com>
Wed, 28 Oct 2009 19:28:57 +0000 (19:28 +0000)
leftover FDEs.

gdb/ChangeLog
gdb/dwarf2-frame.c

index c0809007d01c325f0555b16ca3d1419cd12eb02d..a58386dcc7d1c5b1df5534c4ccdd654597d679c1 100644 (file)
@@ -1,3 +1,8 @@
+2009-10-28  Pedro Alves  <pedro@codesourcery.com>
+
+        * dwarf2-frame.c (dwarf2_build_frame_info): Discard --gc-section
+       leftover FDEs.
+
 2009-10-28  Pedro Alves  <pedro@codesourcery.com>
 
        * infrun.c (keep_going): Wrap with resume_cleanups.
index 5e9be2ccb2cc7ae896725ade66755e5c79672362..a4d6dd535965521a64021fc077b879b515c15928 100644 (file)
@@ -2101,7 +2101,9 @@ dwarf2_build_frame_info (struct objfile *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 *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;
+
+      /* 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];
 
-      /* 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.  */;
-        }
+         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.  */