* scripttempl/elf.sc: Discard sections with .gnu.lto_ prefix.
[deliverable/binutils-gdb.git] / gdb / objfiles.c
index c983b116135107e0bde0d09dd1e2e9fa926584bf..92db65ef7c061f89f666f803108b6eec74323a2a 100644 (file)
@@ -452,16 +452,7 @@ free_objfile (struct objfile *objfile)
   /* Discard any data modules have associated with the objfile.  */
   objfile_free_data (objfile);
 
-  /* We always close the bfd, unless the OBJF_KEEPBFD flag is set.  */
-
-  if (objfile->obfd != NULL && !(objfile->flags & OBJF_KEEPBFD))
-    {
-      char *name = bfd_get_filename (objfile->obfd);
-      if (!bfd_close (objfile->obfd))
-       warning (_("cannot close \"%s\": %s"),
-                name, bfd_errmsg (bfd_get_error ()));
-      xfree (name);
-    }
+  gdb_bfd_unref (objfile->obfd);
 
   /* Remove it from the chain of all objfiles. */
 
@@ -675,12 +666,6 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets)
      to be out of order.  */
   msymbols_sort (objfile);
 
-  {
-    int i;
-    for (i = 0; i < objfile->num_sections; ++i)
-      (objfile->section_offsets)->offsets[i] = ANOFFSET (new_offsets, i);
-  }
-
   if (objfile->ei.entry_point != ~(CORE_ADDR) 0)
     {
       /* Relocate ei.entry_point with its section offset, use SECT_OFF_TEXT
@@ -693,6 +678,15 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets)
         objfile->ei.entry_point += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
     }
 
+  {
+    int i;
+    for (i = 0; i < objfile->num_sections; ++i)
+      (objfile->section_offsets)->offsets[i] = ANOFFSET (new_offsets, i);
+  }
+
+  /* Rebuild section map next time we need it.  */
+  objfiles_changed_p = 1;
+
   /* Update the table in exec_ops, used to read memory.  */
   ALL_OBJFILE_OSECTIONS (objfile, s)
     {
@@ -704,7 +698,6 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets)
 
   /* Relocate breakpoints as necessary, after things are relocated. */
   breakpoint_re_set ();
-  objfiles_changed_p = 1;  /* Rebuild section map next time we need it.  */
 }
 \f
 /* Many places in gdb want to test just to see if we have any partial
@@ -806,18 +799,36 @@ qsort_cmp (const void *a, const void *b)
       gdb_assert (sect1_addr >= obj_section_endaddr (sect2));
       return 1;
     }
-  /* This can happen for separate debug-info files.  */
-  gdb_assert (obj_section_endaddr (sect1) == obj_section_endaddr (sect2));
 
   return 0;
 }
 
+/* Select "better" obj_section to keep.  We prefer the one that came from
+   the real object, rather than the one from separate debuginfo.
+   Most of the time the two sections are exactly identical, but with
+   prelinking the .rel.dyn section in the real object may have different
+   size.  */
+
+static struct obj_section *
+preferred_obj_section (struct obj_section *a, struct obj_section *b)
+{
+  gdb_assert (obj_section_addr (a) == obj_section_addr (b));
+  gdb_assert ((a->objfile->separate_debug_objfile == b->objfile)
+             || (b->objfile->separate_debug_objfile == a->objfile));
+  gdb_assert ((a->objfile->separate_debug_objfile_backlink == b->objfile)
+             || (b->objfile->separate_debug_objfile_backlink == a->objfile));
+
+  if (a->objfile->separate_debug_objfile != NULL)
+    return a;
+  return b;
+}
+
 /* Update PMAP, PMAP_SIZE with non-TLS sections from all objfiles.  */
 
 static void
 update_section_map (struct obj_section ***pmap, int *pmap_size)
 {
-  int map_size, idx;
+  int map_size, i, j;
   struct obj_section *s, **map;
   struct objfile *objfile;
 
@@ -837,15 +848,45 @@ update_section_map (struct obj_section ***pmap, int *pmap_size)
 
   map = xmalloc (map_size * sizeof (*map));
 
-  idx = 0;
+  i = 0;
   ALL_OBJSECTIONS (objfile, s)
     if (insert_p (objfile, s))
-      map[idx++] = s;
+      map[i++] = s;
 
 #undef insert_p
 
   qsort (map, map_size, sizeof (*map), qsort_cmp);
 
+  /* With separate debuginfo files, we may have up to two (almost)
+     identical copies of some obj_sections in the map.
+     Filter out duplicates.  */
+  for (i = 0, j = 0; i < map_size; ++i)
+    {
+      struct obj_section *sect1 = map[i];
+      struct obj_section *sect2 = (i + 1 < map_size) ? map[i + 1] : NULL;
+
+      if (sect2 == NULL
+         || obj_section_addr (sect1) != obj_section_addr (sect2))
+       map[j++] = sect1;
+      else
+       {
+         map[j++] = preferred_obj_section (sect1, sect2);
+         ++i;
+       }
+    }
+
+  if (j < map_size)
+    {
+      /* Some duplicates were eliminated.
+        The new size shouldn't be less than half of the original. */
+      gdb_assert (map_size / 2 <= j);
+      map_size = j;
+
+      map = xrealloc (map, map_size * sizeof (*map));  /* Trim excess space.  */
+    }
+  else
+    gdb_assert (j == map_size);
+
   *pmap = map;
   *pmap_size = map_size;
 }
@@ -1020,3 +1061,35 @@ objfiles_changed (void)
 {
   objfiles_changed_p = 1;  /* Rebuild section map next time we need it.  */
 }
+
+/* Unreference and possibly close abfd.  */
+void
+gdb_bfd_unref (struct bfd *abfd)
+{
+  int *p_refcount;
+  char *name;
+
+  if (abfd == NULL)
+    return;
+
+  p_refcount = bfd_usrdata (abfd);
+
+  /* Valid range for p_refcount: NULL (single owner), or a pointer
+     to int counter, which has a value of 1 (single owner) or 2 (shared).  */
+  gdb_assert (p_refcount == NULL || *p_refcount == 1 || *p_refcount == 2);
+
+  if (p_refcount != NULL)
+    {
+      *p_refcount -= 1;
+      if (*p_refcount > 0)
+       return;
+    }
+  xfree (p_refcount);
+  bfd_usrdata (abfd) = NULL;  /* Paranoia.  */
+
+  name = bfd_get_filename (abfd);
+  if (!bfd_close (abfd))
+    warning (_("cannot close \"%s\": %s"),
+            name, bfd_errmsg (bfd_get_error ()));
+  xfree (name);
+}
This page took 0.025507 seconds and 4 git commands to generate.