distinguish these in buildsym.c. */
struct pending **list_in_scope;
- /* The abbrev table for this CU.
- Normally this points to the abbrev table in the objfile.
- But if DWO_UNIT is non-NULL this is the abbrev table in the DWO file. */
- struct abbrev_table *abbrev_table;
-
/* Hash table holding all the loaded partial DIEs
with partial_die->offset.SECT_OFF as hash. */
htab_t partial_dies;
/* The value of the DW_AT_comp_dir attribute. */
const char *comp_dir;
+
+ /* The abbreviation table to use when reading the DIEs. */
+ struct abbrev_table *abbrev_table;
};
/* Type of function passed to init_cutu_and_read_dies, et.al. */
struct abbrev_table
{
+ explicit abbrev_table (sect_offset off)
+ : sect_off (off)
+ {
+ abbrevs =
+ XOBNEWVEC (&abbrev_obstack, struct abbrev_info *, ABBREV_HASH_SIZE);
+ memset (abbrevs, 0, ABBREV_HASH_SIZE * sizeof (struct abbrev_info *));
+ }
+
+ DISABLE_COPY_AND_ASSIGN (abbrev_table);
+
+ /* Allocate space for a struct abbrev_info object in
+ ABBREV_TABLE. */
+ struct abbrev_info *alloc_abbrev ();
+
+ /* Add an abbreviation to the table. */
+ void add_abbrev (unsigned int abbrev_number, struct abbrev_info *abbrev);
+
+ /* Look up an abbrev in the table.
+ Returns NULL if the abbrev is not found. */
+
+ struct abbrev_info *lookup_abbrev (unsigned int abbrev_number);
+
+
/* Where the abbrev table came from.
This is used as a sanity check when the table is used. */
- sect_offset sect_off;
+ const sect_offset sect_off;
/* Storage for the abbrev table. */
- struct obstack abbrev_obstack;
+ auto_obstack abbrev_obstack;
/* Hash table of abbrevs.
This is an array of size ABBREV_HASH_SIZE allocated in abbrev_obstack.
struct abbrev_info **abbrevs;
};
+typedef std::unique_ptr<struct abbrev_table> abbrev_table_up;
+
/* Attributes have a name and a value. */
struct attribute
{
static void psymtab_to_symtab_1 (struct partial_symtab *);
-static struct abbrev_info *abbrev_table_lookup_abbrev
- (const struct abbrev_table *, unsigned int);
-
-static struct abbrev_table *abbrev_table_read_table
+static abbrev_table_up abbrev_table_read_table
(struct dwarf2_per_objfile *dwarf2_per_objfile, struct dwarf2_section_info *,
sect_offset);
-static void abbrev_table_free (struct abbrev_table *);
-
-static void abbrev_table_free_cleanup (void *);
-
-static void dwarf2_read_abbrevs (struct dwarf2_cu *,
- struct dwarf2_section_info *);
-
-static void dwarf2_free_abbrev_table (void *);
-
static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
static struct partial_die_info *load_partial_dies
init_cu_die_reader (struct die_reader_specs *reader,
struct dwarf2_cu *cu,
struct dwarf2_section_info *section,
- struct dwo_file *dwo_file)
+ struct dwo_file *dwo_file,
+ struct abbrev_table *abbrev_table)
{
gdb_assert (section->readin && section->buffer != NULL);
reader->abfd = get_section_bfd_owner (section);
reader->buffer = section->buffer;
reader->buffer_end = section->buffer + section->size;
reader->comp_dir = NULL;
+ reader->abbrev_table = abbrev_table;
}
/* Subroutine of init_cutu_and_read_dies to simplify it.
STUB_COMP_DIR may be non-NULL.
*RESULT_READER,*RESULT_INFO_PTR,*RESULT_COMP_UNIT_DIE,*RESULT_HAS_CHILDREN
are filled in with the info of the DIE from the DWO file.
- ABBREV_TABLE_PROVIDED is non-zero if the caller of init_cutu_and_read_dies
- provided an abbrev table to use.
+ *RESULT_DWO_ABBREV_TABLE will be filled in with the abbrev table allocated
+ from the dwo. Since *RESULT_READER references this abbrev table, it must be
+ kept around for at least as long as *RESULT_READER.
+
The result is non-zero if a valid (non-dummy) DIE was found. */
static int
read_cutu_die_from_dwo (struct dwarf2_per_cu_data *this_cu,
struct dwo_unit *dwo_unit,
- int abbrev_table_provided,
struct die_info *stub_comp_unit_die,
const char *stub_comp_dir,
struct die_reader_specs *result_reader,
const gdb_byte **result_info_ptr,
struct die_info **result_comp_unit_die,
- int *result_has_children)
+ int *result_has_children,
+ abbrev_table_up *result_dwo_abbrev_table)
{
struct dwarf2_per_objfile *dwarf2_per_objfile = this_cu->dwarf2_per_objfile;
struct objfile *objfile = dwarf2_per_objfile->objfile;
struct dwarf2_cu *cu = this_cu->cu;
- struct dwarf2_section_info *section;
bfd *abfd;
const gdb_byte *begin_info_ptr, *info_ptr;
struct attribute *comp_dir, *stmt_list, *low_pc, *high_pc, *ranges;
/* Set up for reading the DWO CU/TU. */
cu->dwo_unit = dwo_unit;
- section = dwo_unit->section;
+ dwarf2_section_info *section = dwo_unit->section;
dwarf2_read_section (objfile, section);
abfd = get_section_bfd_owner (section);
begin_info_ptr = info_ptr = (section->buffer
+ to_underlying (dwo_unit->sect_off));
dwo_abbrev_section = &dwo_unit->dwo_file->sections.abbrev;
- init_cu_die_reader (result_reader, cu, section, dwo_unit->dwo_file);
if (this_cu->is_debug_types)
{
dwo_unit->length = get_cu_length (&cu->header);
}
- /* Replace the CU's original abbrev table with the DWO's.
- Reminder: We can't read the abbrev table until we've read the header. */
- if (abbrev_table_provided)
- {
- /* Don't free the provided abbrev table, the caller of
- init_cutu_and_read_dies owns it. */
- dwarf2_read_abbrevs (cu, dwo_abbrev_section);
- /* Ensure the DWO abbrev table gets freed. */
- make_cleanup (dwarf2_free_abbrev_table, cu);
- }
- else
- {
- dwarf2_free_abbrev_table (cu);
- dwarf2_read_abbrevs (cu, dwo_abbrev_section);
- /* Leave any existing abbrev table cleanup as is. */
- }
+ *result_dwo_abbrev_table
+ = abbrev_table_read_table (dwarf2_per_objfile, dwo_abbrev_section,
+ cu->header.abbrev_sect_off);
+ init_cu_die_reader (result_reader, cu, section, dwo_unit->dwo_file,
+ result_dwo_abbrev_table->get ());
/* Read in the die, but leave space to copy over the attributes
from the stub. This has the benefit of simplifying the rest of
abbrev table. When reading DWOs with skeletonless TUs, all the TUs
could share abbrev tables. */
+ /* The abbreviation table used by READER, this must live at least as long as
+ READER. */
+ abbrev_table_up dwo_abbrev_table;
+
if (read_cutu_die_from_dwo (this_cu, sig_type->dwo_unit,
- 0 /* abbrev_table_provided */,
NULL /* stub_comp_unit_die */,
sig_type->dwo_unit->dwo_file->comp_dir,
&reader, &info_ptr,
- &comp_unit_die, &has_children) == 0)
+ &comp_unit_die, &has_children,
+ &dwo_abbrev_table) == 0)
{
/* Dummy die. */
do_cleanups (cleanups);
caller clean it up when finished with it. */
discard_cleanups (free_cu_cleanup);
- /* We can only discard free_cu_cleanup and all subsequent cleanups.
- So we have to manually free the abbrev table. */
- dwarf2_free_abbrev_table (cu);
-
/* Link this CU into read_in_chain. */
this_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
dwarf2_per_objfile->read_in_chain = this_cu;
/* If we don't have them yet, read the abbrevs for this compilation unit.
And if we need to read them now, make sure they're freed when we're
- done. Note that it's important that if the CU had an abbrev table
- on entry we don't free it when we're done: Somewhere up the call stack
- it may be in use. */
+ done (own the table through ABBREV_TABLE_HOLDER). */
+ abbrev_table_up abbrev_table_holder;
if (abbrev_table != NULL)
+ gdb_assert (cu->header.abbrev_sect_off == abbrev_table->sect_off);
+ else
{
- gdb_assert (cu->abbrev_table == NULL);
- gdb_assert (cu->header.abbrev_sect_off == abbrev_table->sect_off);
- cu->abbrev_table = abbrev_table;
- }
- else if (cu->abbrev_table == NULL)
- {
- dwarf2_read_abbrevs (cu, abbrev_section);
- make_cleanup (dwarf2_free_abbrev_table, cu);
- }
- else if (rereading_dwo_cu)
- {
- dwarf2_free_abbrev_table (cu);
- dwarf2_read_abbrevs (cu, abbrev_section);
+ abbrev_table_holder
+ = abbrev_table_read_table (dwarf2_per_objfile, abbrev_section,
+ cu->header.abbrev_sect_off);
+ abbrev_table = abbrev_table_holder.get ();
}
/* Read the top level CU/TU die. */
- init_cu_die_reader (&reader, cu, section, NULL);
+ init_cu_die_reader (&reader, cu, section, NULL, abbrev_table);
info_ptr = read_full_die (&reader, &comp_unit_die, info_ptr, &has_children);
/* If we are in a DWO stub, process it and then read in the "real" CU/TU
- from the DWO file.
+ from the DWO file. read_cutu_die_from_dwo will allocate the abbreviation
+ table from the DWO file and pass the ownership over to us. It will be
+ referenced from READER, so we must make sure to free it after we're done
+ with READER.
+
Note that if USE_EXISTING_OK != 0, and THIS_CU->cu already contains a
DWO CU, that this test will fail (the attribute will not be present). */
attr = dwarf2_attr (comp_unit_die, DW_AT_GNU_dwo_name, cu);
+ abbrev_table_up dwo_abbrev_table;
if (attr)
{
struct dwo_unit *dwo_unit;
if (dwo_unit != NULL)
{
if (read_cutu_die_from_dwo (this_cu, dwo_unit,
- abbrev_table != NULL,
comp_unit_die, NULL,
&reader, &info_ptr,
- &dwo_comp_unit_die, &has_children) == 0)
+ &dwo_comp_unit_die, &has_children,
+ &dwo_abbrev_table) == 0)
{
/* Dummy die. */
do_cleanups (cleanups);
caller clean it up when finished with it. */
discard_cleanups (free_cu_cleanup);
- /* We can only discard free_cu_cleanup and all subsequent cleanups.
- So we have to manually free the abbrev table. */
- dwarf2_free_abbrev_table (cu);
-
/* Link this CU into read_in_chain. */
this_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
dwarf2_per_objfile->read_in_chain = this_cu;
return;
}
- dwarf2_read_abbrevs (&cu, abbrev_section);
- make_cleanup (dwarf2_free_abbrev_table, &cu);
+ abbrev_table_up abbrev_table
+ = abbrev_table_read_table (dwarf2_per_objfile, abbrev_section,
+ cu.header.abbrev_sect_off);
- init_cu_die_reader (&reader, &cu, section, dwo_file);
+ init_cu_die_reader (&reader, &cu, section, dwo_file, abbrev_table.get ());
info_ptr = read_full_die (&reader, &comp_unit_die, info_ptr, &has_children);
die_reader_func (&reader, info_ptr, comp_unit_die, has_children, data);
{
struct tu_stats *tu_stats = &dwarf2_per_objfile->tu_stats;
struct cleanup *cleanups;
- struct abbrev_table *abbrev_table;
+ abbrev_table_up abbrev_table;
sect_offset abbrev_offset;
struct tu_abbrev_offset *sorted_by_abbrev;
int i;
sizeof (struct tu_abbrev_offset), sort_tu_by_abbrev_offset);
abbrev_offset = (sect_offset) ~(unsigned) 0;
- abbrev_table = NULL;
- make_cleanup (abbrev_table_free_cleanup, &abbrev_table);
for (i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
{
if (abbrev_table == NULL
|| tu->abbrev_offset != abbrev_offset)
{
- if (abbrev_table != NULL)
- {
- abbrev_table_free (abbrev_table);
- /* Reset to NULL in case abbrev_table_read_table throws
- an error: abbrev_table_free_cleanup will get called. */
- abbrev_table = NULL;
- }
abbrev_offset = tu->abbrev_offset;
abbrev_table =
abbrev_table_read_table (dwarf2_per_objfile,
++tu_stats->nr_uniq_abbrev_tables;
}
- init_cutu_and_read_dies (&tu->sig_type->per_cu, abbrev_table, 0, 0,
- build_type_psymtabs_reader, NULL);
+ init_cutu_and_read_dies (&tu->sig_type->per_cu, abbrev_table.get (),
+ 0, 0, build_type_psymtabs_reader, NULL);
}
do_cleanups (cleanups);
return read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
}
-/* Read the initial uleb128 in the die at INFO_PTR in compilation unit CU.
+/* Read the initial uleb128 in the die at INFO_PTR in compilation unit
+ READER::CU. Use READER::ABBREV_TABLE to lookup any abbreviation.
+
Return the corresponding abbrev, or NULL if the number is zero (indicating
an empty DIE). In either case *BYTES_READ will be set to the length of
the initial number. */
static struct abbrev_info *
-peek_die_abbrev (const gdb_byte *info_ptr, unsigned int *bytes_read,
- struct dwarf2_cu *cu)
+peek_die_abbrev (const die_reader_specs &reader,
+ const gdb_byte *info_ptr, unsigned int *bytes_read)
{
+ dwarf2_cu *cu = reader.cu;
bfd *abfd = cu->per_cu->dwarf2_per_objfile->objfile->obfd;
- unsigned int abbrev_number;
- struct abbrev_info *abbrev;
-
- abbrev_number = read_unsigned_leb128 (abfd, info_ptr, bytes_read);
+ unsigned int abbrev_number
+ = read_unsigned_leb128 (abfd, info_ptr, bytes_read);
if (abbrev_number == 0)
return NULL;
- abbrev = abbrev_table_lookup_abbrev (cu->abbrev_table, abbrev_number);
+ abbrev_info *abbrev = reader.abbrev_table->lookup_abbrev (abbrev_number);
if (!abbrev)
{
error (_("Dwarf Error: Could not find abbrev number %d in %s"
static const gdb_byte *
skip_children (const struct die_reader_specs *reader, const gdb_byte *info_ptr)
{
- struct dwarf2_cu *cu = reader->cu;
- struct abbrev_info *abbrev;
- unsigned int bytes_read;
-
while (1)
{
- abbrev = peek_die_abbrev (info_ptr, &bytes_read, cu);
+ unsigned int bytes_read;
+ abbrev_info *abbrev = peek_die_abbrev (*reader, info_ptr, &bytes_read);
+
if (abbrev == NULL)
return info_ptr + bytes_read;
else
return info_ptr;
}
- abbrev = abbrev_table_lookup_abbrev (cu->abbrev_table, abbrev_number);
+ abbrev = reader->abbrev_table->lookup_abbrev (abbrev_number);
if (!abbrev)
error (_("Dwarf Error: could not find abbrev number %d [in module %s]"),
abbrev_number,
/* Allocate space for a struct abbrev_info object in ABBREV_TABLE. */
-static struct abbrev_info *
-abbrev_table_alloc_abbrev (struct abbrev_table *abbrev_table)
+struct abbrev_info *
+abbrev_table::alloc_abbrev ()
{
struct abbrev_info *abbrev;
- abbrev = XOBNEW (&abbrev_table->abbrev_obstack, struct abbrev_info);
+ abbrev = XOBNEW (&abbrev_obstack, struct abbrev_info);
memset (abbrev, 0, sizeof (struct abbrev_info));
return abbrev;
/* Add an abbreviation to the table. */
-static void
-abbrev_table_add_abbrev (struct abbrev_table *abbrev_table,
- unsigned int abbrev_number,
- struct abbrev_info *abbrev)
+void
+abbrev_table::add_abbrev (unsigned int abbrev_number,
+ struct abbrev_info *abbrev)
{
unsigned int hash_number;
hash_number = abbrev_number % ABBREV_HASH_SIZE;
- abbrev->next = abbrev_table->abbrevs[hash_number];
- abbrev_table->abbrevs[hash_number] = abbrev;
+ abbrev->next = abbrevs[hash_number];
+ abbrevs[hash_number] = abbrev;
}
/* Look up an abbrev in the table.
Returns NULL if the abbrev is not found. */
-static struct abbrev_info *
-abbrev_table_lookup_abbrev (const struct abbrev_table *abbrev_table,
- unsigned int abbrev_number)
+struct abbrev_info *
+abbrev_table::lookup_abbrev (unsigned int abbrev_number)
{
unsigned int hash_number;
struct abbrev_info *abbrev;
hash_number = abbrev_number % ABBREV_HASH_SIZE;
- abbrev = abbrev_table->abbrevs[hash_number];
+ abbrev = abbrevs[hash_number];
while (abbrev)
{
/* Read in an abbrev table. */
-static struct abbrev_table *
+static abbrev_table_up
abbrev_table_read_table (struct dwarf2_per_objfile *dwarf2_per_objfile,
struct dwarf2_section_info *section,
sect_offset sect_off)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
bfd *abfd = get_section_bfd_owner (section);
- struct abbrev_table *abbrev_table;
const gdb_byte *abbrev_ptr;
struct abbrev_info *cur_abbrev;
unsigned int abbrev_number, bytes_read, abbrev_name;
struct attr_abbrev *cur_attrs;
unsigned int allocated_attrs;
- abbrev_table = XNEW (struct abbrev_table);
- abbrev_table->sect_off = sect_off;
- obstack_init (&abbrev_table->abbrev_obstack);
- abbrev_table->abbrevs =
- XOBNEWVEC (&abbrev_table->abbrev_obstack, struct abbrev_info *,
- ABBREV_HASH_SIZE);
- memset (abbrev_table->abbrevs, 0,
- ABBREV_HASH_SIZE * sizeof (struct abbrev_info *));
+ abbrev_table_up abbrev_table (new struct abbrev_table (sect_off));
dwarf2_read_section (objfile, section);
abbrev_ptr = section->buffer + to_underlying (sect_off);
/* Loop until we reach an abbrev number of 0. */
while (abbrev_number)
{
- cur_abbrev = abbrev_table_alloc_abbrev (abbrev_table);
+ cur_abbrev = abbrev_table->alloc_abbrev ();
/* read in abbrev header */
cur_abbrev->number = abbrev_number;
memcpy (cur_abbrev->attrs, cur_attrs,
cur_abbrev->num_attrs * sizeof (struct attr_abbrev));
- abbrev_table_add_abbrev (abbrev_table, abbrev_number, cur_abbrev);
+ abbrev_table->add_abbrev (abbrev_number, cur_abbrev);
/* Get next abbreviation.
Under Irix6 the abbreviations for a compilation unit are not
break;
abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
- if (abbrev_table_lookup_abbrev (abbrev_table, abbrev_number) != NULL)
+ if (abbrev_table->lookup_abbrev (abbrev_number) != NULL)
break;
}
return abbrev_table;
}
-/* Free the resources held by ABBREV_TABLE. */
-
-static void
-abbrev_table_free (struct abbrev_table *abbrev_table)
-{
- obstack_free (&abbrev_table->abbrev_obstack, NULL);
- xfree (abbrev_table);
-}
-
-/* Same as abbrev_table_free but as a cleanup.
- We pass in a pointer to the pointer to the table so that we can
- set the pointer to NULL when we're done. It also simplifies
- build_type_psymtabs_1. */
-
-static void
-abbrev_table_free_cleanup (void *table_ptr)
-{
- struct abbrev_table **abbrev_table_ptr = (struct abbrev_table **) table_ptr;
-
- if (*abbrev_table_ptr != NULL)
- abbrev_table_free (*abbrev_table_ptr);
- *abbrev_table_ptr = NULL;
-}
-
-/* Read the abbrev table for CU from ABBREV_SECTION. */
-
-static void
-dwarf2_read_abbrevs (struct dwarf2_cu *cu,
- struct dwarf2_section_info *abbrev_section)
-{
- cu->abbrev_table =
- abbrev_table_read_table (cu->per_cu->dwarf2_per_objfile, abbrev_section,
- cu->header.abbrev_sect_off);
-}
-
-/* Release the memory used by the abbrev table for a compilation unit. */
-
-static void
-dwarf2_free_abbrev_table (void *ptr_to_cu)
-{
- struct dwarf2_cu *cu = (struct dwarf2_cu *) ptr_to_cu;
-
- if (cu->abbrev_table != NULL)
- abbrev_table_free (cu->abbrev_table);
- /* Set this to NULL so that we SEGV if we try to read it later,
- and also because free_comp_unit verifies this is NULL. */
- cu->abbrev_table = NULL;
-}
-\f
/* Returns nonzero if TAG represents a type that we might generate a partial
symbol for. */
struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
struct partial_die_info *part_die;
struct partial_die_info *parent_die, *last_die, *first_die = NULL;
- struct abbrev_info *abbrev;
unsigned int bytes_read;
unsigned int load_all = 0;
int nesting_level = 1;
while (1)
{
- abbrev = peek_die_abbrev (info_ptr, &bytes_read, cu);
+ abbrev_info *abbrev = peek_die_abbrev (*reader, info_ptr, &bytes_read);
/* A NULL abbrev means the end of a series of children. */
if (abbrev == NULL)