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]

Re: [7/10] keep track of dependencies


On Wed, 25 Apr 2012 20:54:11 +0200, Tom Tromey wrote:
> @@ -445,6 +451,9 @@ struct dwarf2_per_cu_data
>      /* Data needed by the "quick" functions.  */
>      struct dwarf2_per_cu_quick_data *quick;
>    } v;
> +
> +  /* The CUs we import using DW_TAG_imported_unit.  */

Maybe to describe also its lifetime / usage.

/* Once it is filled in by scan_partial_symbols and freed by
   process_psymtab_comp_unit to compute partial_symtab->dependencies, if
   psymtabs are in use.  It is also filled in by process_die and freed by
   compute_symtab_includes to compute symtab->includes.  */


> +  VEC (dwarf2_per_cu_ptr) *imported_symtabs;
>  };
>  
>  /* Entry in the signatured_types hash table.  */
[...]
> +/* Add a user to the list of psymtab users of INCLUDED.  */
> +
> +static void
> +add_partial_user (htab_t user_hash,
> +		  struct partial_symtab *included,
> +		  struct partial_symtab *using_psymtab)
> +{
> +  void **slot;
> +  struct partial_users *user, tem;

I think the variable name 'user' is confusing here - being exactly the
opposite.  USER (matching INCLUDED) is being used by USING_PSYMTAB here.
I hope I did not mess the wording.


> +
> +  tem.pst = included;
> +  slot = htab_find_slot (user_hash, &tem, INSERT);
> +  if (*slot == NULL)
> +    {
> +      user = XNEW (struct partial_users);
> +      user->pst = included;
> +      user->users = NULL;
> +      *slot = user;
> +    }
> +  else
> +    user = *slot;
> +  VEC_safe_push (partial_symtab_p, user->users, using_psymtab);
> +}
> +
> +/* Compute the 'users' field for each psymtab in OBJFILE.  */
> +
> +static void
> +set_partial_users (struct objfile *objfile)
> +{
> +  htab_t user_hash;
> +  int i;
> +
> +  user_hash = htab_create_alloc (1, hash_partial_users, eq_partial_users,
> +				 del_partial_users, xcalloc, xfree);
> +
> +  for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
> +    {
> +      struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
> +      struct partial_symtab *pst = per_cu->v.psymtab;
> +      int j;
> +
> +      for (j = 0; j < pst->number_of_dependencies; ++j)
> +	add_partial_user (user_hash, pst->dependencies[j], pst);
> +    }
> +
> +  for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
> +    {
> +      struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
> +      struct partial_symtab *pst = per_cu->v.psymtab;
> +      struct partial_users *user, tem;
> +
> +      tem.pst = pst;
> +      user = htab_find (user_hash, &tem);
> +      if (user != NULL)
> +	{
> +	  int len = VEC_length (partial_symtab_p, user->users);
> +
> +	  gdb_assert (len > 0);
> +	  pst->users = obstack_alloc (&objfile->objfile_obstack,
> +				      (len + 1)
> +				      * sizeof (struct partial_symtab *));

I think here should be one more parentheses according to GCS.


> +	  memcpy (pst->users,
> +		  VEC_address (partial_symtab_p, user->users),
> +		  len * sizeof (struct partial_symtab *));
> +	  pst->users[len] = NULL;
> +	}
> +    }
> +
> +  htab_delete (user_hash);
> +}
> +
>  /* Build the partial symbol table by doing a quick pass through the
>     .debug_info and .debug_abbrev sections.  */
>  
[...]
> +/* A helper function for computing the list of all symbol tables
> +   included by PER_CU.  */
> +
> +static void
> +recursively_compute_inclusions (VEC (dwarf2_per_cu_ptr) **result,
> +				htab_t all_children,
> +				struct dwarf2_per_cu_data *per_cu)
> +{
> +  void **slot;
> +  int ix;
> +  struct dwarf2_per_cu_data *iter;
> +
> +  slot = htab_find_slot (all_children, per_cu, INSERT);
> +  if (*slot != NULL)
> +    {
> +      /* This inclusion and its children have been processed.  */
> +      return;
> +    }
> +
> +  *slot = per_cu;
> +  /* Only add a CU if it has a symbol table.  */
> +  if (get_symtab (per_cu) != NULL)
> +    VEC_safe_push (dwarf2_per_cu_ptr, *result, per_cu);
> +
> +  for (ix = 0;
> +       VEC_iterate (dwarf2_per_cu_ptr, per_cu->imported_symtabs, ix, iter);
> +       ++ix)
> +    recursively_compute_inclusions (result, all_children, iter);
> +}
> +
> +/* Compute the symtab 'includes' fields for the symtab related to
> +   PER_CU.  */
> +
> +static void
> +compute_symtab_includes (struct dwarf2_per_cu_data *per_cu)
> +{
> +  if (!VEC_empty (dwarf2_per_cu_ptr, per_cu->imported_symtabs))
> +    {
> +      int ix, len;
> +      struct dwarf2_per_cu_data *iter;
> +      VEC (dwarf2_per_cu_ptr) *result_children = NULL;
> +      htab_t all_children;
> +      struct symtab *symtab = get_symtab (per_cu);
> +
> +      /* If we don't have a symtab, we can just skip this case.  */
> +      if (symtab == NULL)
> +	return;
> +
> +      all_children = htab_create_alloc (1, htab_hash_pointer, htab_eq_pointer,
> +					NULL, xcalloc, xfree);
> +
> +      for (ix = 0;
> +	   VEC_iterate (dwarf2_per_cu_ptr, per_cu->imported_symtabs,
> +			ix, iter);
> +	   ++ix)
> +	recursively_compute_inclusions (&result_children, all_children, iter);
> +
> +      /* Now we have a transitive closure of all the included CUs, so
> +	 we can convert it to a list of symtabs.  */
> +      len = VEC_length (dwarf2_per_cu_ptr, result_children);
> +      symtab->includes
> +	= obstack_alloc (&dwarf2_per_objfile->objfile->objfile_obstack,
> +			 (len + 1) * sizeof (struct symtab *));
> +      for (ix = 0;
> +	   VEC_iterate (dwarf2_per_cu_ptr, result_children, ix, iter);
> +	   ++ix)

Why is RESULT_CHILDREN used here at all?  Would not it be sufficient to just
call htab_traverse for ALL_CHILDREN?


> +	symtab->includes[ix] = get_symtab (iter);
> +      symtab->includes[len] = NULL;
> +
> +      VEC_free (dwarf2_per_cu_ptr, result_children);
> +      htab_delete (all_children);
> +    }
> +}
[...]
> @@ -5005,6 +5276,31 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
>  		   dwarf_tag_name (die->tag));
>        read_import_statement (die, cu);
>        break;
> +
> +    case DW_TAG_imported_unit:

process_die only calls functions in general, it would be nice to put this
block into a new function.


> +      {
> +	struct attribute *attr;
> +
> +	attr = dwarf2_attr (die, DW_AT_import, cu);
> +	if (attr != NULL)
> +	  {
> +	    struct dwarf2_per_cu_data *per_cu;
> +	    struct symtab *imported_symtab;
> +	    sect_offset offset;
> +
> +	    offset = dwarf2_get_ref_die_offset (attr);
> +	    per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile);
> +
> +	    /* Queue the unit, if needed.  */
> +	    if (maybe_queue_comp_unit (cu, per_cu))
> +	      load_full_comp_unit (per_cu);
> +
> +	    VEC_safe_push (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs,
> +			   per_cu);
> +	  }
> +      }
> +      break;
> +
>      default:
>        new_symbol (die, NULL, cu);
>        break;

Thanks,
Jan


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