Share DWARF partial symtabs

This changes the DWARF reader to share partial symtabs (or indices if
they are available) across objfiles.  This has a few parts.

* If multiple objfiles backed by the same BFD can share partial symtabs
  (see below), a single dwarf2_per_bfd is created.  It is stored in the
  per-bfd `dwarf2_per_bfd_bfd_data_key` registry.  Multiple
  dwarf2_per_objfile objects will point to the same instance.  The
  lifetime of these dwarf2_per_bfd objects is naturally handled.  When
  all the objfiles using the BFD are destroyed, the BFD's refount drops
  to 0, which triggers the removal of the corresponding dwarf2_per_bfd
  object from the registry and its destruction.

* If multiple objfiles backed by the same BFD can't share partial
  symtabs (see below), one dwarf2_per_bfd object is created for each
  objfile.  Each dwarf2_per_objfile will point to their own instance of
  dwarf2_per_bfd.  These instances of dwarf2_per_bfd are kept in a
  per-objfile registry, meaning that when the objfile gets destroyed,
  the dwarf2_per_bfd instance gets destroyed as well.

* objfile::partial_symtabs is changed to be a shared_ptr again.  This
  lets us stash a second reference in dwarf2_per_bfd; if the DWARF
  data is being shared, we can simply copy this value to the new
  objfile.

* Two dwarf2_per_objfile objects backed by the same BFD may share a
  dwarf2_per_bfd instance if:

  * No other symbol reader has found symbols, and
  * No BFD section rqeuires relocation

gdb/ChangeLog:

YYYY-MM-DD  Tom Tromey  <tom@tromey.com>
YYYY-MM-DD  Simon Marchi  <simon.marchi@efficios.com>

	* objfiles.h (struct objfile) <partial_symtabs>: Now a
	shared_ptr.
	* dwarf2/read.h (struct dwarf2_per_objfile) <partial_symtabs>: New
	member.
	* dwarf2/read.c (dwarf2_per_bfd_bfd_data_key,
	dwarf2_per_bfd_objfile_data_key>: New globals.
	(dwarf2_has_info): Use shared dwarf2_per_bfd if possible.
	(dwarf2_get_section_info): Use get_dwarf2_per_objfile.
	(dwarf2_initialize_objfile): Consider cases where per_bfd can be
	shared.
	(dwarf2_build_psymtabs): Set objfile::partial_symtabs and
	short-circuit when sharing.
	(dwarf2_build_psymtabs): Set dwarf2_per_objfile::partial_symtabs.
	(dwarf2_psymtab::expand_psymtab): Use free_cached_comp_units.

Change-Id: I868c64448589102ab8cbb8f06c31a8de50a14004
This commit is contained in:
Tom Tromey 2020-05-27 11:20:14 -04:00 committed by Simon Marchi
parent 39b16f87f7
commit 17ee85fc2a
4 changed files with 115 additions and 15 deletions

View File

@ -1,3 +1,21 @@
2020-05-27 Tom Tromey <tom@tromey.com>
Simon Marchi <simon.marchi@efficios.com>
* objfiles.h (struct objfile) <partial_symtabs>: Now a
shared_ptr.
* dwarf2/read.h (struct dwarf2_per_objfile) <partial_symtabs>: New
member.
* dwarf2/read.c (dwarf2_per_bfd_bfd_data_key,
dwarf2_per_bfd_objfile_data_key>: New globals.
(dwarf2_has_info): Use shared dwarf2_per_bfd if possible.
(dwarf2_get_section_info): Use get_dwarf2_per_objfile.
(dwarf2_initialize_objfile): Consider cases where per_bfd can be
shared.
(dwarf2_build_psymtabs): Set objfile::partial_symtabs and
short-circuit when sharing.
(dwarf2_build_psymtabs): Set dwarf2_per_objfile::partial_symtabs.
(dwarf2_psymtab::expand_psymtab): Use free_cached_comp_units.
2020-05-27 Simon Marchi <simon.marchi@efficios.com>
* dwarf2/read.h (struct dwarf2_per_bfd) <line_header_hash>: Move

View File

@ -105,7 +105,19 @@ static bool check_physname = false;
/* When true, do not reject deprecated .gdb_index sections. */
static bool use_deprecated_index_sections = false;
static const struct objfile_key<dwarf2_per_objfile> dwarf2_objfile_data_key;
/* This is used to store the data that is always per objfile. */
static const objfile_key<dwarf2_per_objfile> dwarf2_objfile_data_key;
/* These are used to store the dwarf2_per_bfd objects.
objfiles having the same BFD, which doesn't require relocations, are going to
share a dwarf2_per_bfd object, which is held in the _bfd_data_key version.
Other objfiles are not going to share a dwarf2_per_bfd with any other
objfiles, so they'll have their own version kept in the _objfile_data_key
version. */
static const struct bfd_key<dwarf2_per_bfd> dwarf2_per_bfd_bfd_data_key;
static const struct objfile_key<dwarf2_per_bfd> dwarf2_per_bfd_objfile_data_key;
/* The "aclass" indices for various kinds of computed DWARF symbols. */
@ -1853,9 +1865,30 @@ dwarf2_has_info (struct objfile *objfile,
if (dwarf2_per_objfile == NULL)
{
/* For now, each dwarf2_per_objfile owns its own dwarf2_per_bfd (no
sharing yet). */
dwarf2_per_bfd *per_bfd = new dwarf2_per_bfd (objfile->obfd, names, can_copy);
dwarf2_per_bfd *per_bfd;
/* We can share a "dwarf2_per_bfd" with other objfiles if the BFD
doesn't require relocations and if there aren't partial symbols
from some other reader. */
if (!objfile_has_partial_symbols (objfile)
&& !gdb_bfd_requires_relocations (objfile->obfd))
{
/* See if one has been created for this BFD yet. */
per_bfd = dwarf2_per_bfd_bfd_data_key.get (objfile->obfd);
if (per_bfd == nullptr)
{
/* No, create it now. */
per_bfd = new dwarf2_per_bfd (objfile->obfd, names, can_copy);
dwarf2_per_bfd_bfd_data_key.set (objfile->obfd, per_bfd);
}
}
else
{
/* No sharing possible, create one specifically for this objfile. */
per_bfd = new dwarf2_per_bfd (objfile->obfd, names, can_copy);
dwarf2_per_bfd_objfile_data_key.set (objfile, per_bfd);
}
dwarf2_per_objfile = dwarf2_objfile_data_key.emplace (objfile, objfile, per_bfd);
}
@ -2017,7 +2050,7 @@ dwarf2_get_section_info (struct objfile *objfile,
asection **sectp, const gdb_byte **bufp,
bfd_size_type *sizep)
{
struct dwarf2_per_objfile *data = dwarf2_objfile_data_key.get (objfile);
struct dwarf2_per_objfile *data = get_dwarf2_per_objfile (objfile);
struct dwarf2_section_info *info;
/* We may see an objfile without any DWARF, in which case we just
@ -5913,6 +5946,7 @@ dwarf2_initialize_objfile (struct objfile *objfile, dw_index_kind *index_kind)
{
struct dwarf2_per_objfile *dwarf2_per_objfile
= get_dwarf2_per_objfile (objfile);
dwarf2_per_bfd *per_bfd = dwarf2_per_objfile->per_bfd;
/* If we're about to read full symbols, don't bother with the
indices. In this case we also don't care if some other debug
@ -5920,20 +5954,28 @@ dwarf2_initialize_objfile (struct objfile *objfile, dw_index_kind *index_kind)
expanded anyway. */
if ((objfile->flags & OBJF_READNOW))
{
dwarf2_per_objfile->per_bfd->using_index = 1;
/* When using READNOW, the using_index flag (set below) indicates that
PER_BFD was already initialized, when we loaded some other objfile. */
if (per_bfd->using_index)
{
*index_kind = dw_index_kind::GDB_INDEX;
dwarf2_per_objfile->resize_symtabs ();
return true;
}
per_bfd->using_index = 1;
create_all_comp_units (dwarf2_per_objfile);
create_all_type_units (dwarf2_per_objfile);
dwarf2_per_objfile->per_bfd->quick_file_names_table
= create_quick_file_names_table
(dwarf2_per_objfile->per_bfd->all_comp_units.size ());
per_bfd->quick_file_names_table
= create_quick_file_names_table (per_bfd->all_comp_units.size ());
dwarf2_per_objfile->resize_symtabs ();
for (int i = 0; i < (dwarf2_per_objfile->per_bfd->all_comp_units.size ()
+ dwarf2_per_objfile->per_bfd->all_type_units.size ()); ++i)
for (int i = 0; i < (per_bfd->all_comp_units.size ()
+ per_bfd->all_type_units.size ()); ++i)
{
dwarf2_per_cu_data *per_cu = dwarf2_per_objfile->per_bfd->get_cutu (i);
dwarf2_per_cu_data *per_cu = per_bfd->get_cutu (i);
per_cu->v.quick = OBSTACK_ZALLOC (&dwarf2_per_objfile->per_bfd->obstack,
per_cu->v.quick = OBSTACK_ZALLOC (&per_bfd->obstack,
struct dwarf2_per_cu_quick_data);
}
@ -5944,6 +5986,24 @@ dwarf2_initialize_objfile (struct objfile *objfile, dw_index_kind *index_kind)
return true;
}
/* Was a debug names index already read when we processed an objfile sharing
PER_BFD? */
if (per_bfd->debug_names_table != nullptr)
{
*index_kind = dw_index_kind::DEBUG_NAMES;
dwarf2_per_objfile->resize_symtabs ();
return true;
}
/* Was a GDB index already read when we processed an objfile sharing
PER_BFD? */
if (per_bfd->index_table != nullptr)
{
*index_kind = dw_index_kind::GDB_INDEX;
dwarf2_per_objfile->resize_symtabs ();
return true;
}
if (dwarf2_read_debug_names (dwarf2_per_objfile))
{
*index_kind = dw_index_kind::DEBUG_NAMES;
@ -5984,6 +6044,16 @@ dwarf2_build_psymtabs (struct objfile *objfile)
{
struct dwarf2_per_objfile *dwarf2_per_objfile
= get_dwarf2_per_objfile (objfile);
dwarf2_per_bfd *per_bfd = dwarf2_per_objfile->per_bfd;
if (per_bfd->partial_symtabs != nullptr)
{
/* Partial symbols were already read, so now we can simply
attach them. */
objfile->partial_symtabs = per_bfd->partial_symtabs;
dwarf2_per_objfile->resize_symtabs ();
return;
}
init_psymbol_list (objfile, 1024);
@ -6005,6 +6075,12 @@ dwarf2_build_psymtabs (struct objfile *objfile)
{
exception_print (gdb_stderr, except);
}
/* Finish by setting the local reference to partial symtabs, so that
we don't try to read them again if reading another objfile with the same
BFD. If we can't in fact share, this won't make a difference anyway as
the dwarf2_per_bfd object won't be shared. */
per_bfd->partial_symtabs = objfile->partial_symtabs;
}
/* Find the base address of the compilation unit for range lists and
@ -9053,9 +9129,10 @@ dwarf2_psymtab::expand_psymtab (struct objfile *objfile)
{
gdb_assert (!readin_p (objfile));
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
free_cached_comp_units freer (per_objfile);
expand_dependencies (objfile);
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
dw2_do_instantiate_symtab (per_cu_data, per_objfile, false);
gdb_assert (get_compunit_symtab (objfile) != nullptr);
}

View File

@ -251,6 +251,11 @@ public:
/* CUs that are queued to be read. */
std::queue<dwarf2_queue_item> queue;
/* We keep a separate reference to the partial symtabs, in case we
are sharing them between objfiles. This is only set after
partial symbols have been read the first time. */
std::shared_ptr<psymtab_storage> partial_symtabs;
private:
/* The total number of per_cu and signatured_type objects that have

View File

@ -576,7 +576,7 @@ public:
/* The partial symbol tables. */
std::unique_ptr<psymtab_storage> partial_symtabs;
std::shared_ptr<psymtab_storage> partial_symtabs;
/* The object file's BFD. Can be null if the objfile contains only
minimal symbols, e.g. the run time common symbols for SunOS4. */