* psymtab.c (partial_map_expand_apply): Add assertion.
authorTom Tromey <tromey@redhat.com>
Thu, 10 May 2012 19:54:45 +0000 (19:54 +0000)
committerTom Tromey <tromey@redhat.com>
Thu, 10 May 2012 19:54:45 +0000 (19:54 +0000)
(partial_map_symtabs_matching_filename): Skip included psymtabs.
(psymtab_to_symtab): Find unshared psymtab.
(dump_psymtab): Print including psymtabs.
(recursively_search_psymtabs): New function.
(expand_symtabs_matching_via_partial): Use it.
* psympriv.h (struct partial_symtab) <user, searched_flag>: New
fields.
(enum psymtab_search_status): New.

gdb/ChangeLog
gdb/psympriv.h
gdb/psymtab.c

index f62a45fb80de4f90dd9df3d571aeb9b4afe8a514..151c515a6db1db7fcd6ae166c6c27fbd073f47e2 100644 (file)
@@ -1,3 +1,15 @@
+2012-05-10  Tom Tromey  <tromey@redhat.com>
+
+       * psymtab.c (partial_map_expand_apply): Add assertion.
+       (partial_map_symtabs_matching_filename): Skip included psymtabs.
+       (psymtab_to_symtab): Find unshared psymtab.
+       (dump_psymtab): Print including psymtabs.
+       (recursively_search_psymtabs): New function.
+       (expand_symtabs_matching_via_partial): Use it.
+       * psympriv.h (struct partial_symtab) <user, searched_flag>: New
+       fields.
+       (enum psymtab_search_status): New.
+
 2012-05-10  Tom Tromey  <tromey@redhat.com>
 
        * tracepoint.c (scope_info): Update.
index df7b874e07454035765c728072b452159fe7fa13..370ce86b3159ff83b7879e8fcb4cf0cadcf64e83 100644 (file)
@@ -54,6 +54,17 @@ struct partial_symbol
 #define PSYMBOL_DOMAIN(psymbol)        (psymbol)->domain
 #define PSYMBOL_CLASS(psymbol)         (psymbol)->aclass
 
+/* A convenience enum to give names to some constants used when
+   searching psymtabs.  This is internal to psymtab and should not be
+   used elsewhere.  */
+
+enum psymtab_search_status
+  {
+    PST_NOT_SEARCHED,
+    PST_SEARCHED_AND_FOUND,
+    PST_SEARCHED_AND_NOT_FOUND
+  };
+
 /* Each source file that has not been fully read in is represented by
    a partial_symtab.  This contains the information on where in the
    executable the debugging symbols for a specific file are, and a
@@ -111,6 +122,35 @@ struct partial_symtab
 
   int number_of_dependencies;
 
+  /* If NULL, this is an ordinary partial symbol table.
+
+     If non-NULL, this holds a single includer of this partial symbol
+     table, and this partial symbol table is a shared one.
+
+     A shared psymtab is one that is referenced by multiple other
+     psymtabs, and which conceptually has its contents directly
+     included in those.
+
+     Shared psymtabs have special semantics.  When a search finds a
+     symbol in a shared table, we instead return one of the non-shared
+     tables that include this one.
+
+     A shared psymtabs can be referred to by other shared ones.
+
+     The psymtabs that refer to a shared psymtab will list the shared
+     psymtab in their 'dependencies' array.
+
+     In DWARF terms, a shared psymtab is a DW_TAG_partial_unit; but
+     of course using a name based on that would be too confusing, so
+     "shared" was chosen instead.
+     
+     Only a single user is needed because, when expanding a shared
+     psymtab, we only need to expand its "canonical" non-shared user.
+     The choice of which one should be canonical is left to the
+     debuginfo reader; it can be arbitrary.  */
+
+  struct partial_symtab *user;
+
   /* Global symbol list.  This list will be sorted after readin to
      improve access.  Binary search will be the usual method of
      finding a symbol within it.  globals_offset is an integer offset
@@ -142,6 +182,10 @@ struct partial_symtab
 
   unsigned char psymtabs_addrmap_supported;
 
+  /* A flag that is temporarily used when searching psymtabs.  */
+
+  ENUM_BITFIELD (psymtab_search_status) searched_flag : 2;
+
   /* Pointer to symtab eventually allocated for this source file, 0 if
      !readin or if we haven't looked for the symtab after it was readin.  */
 
index 9620de8bd351f6e15fc874c0a987e6816f194f75..814023e894a8c7f602043c308d131a1639249490 100644 (file)
@@ -135,6 +135,10 @@ partial_map_expand_apply (struct objfile *objfile,
 {
   struct symtab *last_made = objfile->symtabs;
 
+  /* Shared psymtabs should never be seen here.  Instead they should
+     be handled properly by the caller.  */
+  gdb_assert (pst->user == NULL);
+
   /* Don't visit already-expanded psymtabs.  */
   if (pst->readin)
     return 0;
@@ -165,6 +169,11 @@ partial_map_symtabs_matching_filename (struct objfile *objfile,
 
   ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, pst)
   {
+    /* We can skip shared psymtabs here, because any file name will be
+       attached to the unshared psymtab.  */
+    if (pst->user != NULL)
+      continue;
+
     if (FILENAME_CMP (name, pst->filename) == 0
        || (!is_abs && compare_filenames_for_search (pst->filename,
                                                     name, name_len)))
@@ -760,6 +769,11 @@ lookup_partial_symbol (struct partial_symtab *pst, const char *name,
 static struct symtab *
 psymtab_to_symtab (struct partial_symtab *pst)
 {
+  /* If it is a shared psymtab, find an unshared psymtab that includes
+     it.  Any such psymtab will do.  */
+  while (pst->user != NULL)
+    pst = pst->user;
+
   /* If it's been looked up before, return it.  */
   if (pst->symtab)
     return pst->symtab;
@@ -1000,6 +1014,12 @@ dump_psymtab (struct objfile *objfile, struct partial_symtab *psymtab,
       fprintf_filtered (outfile, " %s\n",
                        psymtab->dependencies[i]->filename);
     }
+  if (psymtab->user != NULL)
+    {
+      fprintf_filtered (outfile, "  Shared partial symtab with user ");
+      gdb_print_host_address (psymtab->user, outfile);
+      fprintf_filtered (outfile, "\n");
+    }
   if (psymtab->n_global_syms > 0)
     {
       print_partial_symbols (gdbarch,
@@ -1236,6 +1256,94 @@ map_matching_symbols_psymtab (const char *name, domain_enum namespace,
     }
 }          
 
+/* A helper for expand_symtabs_matching_via_partial that handles
+   searching included psymtabs.  This returns 1 if a symbol is found,
+   and zero otherwise.  It also updates the 'searched_flag' on the
+   various psymtabs that it searches.  */
+
+static int
+recursively_search_psymtabs (struct partial_symtab *ps,
+                            struct objfile *objfile,
+                            enum search_domain kind,
+                            int (*name_matcher) (const char *, void *),
+                            void *data)
+{
+  struct partial_symbol **psym;
+  struct partial_symbol **bound, **gbound, **sbound;
+  int keep_going = 1;
+  int result = PST_SEARCHED_AND_NOT_FOUND;
+  int i;
+
+  if (ps->searched_flag != PST_NOT_SEARCHED)
+    return ps->searched_flag == PST_SEARCHED_AND_FOUND;
+
+  /* Recurse into shared psymtabs first, because they may have already
+     been searched, and this could save some time.  */
+  for (i = 0; i < ps->number_of_dependencies; ++i)
+    {
+      int r;
+
+      /* Skip non-shared dependencies, these are handled elsewhere.  */
+      if (ps->dependencies[i]->user == NULL)
+       continue;
+
+      r = recursively_search_psymtabs (ps->dependencies[i],
+                                      objfile, kind, name_matcher, data);
+      if (r != 0)
+       {
+         ps->searched_flag = PST_SEARCHED_AND_FOUND;
+         return 1;
+       }
+    }
+
+  gbound = (objfile->global_psymbols.list
+           + ps->globals_offset + ps->n_global_syms);
+  sbound = (objfile->static_psymbols.list
+           + ps->statics_offset + ps->n_static_syms);
+  bound = gbound;
+
+  /* Go through all of the symbols stored in a partial
+     symtab in one loop.  */
+  psym = objfile->global_psymbols.list + ps->globals_offset;
+  while (keep_going)
+    {
+      if (psym >= bound)
+       {
+         if (bound == gbound && ps->n_static_syms != 0)
+           {
+             psym = objfile->static_psymbols.list + ps->statics_offset;
+             bound = sbound;
+           }
+         else
+           keep_going = 0;
+         continue;
+       }
+      else
+       {
+         QUIT;
+
+         if ((kind == ALL_DOMAIN
+              || (kind == VARIABLES_DOMAIN
+                  && SYMBOL_CLASS (*psym) != LOC_TYPEDEF
+                  && SYMBOL_CLASS (*psym) != LOC_BLOCK)
+              || (kind == FUNCTIONS_DOMAIN
+                  && SYMBOL_CLASS (*psym) == LOC_BLOCK)
+              || (kind == TYPES_DOMAIN
+                  && SYMBOL_CLASS (*psym) == LOC_TYPEDEF))
+             && (*name_matcher) (SYMBOL_SEARCH_NAME (*psym), data))
+           {
+             /* Found a match, so notify our caller.  */
+             result = PST_SEARCHED_AND_FOUND;
+             keep_going = 0;
+           }
+       }
+      psym++;
+    }
+
+  ps->searched_flag = result;
+  return result == PST_SEARCHED_AND_FOUND;
+}
+
 static void
 expand_symtabs_matching_via_partial
   (struct objfile *objfile,
@@ -1246,60 +1354,27 @@ expand_symtabs_matching_via_partial
 {
   struct partial_symtab *ps;
 
+  /* Clear the search flags.  */
   ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps)
     {
-      struct partial_symbol **psym;
-      struct partial_symbol **bound, **gbound, **sbound;
-      int keep_going = 1;
+      ps->searched_flag = PST_NOT_SEARCHED;
+    }
 
+  ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps)
+    {
       if (ps->readin)
        continue;
 
-      if (file_matcher && ! (*file_matcher) (ps->filename, data))
+      /* We skip shared psymtabs because file-matching doesn't apply
+        to them; but we search them later in the loop.  */
+      if (ps->user != NULL)
        continue;
 
-      gbound = objfile->global_psymbols.list
-       + ps->globals_offset + ps->n_global_syms;
-      sbound = objfile->static_psymbols.list
-       + ps->statics_offset + ps->n_static_syms;
-      bound = gbound;
+      if (file_matcher && ! (*file_matcher) (ps->filename, data))
+       continue;
 
-      /* Go through all of the symbols stored in a partial
-        symtab in one loop.  */
-      psym = objfile->global_psymbols.list + ps->globals_offset;
-      while (keep_going)
-       {
-         if (psym >= bound)
-           {
-             if (bound == gbound && ps->n_static_syms != 0)
-               {
-                 psym = objfile->static_psymbols.list + ps->statics_offset;
-                 bound = sbound;
-               }
-             else
-               keep_going = 0;
-             continue;
-           }
-         else
-           {
-             QUIT;
-
-             if ((kind == ALL_DOMAIN
-                  || (kind == VARIABLES_DOMAIN
-                      && SYMBOL_CLASS (*psym) != LOC_TYPEDEF
-                      && SYMBOL_CLASS (*psym) != LOC_BLOCK)
-                  || (kind == FUNCTIONS_DOMAIN
-                      && SYMBOL_CLASS (*psym) == LOC_BLOCK)
-                  || (kind == TYPES_DOMAIN
-                      && SYMBOL_CLASS (*psym) == LOC_TYPEDEF))
-                 && (*name_matcher) (SYMBOL_SEARCH_NAME (*psym), data))
-               {
-                 psymtab_to_symtab (ps);
-                 keep_going = 0;
-               }
-           }
-         psym++;
-       }
+      if (recursively_search_psymtabs (ps, objfile, kind, name_matcher, data))
+       psymtab_to_symtab (ps);
     }
 }