*** empty log message ***
[deliverable/binutils-gdb.git] / gdb / objfiles.c
index 48f261362241d67aed48e75b5ca956fd75335857..cacdabae3b7352e4cd2898608a87c221af49bf4f 100644 (file)
@@ -1,7 +1,7 @@
 /* GDB routines for manipulating objfiles.
 
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-   2002, 2003, 2004, 2007, 2008, 2009 Free Software Foundation, Inc.
+   2002, 2003, 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
    Contributed by Cygnus Support, using pieces from other GDB modules.
 
@@ -52,6 +52,8 @@
 #include "exec.h"
 #include "observer.h"
 #include "complaints.h"
+#include "psymtab.h"
+#include "solist.h"
 
 /* Prototypes for local functions */
 
@@ -378,6 +380,45 @@ terminate_minimal_symbol_table (struct objfile *objfile)
   }
 }
 
+/* Iterator on PARENT and every separate debug objfile of PARENT.
+   The usage pattern is:
+     for (objfile = parent;
+          objfile;
+          objfile = objfile_separate_debug_iterate (parent, objfile))
+       ...
+*/
+
+struct objfile *
+objfile_separate_debug_iterate (const struct objfile *parent,
+                                const struct objfile *objfile)
+{
+  struct objfile *res;
+
+  /* If any, return the first child.  */
+  res = objfile->separate_debug_objfile;
+  if (res)
+    return res;
+
+  /* Common case where there is no separate debug objfile.  */
+  if (objfile == parent)
+    return NULL;
+
+  /* Return the brother if any.  Note that we don't iterate on brothers of
+     the parents.  */
+  res = objfile->separate_debug_objfile_link;
+  if (res)
+    return res;
+
+  for (res = objfile->separate_debug_objfile_backlink;
+       res != parent;
+       res = res->separate_debug_objfile_backlink)
+    {
+      gdb_assert (res != NULL);
+      if (res->separate_debug_objfile_link)
+        return res->separate_debug_objfile_link;
+    }
+  return NULL;
+}
 
 /* Put one object file before a specified on in the global list.
    This can be used to make sure an object file is destroyed before
@@ -455,6 +496,41 @@ unlink_objfile (struct objfile *objfile)
                  _("unlink_objfile: objfile already unlinked"));
 }
 
+/* Add OBJFILE as a separate debug objfile of PARENT.  */
+
+void
+add_separate_debug_objfile (struct objfile *objfile, struct objfile *parent)
+{
+  gdb_assert (objfile && parent);
+
+  /* Must not be already in a list.  */
+  gdb_assert (objfile->separate_debug_objfile_backlink == NULL);
+  gdb_assert (objfile->separate_debug_objfile_link == NULL);
+
+  objfile->separate_debug_objfile_backlink = parent;
+  objfile->separate_debug_objfile_link = parent->separate_debug_objfile;
+  parent->separate_debug_objfile = objfile;
+
+  /* Put the separate debug object before the normal one, this is so that
+     usage of the ALL_OBJFILES_SAFE macro will stay safe. */
+  put_objfile_before (objfile, parent);
+}
+
+/* Free all separate debug objfile of OBJFILE, but don't free OBJFILE
+   itself.  */
+
+void
+free_objfile_separate_debug (struct objfile *objfile)
+{
+  struct objfile *child;
+
+  for (child = objfile->separate_debug_objfile; child;)
+    {
+      struct objfile *next_child = child->separate_debug_objfile_link;
+      free_objfile (child);
+      child = next_child;
+    }
+}
 
 /* Destroy an objfile and all the symtabs and psymtabs under it.  Note
    that as much as possible is allocated on the objfile_obstack 
@@ -475,16 +551,38 @@ unlink_objfile (struct objfile *objfile)
 void
 free_objfile (struct objfile *objfile)
 {
-  if (objfile->separate_debug_objfile)
-    {
-      free_objfile (objfile->separate_debug_objfile);
-    }
-  
+  /* Free all separate debug objfiles.  */
+  free_objfile_separate_debug (objfile);
+
   if (objfile->separate_debug_objfile_backlink)
     {
       /* We freed the separate debug file, make sure the base objfile
         doesn't reference it.  */
-      objfile->separate_debug_objfile_backlink->separate_debug_objfile = NULL;
+      struct objfile *child;
+
+      child = objfile->separate_debug_objfile_backlink->separate_debug_objfile;
+
+      if (child == objfile)
+        {
+          /* OBJFILE is the first child.  */
+          objfile->separate_debug_objfile_backlink->separate_debug_objfile =
+            objfile->separate_debug_objfile_link;
+        }
+      else
+        {
+          /* Find OBJFILE in the list.  */
+          while (1)
+            {
+              if (child->separate_debug_objfile_link == objfile)
+                {
+                  child->separate_debug_objfile_link =
+                    objfile->separate_debug_objfile_link;
+                  break;
+                }
+              child = child->separate_debug_objfile_link;
+              gdb_assert (child);
+            }
+        }
     }
   
   /* Remove any references to this objfile in the global value
@@ -591,6 +689,11 @@ void
 free_all_objfiles (void)
 {
   struct objfile *objfile, *temp;
+  struct so_list *so;
+
+  /* Any objfile referencewould become stale.  */
+  for (so = master_so_list (); so; so = so->next)
+    gdb_assert (so->objfile == NULL);
 
   ALL_OBJFILES_SAFE (objfile, temp)
   {
@@ -600,9 +703,11 @@ free_all_objfiles (void)
 }
 \f
 /* Relocate OBJFILE to NEW_OFFSETS.  There should be OBJFILE->NUM_SECTIONS
-   entries in new_offsets.  */
-void
-objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets)
+   entries in new_offsets.  SEPARATE_DEBUG_OBJFILE is not touched here.
+   Return non-zero iff any change happened.  */
+
+static int
+objfile_relocate1 (struct objfile *objfile, struct section_offsets *new_offsets)
 {
   struct obj_section *s;
   struct section_offsets *delta =
@@ -620,7 +725,7 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets)
          something_changed = 1;
       }
     if (!something_changed)
-      return;
+      return 0;
   }
 
   /* OK, get all the symtabs.  */
@@ -680,38 +785,12 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets)
     }
   }
 
-  {
-    struct partial_symtab *p;
+  if (objfile->psymtabs_addrmap)
+    addrmap_relocate (objfile->psymtabs_addrmap,
+                     ANOFFSET (delta, SECT_OFF_TEXT (objfile)));
 
-    ALL_OBJFILE_PSYMTABS (objfile, p)
-    {
-      p->textlow += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
-      p->texthigh += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
-    }
-  }
-
-  {
-    struct partial_symbol **psym;
-
-    for (psym = objfile->global_psymbols.list;
-        psym < objfile->global_psymbols.next;
-        psym++)
-      {
-       fixup_psymbol_section (*psym, objfile);
-       if (SYMBOL_SECTION (*psym) >= 0)
-         SYMBOL_VALUE_ADDRESS (*psym) += ANOFFSET (delta,
-                                                   SYMBOL_SECTION (*psym));
-      }
-    for (psym = objfile->static_psymbols.list;
-        psym < objfile->static_psymbols.next;
-        psym++)
-      {
-       fixup_psymbol_section (*psym, objfile);
-       if (SYMBOL_SECTION (*psym) >= 0)
-         SYMBOL_VALUE_ADDRESS (*psym) += ANOFFSET (delta,
-                                                   SYMBOL_SECTION (*psym));
-      }
-  }
+  if (objfile->sf)
+    objfile->sf->qf->relocate (objfile, new_offsets, delta);
 
   {
     struct minimal_symbol *msym;
@@ -753,8 +832,61 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets)
                                obj_section_addr (s));
     }
 
+  /* Data changed.  */
+  return 1;
+}
+
+/* Relocate OBJFILE to NEW_OFFSETS.  There should be OBJFILE->NUM_SECTIONS
+   entries in new_offsets.  Process also OBJFILE's SEPARATE_DEBUG_OBJFILEs.
+
+   The number and ordering of sections does differ between the two objfiles.
+   Only their names match.  Also the file offsets will differ (objfile being
+   possibly prelinked but separate_debug_objfile is probably not prelinked) but
+   the in-memory absolute address as specified by NEW_OFFSETS must match both
+   files.  */
+
+void
+objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets)
+{
+  struct objfile *debug_objfile;
+  int changed = 0;
+
+  changed |= objfile_relocate1 (objfile, new_offsets);
+
+  for (debug_objfile = objfile->separate_debug_objfile;
+       debug_objfile;
+       debug_objfile = objfile_separate_debug_iterate (objfile, debug_objfile))
+    {
+      struct section_addr_info *objfile_addrs;
+      struct section_offsets *new_debug_offsets;
+      int new_debug_num_sections;
+      struct cleanup *my_cleanups;
+
+      objfile_addrs = build_section_addr_info_from_objfile (objfile);
+      my_cleanups = make_cleanup (xfree, objfile_addrs);
+
+      /* Here OBJFILE_ADDRS contain the correct absolute addresses, the
+        relative ones must be already created according to debug_objfile.  */
+
+      addr_info_make_relative (objfile_addrs, debug_objfile->obfd);
+
+      gdb_assert (debug_objfile->num_sections
+                 == bfd_count_sections (debug_objfile->obfd));
+      new_debug_offsets = xmalloc (SIZEOF_N_SECTION_OFFSETS
+                                                (debug_objfile->num_sections));
+      make_cleanup (xfree, new_debug_offsets);
+      relative_addr_info_to_section_offsets (new_debug_offsets,
+                                            debug_objfile->num_sections,
+                                            objfile_addrs);
+
+      changed |= objfile_relocate1 (debug_objfile, new_debug_offsets);
+
+      do_cleanups (my_cleanups);
+    }
+
   /* Relocate breakpoints as necessary, after things are relocated. */
-  breakpoint_re_set ();
+  if (changed)
+    breakpoint_re_set ();
 }
 \f
 /* Return non-zero if OBJFILE has partial symbols.  */
@@ -762,7 +894,7 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets)
 int
 objfile_has_partial_symbols (struct objfile *objfile)
 {
-  return objfile->psymtabs != NULL;
+  return objfile->sf ? objfile->sf->qf->has_symbols (objfile) : 0;
 }
 
 /* Return non-zero if OBJFILE has full symbols.  */
@@ -774,25 +906,16 @@ objfile_has_full_symbols (struct objfile *objfile)
 }
 
 /* Return non-zero if OBJFILE has full or partial symbols, either directly
-   or throught its separate debug file.  */
+   or through a separate debug file.  */
 
 int
 objfile_has_symbols (struct objfile *objfile)
 {
-  struct objfile *separate_objfile;
-
-  if (objfile_has_partial_symbols (objfile)
-      || objfile_has_full_symbols (objfile))
-    return 1;
-
-  separate_objfile = objfile->separate_debug_objfile;
-  if (separate_objfile == NULL)
-    return 0;
-
-  if (objfile_has_partial_symbols (separate_objfile)
-      || objfile_has_full_symbols (separate_objfile))
-    return 1;
+  struct objfile *o;
 
+  for (o = objfile; o; o = objfile_separate_debug_iterate (objfile, o))
+    if (objfile_has_partial_symbols (o) || objfile_has_full_symbols (o))
+      return 1;
   return 0;
 }
 
@@ -1354,11 +1477,33 @@ objfiles_changed (void)
   get_objfile_pspace_data (current_program_space)->objfiles_changed_p = 1;
 }
 
+/* Close ABFD, and warn if that fails.  */
+
+int
+gdb_bfd_close_or_warn (struct bfd *abfd)
+{
+  int ret;
+  char *name = bfd_get_filename (abfd);
+
+  ret = bfd_close (abfd);
+
+  if (!ret)
+    warning (_("cannot close \"%s\": %s"),
+            name, bfd_errmsg (bfd_get_error ()));
+
+  return ret;
+}
+
 /* Add reference to ABFD.  Returns ABFD.  */
 struct bfd *
 gdb_bfd_ref (struct bfd *abfd)
 {
-  int *p_refcount = bfd_usrdata (abfd);
+  int *p_refcount;
+
+  if (abfd == NULL)
+    return NULL;
+
+  p_refcount = bfd_usrdata (abfd);
 
   if (p_refcount != NULL)
     {
@@ -1397,9 +1542,7 @@ gdb_bfd_unref (struct bfd *abfd)
   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 ()));
+  gdb_bfd_close_or_warn (abfd);
   xfree (name);
 }
 
This page took 0.029023 seconds and 4 git commands to generate.