[RFA] Remove pre_expand_symtabs_matching quick_symbol_functions API

Doug Evans dje@google.com
Fri Dec 21 16:51:00 GMT 2012


Hi.

The .gdb_index generated by gold doesn't do the optimization that
gdb does, namely collapsing common entries into one.

One can add this optimization to gold, but OTOH I couldn't think
of a reason not to apply this patch given that it simplifies the
quick_symbol_functions API.

For one program here with ~2000 .o files, the space used by gdb
to print a local variable goes from 1.4G to 24M.
This is because the variable is of type "int *", and without this
patch gdb pre-expands every symtab that defines "int" before it
goes to look up the definition of "int".

Regression tested on amd64-linux, but I wouldn't be surprised
if I'm missing something ...

[I'm setting aside long term desires to make more radical changes
to gdb's symbol handling, the patch fixes a real problem I'm facing now.]

Ok to check in?
[Or am I missing something ...]

The patch is in context-diff format because in this particular case
I think it's more readable.

2012-12-21  Doug Evans  <dje@google.com>

	* symfile.h (quick_symbol_functions): Delete member
	pre_expand_symtabs_matching.  All uses removed.
	* dwarf2read.c (dw2_lookup_symbol): Implement.
	(dw2_do_expand_symtabs_matching): Delete.
	(dw2_pre_expand_symtabs_matching): Delete.
	(struct dw2_symtab_iterator): New type.
	(dw2_symtab_iter_init, dw2_symtab_iter_next): New functions.
	(dw2_expand_symtabs_for_function): Rewrite.
	(dwarf2_gdb_index_functions): Update.
	* psymtab.c (pre_expand_symtabs_matching_psymtabs): Delete.
	(psym_functions): Update.

Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.724
diff -c -p -r1.724 dwarf2read.c
*** dwarf2read.c	16 Dec 2012 18:57:16 -0000	1.724
--- dwarf2read.c	21 Dec 2012 09:11:10 -0000
*************** dw2_map_symtabs_matching_filename (struc
*** 3149,3247 ****
    return 0;
  }
  
! static struct symtab *
! dw2_lookup_symbol (struct objfile *objfile, int block_index,
! 		   const char *name, domain_enum domain)
  {
!   /* We do all the work in the pre_expand_symtabs_matching hook
!      instead.  */
!   return NULL;
! }
  
! /* A helper function that expands all symtabs that hold an object
!    named NAME.  If WANT_SPECIFIC_BLOCK is non-zero, only look for
!    symbols in block BLOCK_KIND.  */
  
  static void
! dw2_do_expand_symtabs_matching (struct objfile *objfile,
! 				int want_specific_block,
! 				enum block_enum block_kind,
! 				const char *name, domain_enum domain)
  {
    struct mapped_index *index;
  
    dw2_setup (objfile);
  
    index = dwarf2_per_objfile->index_table;
  
!   /* index_table is NULL if OBJF_READNOW.  */
    if (index)
      {
!       offset_type *vec;
  
!       if (find_slot_in_mapped_hash (index, name, &vec))
  	{
! 	  offset_type i, len = MAYBE_SWAP (*vec);
! 	  for (i = 0; i < len; ++i)
  	    {
! 	      offset_type cu_index_and_attrs = MAYBE_SWAP (vec[i + 1]);
! 	      offset_type cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs);
! 	      struct dwarf2_per_cu_data *per_cu = dw2_get_cu (cu_index);
! 	      int want_static = block_kind != GLOBAL_BLOCK;
! 	      /* This value is only valid for index versions >= 7.  */
! 	      int is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs);
! 	      gdb_index_symbol_kind symbol_kind =
! 		GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs);
! 	      /* Only check the symbol attributes if they're present.
! 		 Indices prior to version 7 don't record them,
! 		 and indices >= 7 may elide them for certain symbols
! 		 (gold does this).  */
! 	      int attrs_valid =
! 		(index->version >= 7
! 		 && symbol_kind != GDB_INDEX_SYMBOL_KIND_NONE);
! 
! 	      if (attrs_valid
! 		  && want_specific_block
! 		  && want_static != is_static)
! 		continue;
  
! 	      /* Only check the symbol's kind if it has one.  */
! 	      if (attrs_valid)
! 		{
! 		  switch (domain)
! 		    {
! 		    case VAR_DOMAIN:
! 		      if (symbol_kind != GDB_INDEX_SYMBOL_KIND_VARIABLE
! 			  && symbol_kind != GDB_INDEX_SYMBOL_KIND_FUNCTION
! 			  /* Some types are also in VAR_DOMAIN.  */
! 			  && symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
! 			continue;
! 		      break;
! 		    case STRUCT_DOMAIN:
! 		      if (symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
! 			continue;
! 		      break;
! 		    case LABEL_DOMAIN:
! 		      if (symbol_kind != GDB_INDEX_SYMBOL_KIND_OTHER)
! 			continue;
! 		      break;
! 		    default:
! 		      break;
! 		    }
! 		}
  
! 	      dw2_instantiate_symtab (per_cu);
  	    }
  	}
      }
- }
  
! static void
! dw2_pre_expand_symtabs_matching (struct objfile *objfile,
! 				 enum block_enum block_kind, const char *name,
! 				 domain_enum domain)
! {
!   dw2_do_expand_symtabs_matching (objfile, 1, block_kind, name, domain);
  }
  
  static void
--- 3149,3304 ----
    return 0;
  }
  
! /* Struct used to manage iterating over all CUs looking for a symbol.  */
! 
! struct dw2_symtab_iterator
  {
!   struct mapped_index *index;
!   int want_specific_block;
!   int block_index;
!   domain_enum domain;
!   offset_type *vec;
!   int next;
!   int length;
! };
  
! /* Initialize the index symtab iterator IT.
!    If WANT_SPECIFIC_BLOCK is non-zero, only look for symbols
!    in block BLOCK_KIND.  */
  
  static void
! dw2_symtab_iter_init (struct dw2_symtab_iterator *iter,
! 			struct mapped_index *index,
! 			int want_specific_block,
! 			int block_index,
! 			domain_enum domain,
! 			const char *name)
! {
!   iter->index = index;
!   iter->want_specific_block = want_specific_block;
!   iter->block_index = block_index;
!   iter->domain = domain;
!   iter->next = 0;
! 
!   if (find_slot_in_mapped_hash (index, name, &iter->vec))
!     iter->length = MAYBE_SWAP (*iter->vec);
!   else
!     iter->length = 0;
! }
! 
! /* Return the next matching CU or NULL if there are no more.  */
! 
! static struct dwarf2_per_cu_data *
! dw2_symtab_iter_next (struct dw2_symtab_iterator *iter)
! {
!   for ( ; iter->next < iter->length; ++iter->next)
!     {
!       offset_type cu_index_and_attrs =
! 	MAYBE_SWAP (iter->vec[iter->next + 1]);
!       offset_type cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs);
!       struct dwarf2_per_cu_data *per_cu = dw2_get_cu (cu_index);
!       int want_static = iter->block_index != GLOBAL_BLOCK;
!       /* This value is only valid for index versions >= 7.  */
!       int is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs);
!       gdb_index_symbol_kind symbol_kind =
! 	GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs);
!       /* Only check the symbol attributes if they're present.
! 	 Indices prior to version 7 don't record them,
! 	 and indices >= 7 may elide them for certain symbols
! 	 (gold does this).  */
!       int attrs_valid =
! 	(iter->index->version >= 7
! 	 && symbol_kind != GDB_INDEX_SYMBOL_KIND_NONE);
! 
!       /* Skip if already read in.  */
!       if (per_cu->v.quick->symtab)
! 	continue;
! 
!       if (attrs_valid
! 	  && iter->want_specific_block
! 	  && want_static != is_static)
! 	continue;
! 
!       /* Only check the symbol's kind if it has one.  */
!       if (attrs_valid)
! 	{
! 	  switch (iter->domain)
! 	    {
! 	    case VAR_DOMAIN:
! 	      if (symbol_kind != GDB_INDEX_SYMBOL_KIND_VARIABLE
! 		  && symbol_kind != GDB_INDEX_SYMBOL_KIND_FUNCTION
! 		  /* Some types are also in VAR_DOMAIN.  */
! 		  && symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
! 		continue;
! 	      break;
! 	    case STRUCT_DOMAIN:
! 	      if (symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
! 		continue;
! 	      break;
! 	    case LABEL_DOMAIN:
! 	      if (symbol_kind != GDB_INDEX_SYMBOL_KIND_OTHER)
! 		continue;
! 	      break;
! 	    default:
! 	      break;
! 	    }
! 	}
! 
!       ++iter->next;
!       return per_cu;
!     }
! 
!   return NULL;
! }
! 
! static struct symtab *
! dw2_lookup_symbol (struct objfile *objfile, int block_index,
! 		   const char *name, domain_enum domain)
  {
+   struct symtab *stab_best = NULL;
    struct mapped_index *index;
  
    dw2_setup (objfile);
  
    index = dwarf2_per_objfile->index_table;
  
!   /* index is NULL if OBJF_READNOW.  */
    if (index)
      {
!       struct dw2_symtab_iterator iter;
!       struct dwarf2_per_cu_data *per_cu;
  
!       dw2_symtab_iter_init (&iter, index, 1, block_index, domain, name);
! 
!       while ((per_cu = dw2_symtab_iter_next (&iter)) != NULL)
  	{
! 	  struct symbol *sym = NULL;
! 	  struct symtab *stab = dw2_instantiate_symtab (per_cu);
! 
! 	  /* Some caution must be observed with overloaded functions
! 	     and methods, since the index will not contain any overload
! 	     information (but NAME might contain it).  */
! 	  if (stab->primary)
  	    {
! 	      struct blockvector *bv = BLOCKVECTOR (stab);
! 	      struct block *block = BLOCKVECTOR_BLOCK (bv, block_index);
  
! 	      sym = lookup_block_symbol (block, name, domain);
! 	    }
  
! 	  if (sym && strcmp_iw (SYMBOL_SEARCH_NAME (sym), name) == 0)
! 	    {
! 	      if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
! 		return stab;
! 
! 	      stab_best = stab;
  	    }
+ 
+ 	  /* Keep looking through other CUs.  */
  	}
      }
  
!   return stab_best;
  }
  
  static void
*************** static void
*** 3279,3287 ****
  dw2_expand_symtabs_for_function (struct objfile *objfile,
  				 const char *func_name)
  {
!   /* Note: It doesn't matter what we pass for block_kind here.  */
!   dw2_do_expand_symtabs_matching (objfile, 0, GLOBAL_BLOCK, func_name,
! 				  VAR_DOMAIN);
  }
  
  static void
--- 3336,3360 ----
  dw2_expand_symtabs_for_function (struct objfile *objfile,
  				 const char *func_name)
  {
!   struct mapped_index *index;
! 
!   dw2_setup (objfile);
! 
!   index = dwarf2_per_objfile->index_table;
! 
!   /* index is NULL if OBJF_READNOW.  */
!   if (index)
!     {
!       struct dw2_symtab_iterator iter;
!       struct dwarf2_per_cu_data *per_cu;
! 
!       /* Note: It doesn't matter what we pass for block_index here.  */
!       dw2_symtab_iter_init (&iter, index, 0, GLOBAL_BLOCK, VAR_DOMAIN,
! 			      func_name);
! 
!       while ((per_cu = dw2_symtab_iter_next (&iter)) != NULL)
! 	dw2_instantiate_symtab (per_cu);
!     }
  }
  
  static void
*************** const struct quick_symbol_functions dwar
*** 3697,3703 ****
    dw2_forget_cached_source_info,
    dw2_map_symtabs_matching_filename,
    dw2_lookup_symbol,
-   dw2_pre_expand_symtabs_matching,
    dw2_print_stats,
    dw2_dump,
    dw2_relocate,
--- 3770,3775 ----
Index: psymtab.c
===================================================================
RCS file: /cvs/src/src/gdb/psymtab.c,v
retrieving revision 1.54
diff -c -p -r1.54 psymtab.c
*** psymtab.c	16 Dec 2012 18:57:16 -0000	1.54
--- psymtab.c	21 Dec 2012 09:11:10 -0000
*************** match_partial_symbol (struct objfile *ob
*** 633,647 ****
    return NULL;
  }
  
- static void
- pre_expand_symtabs_matching_psymtabs (struct objfile *objfile,
- 				      enum block_enum block_kind,
- 				      const char *name,
- 				      domain_enum domain)
- {
-   /* Nothing.  */
- }
- 
  /* Returns the name used to search psymtabs.  Unlike symtabs, psymtabs do
     not contain any method/function instance information (since this would
     force reading type information while reading psymtabs).  Therefore,
--- 633,638 ----
*************** const struct quick_symbol_functions psym
*** 1433,1439 ****
    forget_cached_source_info_partial,
    partial_map_symtabs_matching_filename,
    lookup_symbol_aux_psymtabs,
-   pre_expand_symtabs_matching_psymtabs,
    print_psymtab_stats_for_objfile,
    dump_psymtabs_for_objfile,
    relocate_psymtabs,
--- 1424,1429 ----
Index: symfile.h
===================================================================
RCS file: /cvs/src/src/gdb/symfile.h,v
retrieving revision 1.114
diff -c -p -r1.114 symfile.h
*** symfile.h	26 Nov 2012 19:23:52 -0000	1.114
--- symfile.h	21 Dec 2012 09:11:10 -0000
*************** struct quick_symbol_functions
*** 189,204 ****
  				   int kind, const char *name,
  				   domain_enum domain);
  
-   /* This is called to expand symbol tables before looking up a
-      symbol.  A backend can choose to implement this and then have its
-      `lookup_symbol' hook always return NULL, or the reverse.  (It
-      doesn't make sense to implement both.)  The arguments are as for
-      `lookup_symbol'.  */
-   void (*pre_expand_symtabs_matching) (struct objfile *objfile,
- 				       enum block_enum block_kind,
- 				       const char *name,
- 				       domain_enum domain);
- 
    /* Print statistics about any indices loaded for OBJFILE.  The
       statistics should be printed to gdb_stdout.  This is used for
       "maint print statistics".  */
--- 189,194 ----
Index: symtab.c
===================================================================
RCS file: /cvs/src/src/gdb/symtab.c,v
retrieving revision 1.332
diff -c -p -r1.332 symtab.c
*** symtab.c	18 Dec 2012 19:26:28 -0000	1.332
--- symtab.c	21 Dec 2012 09:11:10 -0000
*************** lookup_symbol_aux_objfile (struct objfil
*** 1555,1564 ****
    const struct block *block;
    struct symtab *s;
  
-   if (objfile->sf)
-     objfile->sf->qf->pre_expand_symtabs_matching (objfile, block_index,
- 						  name, domain);
- 
    ALL_OBJFILE_PRIMARY_SYMTABS (objfile, s)
      {
        bv = BLOCKVECTOR (s);
--- 1555,1560 ----
*************** basic_lookup_transparent_type (const cha
*** 1916,1926 ****
  
    ALL_OBJFILES (objfile)
    {
-     if (objfile->sf)
-       objfile->sf->qf->pre_expand_symtabs_matching (objfile,
- 						    GLOBAL_BLOCK,
- 						    name, STRUCT_DOMAIN);
- 
      ALL_OBJFILE_PRIMARY_SYMTABS (objfile, s)
        {
  	bv = BLOCKVECTOR (s);
--- 1912,1917 ----
*************** basic_lookup_transparent_type (const cha
*** 1949,1958 ****
  
    ALL_OBJFILES (objfile)
    {
-     if (objfile->sf)
-       objfile->sf->qf->pre_expand_symtabs_matching (objfile, STATIC_BLOCK,
- 						    name, STRUCT_DOMAIN);
- 
      ALL_OBJFILE_PRIMARY_SYMTABS (objfile, s)
        {
  	bv = BLOCKVECTOR (s);
--- 1940,1945 ----



More information about the Gdb-patches mailing list