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]

[RFA] Support multiple separate debug objfiles


Hi,

on Darwin, debug information are kept in object files.  We partially support
this by calling symbol_file_add but rereading a program doesn't work
correctly because objfiles added are not removed.

I think the best way to support this Darwin particularity is to extended the
notion of separate debug objfiles and allowing multiple separate debug
objfiles.

This patch implements this idea.  It mostly consists in adding a new field
in objfiles and minor adjustments.

No regressions on GNU Linux i386.

Tristan.

2009-12-23  Tristan Gingold  <gingold@adacore.com>

	* symtab.c (lookup_global_symbol_from_objfile): Rename objfile
	parameter to main_objfile.  Iterate on all separate debug objfiles.
	* symfile.h (symbol_file_add_separate)
	(find_separate_debug_file_by_debuglink): Remove parameter names.
	* symfile.c (symbol_file_add_separate): Use add_separate_objfile.
	(reread_symbols): Use free_objfile_separate_debug.
	* objfiles.h (struct objfile): Add separate_debug_objfile_link.
	Adjust comment.
	(objfile_separate_debug_iterate, add_separate_debug_objfile)
	(free_objfile_separate_debug): New prototypes.
	* objfiles.c (objfile_separate_debug_iterate): New function.
	(add_separate_debug_objfile, free_objfile_separate_debug): New
	functions.
	(free_objfile): Use free_objfile_separate_debug.  Adjust for
	multiple separate debug objfile.
	(objfile_has_symbols): Adjust comment.  Iterate on all separate
	debug objfiles.
	* minsyms.c (lookup_minimal_symbol): Adjust for multiple separate
	debug objfile.
	(lookup_minimal_symbol_text): Ditto.
	(lookup_minimal_symbol_by_pc_name): Ditto.
	(lookup_minimal_symbol_solib_trampoline): Ditto.
	(lookup_minimal_symbol_by_pc_section_1): Iterate on all separate
	debug objfiles.
---
 gdb/minsyms.c  |   15 +++----
 gdb/objfiles.c |  124 +++++++++++++++++++++++++++++++++++++++++++++++---------
 gdb/objfiles.h |   25 +++++++++--
 gdb/symfile.c  |   21 ++-------
 gdb/symfile.h  |    5 +-
 gdb/symtab.c   |   66 +++++++++++++++--------------
 6 files changed, 173 insertions(+), 83 deletions(-)

diff --git a/gdb/minsyms.c b/gdb/minsyms.c
index c177c02..ee730a4 100644
--- a/gdb/minsyms.c
+++ b/gdb/minsyms.c
@@ -216,7 +216,7 @@ lookup_minimal_symbol (const char *name, const char *sfile,
        objfile = objfile->next)
     {
       if (objf == NULL || objf == objfile
-	  || objf->separate_debug_objfile == objfile)
+	  || objf == objfile->separate_debug_objfile_backlink)
 	{
 	  /* Do two passes: the first over the ordinary hash table,
 	     and the second over the demangled hash table.  */
@@ -324,7 +324,7 @@ lookup_minimal_symbol_text (const char *name, struct objfile *objf)
        objfile = objfile->next)
     {
       if (objf == NULL || objf == objfile
-	  || objf->separate_debug_objfile == objfile)
+	  || objf == objfile->separate_debug_objfile_backlink)
 	{
 	  for (msymbol = objfile->msymbol_hash[hash];
 	       msymbol != NULL && found_symbol == NULL;
@@ -377,7 +377,7 @@ lookup_minimal_symbol_by_pc_name (CORE_ADDR pc, const char *name,
        objfile = objfile->next)
     {
       if (objf == NULL || objf == objfile
-	  || objf->separate_debug_objfile == objfile)
+	  || objf == objfile->separate_debug_objfile_backlink)
 	{
 	  for (msymbol = objfile->msymbol_hash[hash];
 	       msymbol != NULL;
@@ -416,7 +416,7 @@ lookup_minimal_symbol_solib_trampoline (const char *name,
        objfile = objfile->next)
     {
       if (objf == NULL || objf == objfile
-	  || objf->separate_debug_objfile == objfile)
+	  || objf == objfile->separate_debug_objfile_backlink)
 	{
 	  for (msymbol = objfile->msymbol_hash[hash];
 	       msymbol != NULL && found_symbol == NULL;
@@ -473,11 +473,10 @@ lookup_minimal_symbol_by_pc_section_1 (CORE_ADDR pc,
      no telling which one will have the minimal symbols.  */
 
   gdb_assert (section != NULL);
-  objfile = section->objfile;
-  if (objfile->separate_debug_objfile)
-    objfile = objfile->separate_debug_objfile;
 
-  for (; objfile != NULL; objfile = objfile->separate_debug_objfile_backlink)
+  for (objfile = section->objfile;
+       objfile != NULL;
+       objfile = objfile_separate_debug_iterate (section->objfile, objfile))
     {
       /* If this objfile has a minimal symbol table, go search it using
          a binary search.  Note that a minimal symbol table always consists
diff --git a/gdb/objfiles.c b/gdb/objfiles.c
index c241e8f..995bf11 100644
--- a/gdb/objfiles.c
+++ b/gdb/objfiles.c
@@ -378,6 +378,42 @@ 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;
+
+  res = objfile->separate_debug_objfile;
+  if (res)
+    return res;
+
+  res = objfile->separate_debug_objfile_link;
+  if (res)
+    return res;
+
+  /* Common case where there is no separate debug objfile.  */
+  if (objfile == parent)
+    return NULL;
+
+  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 +491,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 +546,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
@@ -778,25 +871,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 throught 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;
 }
 
diff --git a/gdb/objfiles.h b/gdb/objfiles.h
index cf5fc38..c689622 100644
--- a/gdb/objfiles.h
+++ b/gdb/objfiles.h
@@ -363,15 +363,25 @@ struct objfile
     struct obj_section
      *sections, *sections_end;
 
-    /* Link to objfile that contains the debug symbols for this one.
-       One is loaded if this file has an debug link to an existing
-       debug file with the right checksum */
+    /* GDB allows to have debug symbols in separate object files.  This is
+       used by .gnu_debuglink, ELF build id note and Mach-O OSO.
+       Although this is a tree structure, GDB only support one level
+       (ie a separate debug for a separate debug is not supported).  Note that
+       separate debug object are in the main chain and therefore will be
+       visited by ALL_OBJFILES & co iterators.  Separate debug objfile always
+       has a non-nul separate_debug_objfile_backlink.  */
+
+    /* Link to the first separate debug object, if any.  */
     struct objfile *separate_debug_objfile;
 
     /* If this is a separate debug object, this is used as a link to the
        actual executable objfile. */
     struct objfile *separate_debug_objfile_backlink;
-    
+
+    /* If this is a separate debug object, this is a link to the next one
+       for the same executable objfile.  */
+    struct objfile *separate_debug_objfile_link;
+
     /* Place to stash various statistics about this objfile */
       OBJSTATS;
 
@@ -452,14 +462,21 @@ extern int build_objfile_section_table (struct objfile *);
 
 extern void terminate_minimal_symbol_table (struct objfile *objfile);
 
+extern struct objfile *objfile_separate_debug_iterate (const struct objfile *,
+                                                       const struct objfile *);
+
 extern void put_objfile_before (struct objfile *, struct objfile *);
 
 extern void objfile_to_front (struct objfile *);
 
+extern void add_separate_debug_objfile (struct objfile *, struct objfile *);
+
 extern void unlink_objfile (struct objfile *);
 
 extern void free_objfile (struct objfile *);
 
+extern void free_objfile_separate_debug (struct objfile *);
+
 extern struct cleanup *make_cleanup_free_objfile (struct objfile *);
 
 extern void free_all_objfiles (void);
diff --git a/gdb/symfile.c b/gdb/symfile.c
index 11bc2af..2b58851 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -1042,22 +1042,16 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
 void
 symbol_file_add_separate (bfd *bfd, int symfile_flags, struct objfile *objfile)
 {
-  /* Currently only one separate debug objfile is supported.  */
-  gdb_assert (objfile && objfile->separate_debug_objfile == NULL);
+  struct objfile *new_objfile;
 
-  objfile->separate_debug_objfile =
-    symbol_file_add_with_addrs_or_offsets
+  new_objfile = symbol_file_add_with_addrs_or_offsets
     (bfd, symfile_flags,
      0, /* No addr table.  */
      objfile->section_offsets, objfile->num_sections,
      objfile->flags & (OBJF_REORDERED | OBJF_SHARED | OBJF_READNOW
 		       | OBJF_USERLOADED));
-  objfile->separate_debug_objfile->separate_debug_objfile_backlink
-    = 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->separate_debug_objfile, objfile);
+  add_separate_debug_objfile (new_objfile, objfile);
 }
 
 /* Process the symbol file ABFD, as either the main file or as a
@@ -2272,14 +2266,9 @@ reread_symbols (void)
 
 	  clear_objfile_data (objfile);
 
-	  /* Free the separate debug objfile if there is one.  It will be
+	  /* Free the separate debug objfiles.  It will be
 	     automatically recreated by sym_read.  */
-	  if (objfile->separate_debug_objfile)
-	    {
-	      /* Note: no need to clear separate_debug_objfile field as it is
-		 done by free_objfile.  */
-	      free_objfile (objfile->separate_debug_objfile);
-	    }
+          free_objfile_separate_debug (objfile);
 
 	  /* FIXME: Do we have to free a whole linked list, or is this
 	     enough?  */
diff --git a/gdb/symfile.h b/gdb/symfile.h
index 8eb1b5e..f9c4daa 100644
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -238,10 +238,9 @@ extern struct objfile *symbol_file_add_from_bfd (bfd *, int,
                                                  struct section_addr_info *,
                                                  int);
 
-extern void symbol_file_add_separate (bfd *bfd, int symfile_flags,
-				      struct objfile *objfile);
+extern void symbol_file_add_separate (bfd *, int, struct objfile *);
 
-extern char *find_separate_debug_file_by_debuglink (struct objfile *objfile);
+extern char *find_separate_debug_file_by_debuglink (struct objfile *);
 
 /* Create a new section_addr_info, with room for NUM_SECTIONS.  */
 
diff --git a/gdb/symtab.c b/gdb/symtab.c
index d7b8145..7f5dabd 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -1499,48 +1499,50 @@ lookup_symbol_aux_block (const char *name, const char *linkage_name,
    psymtabs.  */
 
 struct symbol *
-lookup_global_symbol_from_objfile (const struct objfile *objfile,
+lookup_global_symbol_from_objfile (const struct objfile *main_objfile,
 				   const char *name,
 				   const char *linkage_name,
 				   const domain_enum domain)
 {
+  const struct objfile *objfile;
   struct symbol *sym;
   struct blockvector *bv;
   const struct block *block;
   struct symtab *s;
   struct partial_symtab *ps;
 
-  /* Go through symtabs.  */
-  ALL_OBJFILE_SYMTABS (objfile, s)
-  {
-    bv = BLOCKVECTOR (s);
-    block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-    sym = lookup_block_symbol (block, name, linkage_name, domain);
-    if (sym)
-      {
-	block_found = block;
-	return fixup_symbol_section (sym, (struct objfile *)objfile);
-      }
-  }
-
-  /* Now go through psymtabs.  */
-  ALL_OBJFILE_PSYMTABS (objfile, ps)
-  {
-    if (!ps->readin
-	&& lookup_partial_symbol (ps, name, linkage_name,
-				  1, domain))
-      {
-	s = PSYMTAB_TO_SYMTAB (ps);
-	bv = BLOCKVECTOR (s);
-	block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-	sym = lookup_block_symbol (block, name, linkage_name, domain);
-	return fixup_symbol_section (sym, (struct objfile *)objfile);
-      }
-  }
-
-  if (objfile->separate_debug_objfile)
-    return lookup_global_symbol_from_objfile (objfile->separate_debug_objfile,
-					      name, linkage_name, domain);
+  for (objfile = main_objfile;
+       objfile;
+       objfile = objfile_separate_debug_iterate (main_objfile, objfile))
+    {
+      /* Go through symtabs.  */
+      ALL_OBJFILE_SYMTABS (objfile, s)
+        {
+          bv = BLOCKVECTOR (s);
+          block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+          sym = lookup_block_symbol (block, name, linkage_name, domain);
+          if (sym)
+            {
+              block_found = block;
+              return fixup_symbol_section (sym, (struct objfile *)objfile);
+            }
+        }
+
+      /* Now go through psymtabs.  */
+      ALL_OBJFILE_PSYMTABS (objfile, ps)
+        {
+          if (!ps->readin
+              && lookup_partial_symbol (ps, name, linkage_name,
+                                        1, domain))
+            {
+              s = PSYMTAB_TO_SYMTAB (ps);
+              bv = BLOCKVECTOR (s);
+              block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+              sym = lookup_block_symbol (block, name, linkage_name, domain);
+              return fixup_symbol_section (sym, (struct objfile *)objfile);
+            }
+        }
+    }
 
   return NULL;
 }
-- 
1.6.5.rc2


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