This is stored in malloc space because we may realloc it. */
struct signatured_type **all_type_units;
- /* The number of entries in all_type_unit_groups. */
- int n_type_unit_groups;
-
- /* Table of type unit groups.
- This exists to make it easy to iterate over all CUs and TU groups. */
- struct type_unit_group **all_type_unit_groups;
-
/* Table of struct type_unit_group objects.
The hash key is the DW_AT_stmt_list value. */
htab_t type_unit_groups;
unsigned int *);
static const char *read_str_index (const struct die_reader_specs *reader,
- struct dwarf2_cu *cu, ULONGEST str_index);
+ ULONGEST str_index);
static void set_cu_language (unsigned int, struct dwarf2_cu *);
static void read_signatured_type (struct signatured_type *);
-static struct type_unit_group *get_type_unit_group
- (struct dwarf2_cu *, const struct attribute *);
-
-static void build_type_unit_groups (die_reader_func_ftype *, void *);
-
/* memory allocation interface */
static struct dwarf_block *dwarf_alloc_block (struct dwarf2_cu *);
return per_cu->v.quick->symtab;
}
-/* Return the CU given its index.
+/* Return the CU/TU given its index.
This is intended for loops like:
for (i = 0; i < (dwarf2_per_objfile->n_comp_units
+ dwarf2_per_objfile->n_type_units); ++i)
{
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
...;
}
*/
static struct dwarf2_per_cu_data *
-dw2_get_cu (int index)
+dw2_get_cutu (int index)
{
if (index >= dwarf2_per_objfile->n_comp_units)
{
return dwarf2_per_objfile->all_comp_units[index];
}
-/* Return the primary CU given its index.
- The difference between this function and dw2_get_cu is in the handling
- of type units (TUs). Here we return the type_unit_group object.
-
- This is intended for loops like:
-
- for (i = 0; i < (dwarf2_per_objfile->n_comp_units
- + dwarf2_per_objfile->n_type_unit_groups); ++i)
- {
- struct dwarf2_per_cu_data *per_cu = dw2_get_primary_cu (i);
-
- ...;
- }
-*/
+/* Return the CU given its index.
+ This differs from dw2_get_cutu in that it's for when you know INDEX
+ refers to a CU. */
static struct dwarf2_per_cu_data *
-dw2_get_primary_cu (int index)
+dw2_get_cu (int index)
{
- if (index >= dwarf2_per_objfile->n_comp_units)
- {
- index -= dwarf2_per_objfile->n_comp_units;
- gdb_assert (index < dwarf2_per_objfile->n_type_unit_groups);
- return &dwarf2_per_objfile->all_type_unit_groups[index]->per_cu;
- }
+ gdb_assert (index >= 0 && index < dwarf2_per_objfile->n_comp_units);
return dwarf2_per_objfile->all_comp_units[index];
}
}
addrmap_set_empty (mutable_map, lo + baseaddr, hi + baseaddr - 1,
- dw2_get_cu (cu_index));
+ dw2_get_cutu (cu_index));
}
objfile->psymtabs_addrmap = addrmap_create_fixed (mutable_map,
dw2_setup (objfile);
index = dwarf2_per_objfile->n_comp_units - 1;
- return dw2_instantiate_symtab (dw2_get_cu (index));
+ return dw2_instantiate_symtab (dw2_get_cutu (index));
}
/* Traversal function for dw2_forget_cached_source_info. */
for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
int j;
- struct dwarf2_per_cu_data *per_cu = dw2_get_primary_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
struct quick_file_names *file_data;
/* We only need to look at symtabs not already expanded. */
continue;
}
- per_cu = dw2_get_cu (cu_index);
+ per_cu = dw2_get_cutu (cu_index);
/* Skip if already read in. */
if (per_cu->v.quick->symtab)
count = 0;
for (i = 0; i < total; ++i)
{
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
if (!per_cu->v.quick->symtab)
++count;
for (i = 0; i < (dwarf2_per_objfile->n_comp_units
+ dwarf2_per_objfile->n_type_units); ++i)
{
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
dw2_instantiate_symtab (per_cu);
}
for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
int j;
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
struct quick_file_names *file_data;
/* We only need to look at symtabs not already expanded. */
for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
int j;
- struct dwarf2_per_cu_data *per_cu = dw2_get_primary_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
struct quick_file_names *file_data;
void **slot;
continue;
}
- per_cu = dw2_get_cu (cu_index);
+ per_cu = dw2_get_cutu (cu_index);
if (file_matcher == NULL || per_cu->v.quick->mark)
dw2_instantiate_symtab (per_cu);
}
for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
if (per_cu->v.quick->symtab)
{
for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
int j;
- struct dwarf2_per_cu_data *per_cu = dw2_get_primary_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
struct quick_file_names *file_data;
void **slot;
for (i = 0; i < (dwarf2_per_objfile->n_comp_units
+ dwarf2_per_objfile->n_type_units); ++i)
{
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
per_cu->v.quick = OBSTACK_ZALLOC (&objfile->objfile_obstack,
struct dwarf2_per_cu_quick_data);
from it to the DIE in the DWO. If NULL we are skipping the stub.
STUB_COMP_DIR is similar to STUB_COMP_UNIT_DIE: When reading a TU directly
from the DWO file, bypassing the stub, it contains the DW_AT_comp_dir
- attribute of the referencing CU. Exactly one of STUB_COMP_UNIT_DIE and
- STUB_COMP_DIR must be non-NULL.
+ attribute of the referencing CU. At most one of STUB_COMP_UNIT_DIE and
+ 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
struct dwarf2_section_info *section;
bfd *abfd;
const gdb_byte *begin_info_ptr, *info_ptr;
- const char *comp_dir_string;
ULONGEST signature; /* Or dwo_id. */
struct attribute *comp_dir, *stmt_list, *low_pc, *high_pc, *ranges;
int i,num_extra_attrs;
struct attribute *attr;
struct die_info *comp_unit_die;
- /* Exactly one of these must be provided. */
- gdb_assert ((stub_comp_unit_die != NULL) + (stub_comp_dir != NULL) == 1);
+ /* At most one of these may be provided. */
+ gdb_assert ((stub_comp_unit_die != NULL) + (stub_comp_dir != NULL) <= 1);
/* These attributes aren't processed until later:
DW_AT_stmt_list, DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges.
- However, the attribute is found in the stub which we won't have later.
- In order to not impose this complication on the rest of the code,
- we read them here and copy them to the DWO CU/TU die. */
+ DW_AT_comp_dir is used now, to find the DWO file, but it is also
+ referenced later. However, these attributes are found in the stub
+ which we won't have later. In order to not impose this complication
+ on the rest of the code, we read them here and copy them to the
+ DWO CU/TU die. */
stmt_list = NULL;
low_pc = NULL;
return tu_group;
}
-
-/* Struct used to sort TUs by their abbreviation table offset. */
-
-struct tu_abbrev_offset
-{
- struct signatured_type *sig_type;
- sect_offset abbrev_offset;
-};
-
-/* Helper routine for build_type_unit_groups, passed to qsort. */
-
-static int
-sort_tu_by_abbrev_offset (const void *ap, const void *bp)
-{
- const struct tu_abbrev_offset * const *a = ap;
- const struct tu_abbrev_offset * const *b = bp;
- unsigned int aoff = (*a)->abbrev_offset.sect_off;
- unsigned int boff = (*b)->abbrev_offset.sect_off;
-
- return (aoff > boff) - (aoff < boff);
-}
-
-/* A helper function to add a type_unit_group to a table. */
-
-static int
-add_type_unit_group_to_table (void **slot, void *datum)
-{
- struct type_unit_group *tu_group = *slot;
- struct type_unit_group ***datap = datum;
-
- **datap = tu_group;
- ++*datap;
-
- return 1;
-}
-
-/* Efficiently read all the type units, calling init_cutu_and_read_dies on
- each one passing FUNC,DATA.
-
- The efficiency is because we sort TUs by the abbrev table they use and
- only read each abbrev table once. In one program there are 200K TUs
- sharing 8K abbrev tables.
-
- The main purpose of this function is to support building the
- dwarf2_per_objfile->type_unit_groups table.
- TUs typically share the DW_AT_stmt_list of the CU they came from, so we
- can collapse the search space by grouping them by stmt_list.
- The savings can be significant, in the same program from above the 200K TUs
- share 8K stmt_list tables.
-
- FUNC is expected to call get_type_unit_group, which will create the
- struct type_unit_group if necessary and add it to
- dwarf2_per_objfile->type_unit_groups. */
-
-static void
-build_type_unit_groups (die_reader_func_ftype *func, void *data)
-{
- struct objfile *objfile = dwarf2_per_objfile->objfile;
- struct tu_stats *tu_stats = &dwarf2_per_objfile->tu_stats;
- struct cleanup *cleanups;
- struct abbrev_table *abbrev_table;
- sect_offset abbrev_offset;
- struct tu_abbrev_offset *sorted_by_abbrev;
- struct type_unit_group **iter;
- int i;
-
- /* It's up to the caller to not call us multiple times. */
- gdb_assert (dwarf2_per_objfile->type_unit_groups == NULL);
-
- if (dwarf2_per_objfile->n_type_units == 0)
- return;
-
- /* TUs typically share abbrev tables, and there can be way more TUs than
- abbrev tables. Sort by abbrev table to reduce the number of times we
- read each abbrev table in.
- Alternatives are to punt or to maintain a cache of abbrev tables.
- This is simpler and efficient enough for now.
-
- Later we group TUs by their DW_AT_stmt_list value (as this defines the
- symtab to use). Typically TUs with the same abbrev offset have the same
- stmt_list value too so in practice this should work well.
-
- The basic algorithm here is:
-
- sort TUs by abbrev table
- for each TU with same abbrev table:
- read abbrev table if first user
- read TU top level DIE
- [IWBN if DWO skeletons had DW_AT_stmt_list]
- call FUNC */
-
- if (dwarf2_read_debug)
- fprintf_unfiltered (gdb_stdlog, "Building type unit groups ...\n");
-
- /* Sort in a separate table to maintain the order of all_type_units
- for .gdb_index: TU indices directly index all_type_units. */
- sorted_by_abbrev = XNEWVEC (struct tu_abbrev_offset,
- dwarf2_per_objfile->n_type_units);
- for (i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
- {
- struct signatured_type *sig_type = dwarf2_per_objfile->all_type_units[i];
-
- sorted_by_abbrev[i].sig_type = sig_type;
- sorted_by_abbrev[i].abbrev_offset =
- read_abbrev_offset (sig_type->per_cu.section,
- sig_type->per_cu.offset);
- }
- cleanups = make_cleanup (xfree, sorted_by_abbrev);
- qsort (sorted_by_abbrev, dwarf2_per_objfile->n_type_units,
- sizeof (struct tu_abbrev_offset), sort_tu_by_abbrev_offset);
-
- /* Note: In the .gdb_index case, get_type_unit_group may have already been
- called any number of times, so we don't reset tu_stats here. */
-
- abbrev_offset.sect_off = ~(unsigned) 0;
- abbrev_table = NULL;
- make_cleanup (abbrev_table_free_cleanup, &abbrev_table);
-
- for (i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
- {
- const struct tu_abbrev_offset *tu = &sorted_by_abbrev[i];
-
- /* Switch to the next abbrev table if necessary. */
- if (abbrev_table == NULL
- || tu->abbrev_offset.sect_off != abbrev_offset.sect_off)
- {
- 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->abbrev,
- abbrev_offset);
- ++tu_stats->nr_uniq_abbrev_tables;
- }
-
- init_cutu_and_read_dies (&tu->sig_type->per_cu, abbrev_table, 0, 0,
- func, data);
- }
-
- /* type_unit_groups can be NULL if there is an error in the debug info.
- Just create an empty table so the rest of gdb doesn't have to watch
- for this error case. */
- if (dwarf2_per_objfile->type_unit_groups == NULL)
- {
- dwarf2_per_objfile->type_unit_groups =
- allocate_type_unit_groups_table ();
- dwarf2_per_objfile->n_type_unit_groups = 0;
- }
-
- /* Create a vector of pointers to primary type units to make it easy to
- iterate over them and CUs. See dw2_get_primary_cu. */
- dwarf2_per_objfile->n_type_unit_groups =
- htab_elements (dwarf2_per_objfile->type_unit_groups);
- dwarf2_per_objfile->all_type_unit_groups =
- obstack_alloc (&objfile->objfile_obstack,
- dwarf2_per_objfile->n_type_unit_groups
- * sizeof (struct type_unit_group *));
- iter = &dwarf2_per_objfile->all_type_unit_groups[0];
- htab_traverse_noresize (dwarf2_per_objfile->type_unit_groups,
- add_type_unit_group_to_table, &iter);
- gdb_assert (iter - &dwarf2_per_objfile->all_type_unit_groups[0]
- == dwarf2_per_objfile->n_type_unit_groups);
-
- do_cleanups (cleanups);
-
- if (dwarf2_read_debug)
- {
- fprintf_unfiltered (gdb_stdlog, "Done building type unit groups:\n");
- fprintf_unfiltered (gdb_stdlog, " %d TUs\n",
- dwarf2_per_objfile->n_type_units);
- fprintf_unfiltered (gdb_stdlog, " %d uniq abbrev tables\n",
- tu_stats->nr_uniq_abbrev_tables);
- fprintf_unfiltered (gdb_stdlog, " %d symtabs from stmt_list entries\n",
- tu_stats->nr_symtabs);
- fprintf_unfiltered (gdb_stdlog, " %d symtab sharers\n",
- tu_stats->nr_symtab_sharers);
- fprintf_unfiltered (gdb_stdlog, " %d type units without a stmt_list\n",
- tu_stats->nr_stmt_less_type_units);
- }
-}
\f
/* Partial symbol tables. */
sort_pst_symbols (objfile, pst);
}
+/* Struct used to sort TUs by their abbreviation table offset. */
+
+struct tu_abbrev_offset
+{
+ struct signatured_type *sig_type;
+ sect_offset abbrev_offset;
+};
+
+/* Helper routine for build_type_psymtabs_1, passed to qsort. */
+
+static int
+sort_tu_by_abbrev_offset (const void *ap, const void *bp)
+{
+ const struct tu_abbrev_offset * const *a = ap;
+ const struct tu_abbrev_offset * const *b = bp;
+ unsigned int aoff = (*a)->abbrev_offset.sect_off;
+ unsigned int boff = (*b)->abbrev_offset.sect_off;
+
+ return (aoff > boff) - (aoff < boff);
+}
+
+/* Efficiently read all the type units.
+ This does the bulk of the work for build_type_psymtabs.
+
+ The efficiency is because we sort TUs by the abbrev table they use and
+ only read each abbrev table once. In one program there are 200K TUs
+ sharing 8K abbrev tables.
+
+ The main purpose of this function is to support building the
+ dwarf2_per_objfile->type_unit_groups table.
+ TUs typically share the DW_AT_stmt_list of the CU they came from, so we
+ can collapse the search space by grouping them by stmt_list.
+ The savings can be significant, in the same program from above the 200K TUs
+ share 8K stmt_list tables.
+
+ FUNC is expected to call get_type_unit_group, which will create the
+ struct type_unit_group if necessary and add it to
+ dwarf2_per_objfile->type_unit_groups. */
+
+static void
+build_type_psymtabs_1 (void)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ struct tu_stats *tu_stats = &dwarf2_per_objfile->tu_stats;
+ struct cleanup *cleanups;
+ struct abbrev_table *abbrev_table;
+ sect_offset abbrev_offset;
+ struct tu_abbrev_offset *sorted_by_abbrev;
+ struct type_unit_group **iter;
+ int i;
+
+ /* It's up to the caller to not call us multiple times. */
+ gdb_assert (dwarf2_per_objfile->type_unit_groups == NULL);
+
+ if (dwarf2_per_objfile->n_type_units == 0)
+ return;
+
+ /* TUs typically share abbrev tables, and there can be way more TUs than
+ abbrev tables. Sort by abbrev table to reduce the number of times we
+ read each abbrev table in.
+ Alternatives are to punt or to maintain a cache of abbrev tables.
+ This is simpler and efficient enough for now.
+
+ Later we group TUs by their DW_AT_stmt_list value (as this defines the
+ symtab to use). Typically TUs with the same abbrev offset have the same
+ stmt_list value too so in practice this should work well.
+
+ The basic algorithm here is:
+
+ sort TUs by abbrev table
+ for each TU with same abbrev table:
+ read abbrev table if first user
+ read TU top level DIE
+ [IWBN if DWO skeletons had DW_AT_stmt_list]
+ call FUNC */
+
+ if (dwarf2_read_debug)
+ fprintf_unfiltered (gdb_stdlog, "Building type unit groups ...\n");
+
+ /* Sort in a separate table to maintain the order of all_type_units
+ for .gdb_index: TU indices directly index all_type_units. */
+ sorted_by_abbrev = XNEWVEC (struct tu_abbrev_offset,
+ dwarf2_per_objfile->n_type_units);
+ for (i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
+ {
+ struct signatured_type *sig_type = dwarf2_per_objfile->all_type_units[i];
+
+ sorted_by_abbrev[i].sig_type = sig_type;
+ sorted_by_abbrev[i].abbrev_offset =
+ read_abbrev_offset (sig_type->per_cu.section,
+ sig_type->per_cu.offset);
+ }
+ cleanups = make_cleanup (xfree, sorted_by_abbrev);
+ qsort (sorted_by_abbrev, dwarf2_per_objfile->n_type_units,
+ sizeof (struct tu_abbrev_offset), sort_tu_by_abbrev_offset);
+
+ abbrev_offset.sect_off = ~(unsigned) 0;
+ abbrev_table = NULL;
+ make_cleanup (abbrev_table_free_cleanup, &abbrev_table);
+
+ for (i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
+ {
+ const struct tu_abbrev_offset *tu = &sorted_by_abbrev[i];
+
+ /* Switch to the next abbrev table if necessary. */
+ if (abbrev_table == NULL
+ || tu->abbrev_offset.sect_off != abbrev_offset.sect_off)
+ {
+ 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->abbrev,
+ abbrev_offset);
+ ++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);
+ }
+
+ /* type_unit_groups can be NULL if there is an error in the debug info.
+ Just create an empty table so the rest of gdb doesn't have to watch
+ for this error case. */
+ if (dwarf2_per_objfile->type_unit_groups == NULL)
+ {
+ dwarf2_per_objfile->type_unit_groups =
+ allocate_type_unit_groups_table ();
+ }
+
+ do_cleanups (cleanups);
+
+ if (dwarf2_read_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Done building type unit groups:\n");
+ fprintf_unfiltered (gdb_stdlog, " %d TUs\n",
+ dwarf2_per_objfile->n_type_units);
+ fprintf_unfiltered (gdb_stdlog, " %d uniq abbrev tables\n",
+ tu_stats->nr_uniq_abbrev_tables);
+ fprintf_unfiltered (gdb_stdlog, " %d symtabs from stmt_list entries\n",
+ tu_stats->nr_symtabs);
+ fprintf_unfiltered (gdb_stdlog, " %d symtab sharers\n",
+ tu_stats->nr_symtab_sharers);
+ fprintf_unfiltered (gdb_stdlog, " %d type units without a stmt_list\n",
+ tu_stats->nr_stmt_less_type_units);
+ }
+}
+
/* Traversal function for build_type_psymtabs. */
static int
if (! create_all_type_units (objfile))
return;
- build_type_unit_groups (build_type_psymtabs_reader, NULL);
+ build_type_psymtabs_1 ();
/* Now that all TUs have been processed we can fill in the dependencies. */
htab_traverse_noresize (dwarf2_per_objfile->type_unit_groups,
for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
struct partial_symtab *pst = per_cu->v.psymtab;
int j;
for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
process_psymtab_comp_unit (per_cu, 0, language_minimal);
}
if (sibling_ptr < info_ptr)
complaint (&symfile_complaints,
_("DW_AT_sibling points backwards"));
+ else if (sibling_ptr > reader->buffer_end)
+ dwarf2_section_buffer_overflow_complaint (reader->die_section);
else
return sibling_ptr;
}
/* Called when we find the DIE that starts a structure or union scope
(definition) to create a type for the structure or union. Fill in
the type's name and general properties; the members will not be
- processed until process_structure_scope.
+ processed until process_structure_scope. A symbol table entry for
+ the type will also not be done until process_structure_scope (assuming
+ the type has a name).
NOTE: we need to call these functions regardless of whether or not the
DIE has a DW_AT_name attribute, since it might be an anonymous
structure or union. This gets the type entered into our set of
- user defined types.
-
- However, if the structure is incomplete (an opaque struct/union)
- then suppress creating a symbol table entry for it since gdb only
- wants to find the one with the complete definition. Note that if
- it is complete, we just call new_symbol, which does it's own
- checking about whether the struct/union is anonymous or not (and
- suppresses creating a symbol table entry itself). */
+ user defined types. */
static struct type *
read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
if (name != NULL)
TYPE_TAG_NAME (type) = name;
+ attr = dwarf2_attr (die, DW_AT_type, cu);
+ if (attr != NULL)
+ {
+ struct type *underlying_type = die_type (die, cu);
+
+ TYPE_TARGET_TYPE (type) = underlying_type;
+ }
+
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr)
{
if (die_is_declaration (die, cu))
TYPE_STUB (type) = 1;
- /* Finish the creation of this type by using the enum's children. */
+ /* Finish the creation of this type by using the enum's children.
+ We must call this even when the underlying type has been provided
+ so that we can determine if we're looking at a "flag" enum. */
update_enumeration_type_from_children (die, type, cu);
+ /* If this type has an underlying type that is not a stub, then we
+ may use its attributes. We always use the "unsigned" attribute
+ in this situation, because ordinarily we guess whether the type
+ is unsigned -- but the guess can be wrong and the underlying type
+ can tell us the reality. However, we defer to a local size
+ attribute if one exists, because this lets the compiler override
+ the underlying type if needed. */
+ if (TYPE_TARGET_TYPE (type) != NULL && !TYPE_STUB (TYPE_TARGET_TYPE (type)))
+ {
+ TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TYPE_TARGET_TYPE (type));
+ if (TYPE_LENGTH (type) == 0)
+ TYPE_LENGTH (type) = TYPE_LENGTH (TYPE_TARGET_TYPE (type));
+ }
+
+ TYPE_DECLARED_CLASS (type) = dwarf2_flag_true_p (die, DW_AT_enum_class, cu);
+
return set_die_type (die, type, cu);
}
if (die->child == NULL)
{
index_type = objfile_type (objfile)->builtin_int;
- range_type = create_range_type (NULL, index_type, 0, -1);
+ range_type = create_static_range_type (NULL, index_type, 0, -1);
type = create_array_type_with_stride (NULL, element_type, range_type,
bit_stride);
return set_die_type (die, type, cu);
}
index_type = objfile_type (objfile)->builtin_int;
- range_type = create_range_type (NULL, index_type, 1, length);
+ range_type = create_static_range_type (NULL, index_type, 1, length);
char_type = language_string_char_type (cu->language_defn, gdbarch);
type = create_string_type (NULL, char_type, range_type);
return set_die_type (die, type, cu);
}
+/* Parse dwarf attribute if it's a block, reference or constant and put the
+ resulting value of the attribute into struct bound_prop.
+ Returns 1 if ATTR could be resolved into PROP, 0 otherwise. */
+
+static int
+attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die,
+ struct dwarf2_cu *cu, struct dynamic_prop *prop)
+{
+ struct dwarf2_property_baton *baton;
+ struct obstack *obstack = &cu->objfile->objfile_obstack;
+
+ if (attr == NULL || prop == NULL)
+ return 0;
+
+ if (attr_form_is_block (attr))
+ {
+ baton = obstack_alloc (obstack, sizeof (*baton));
+ baton->referenced_type = NULL;
+ baton->locexpr.per_cu = cu->per_cu;
+ baton->locexpr.size = DW_BLOCK (attr)->size;
+ baton->locexpr.data = DW_BLOCK (attr)->data;
+ prop->data.baton = baton;
+ prop->kind = PROP_LOCEXPR;
+ gdb_assert (prop->data.baton != NULL);
+ }
+ else if (attr_form_is_ref (attr))
+ {
+ struct dwarf2_cu *target_cu = cu;
+ struct die_info *target_die;
+ struct attribute *target_attr;
+
+ target_die = follow_die_ref (die, attr, &target_cu);
+ target_attr = dwarf2_attr (target_die, DW_AT_location, target_cu);
+ if (target_attr == NULL)
+ return 0;
+
+ if (attr_form_is_section_offset (target_attr))
+ {
+ baton = obstack_alloc (obstack, sizeof (*baton));
+ baton->referenced_type = die_type (target_die, target_cu);
+ fill_in_loclist_baton (cu, &baton->loclist, target_attr);
+ prop->data.baton = baton;
+ prop->kind = PROP_LOCLIST;
+ gdb_assert (prop->data.baton != NULL);
+ }
+ else if (attr_form_is_block (target_attr))
+ {
+ baton = obstack_alloc (obstack, sizeof (*baton));
+ baton->referenced_type = die_type (target_die, target_cu);
+ baton->locexpr.per_cu = cu->per_cu;
+ baton->locexpr.size = DW_BLOCK (target_attr)->size;
+ baton->locexpr.data = DW_BLOCK (target_attr)->data;
+ prop->data.baton = baton;
+ prop->kind = PROP_LOCEXPR;
+ gdb_assert (prop->data.baton != NULL);
+ }
+ else
+ {
+ dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
+ "dynamic property");
+ return 0;
+ }
+ }
+ else if (attr_form_is_constant (attr))
+ {
+ prop->data.const_val = dwarf2_get_attr_constant_value (attr, 0);
+ prop->kind = PROP_CONST;
+ }
+ else
+ {
+ dwarf2_invalid_attrib_class_complaint (dwarf_form_name (attr->form),
+ dwarf2_name (die, cu));
+ return 0;
+ }
+
+ return 1;
+}
+
/* Read the given DW_AT_subrange DIE. */
static struct type *
struct type *base_type, *orig_base_type;
struct type *range_type;
struct attribute *attr;
- LONGEST low, high;
+ struct dynamic_prop low, high;
int low_default_is_valid;
+ int high_bound_is_count = 0;
const char *name;
LONGEST negative_mask;
if (range_type)
return range_type;
+ low.kind = PROP_CONST;
+ high.kind = PROP_CONST;
+ high.data.const_val = 0;
+
/* Set LOW_DEFAULT_IS_VALID if current language and DWARF version allow
omitting DW_AT_lower_bound. */
switch (cu->language)
{
case language_c:
case language_cplus:
- low = 0;
+ low.data.const_val = 0;
low_default_is_valid = 1;
break;
case language_fortran:
- low = 1;
+ low.data.const_val = 1;
low_default_is_valid = 1;
break;
case language_d:
case language_java:
case language_objc:
- low = 0;
+ low.data.const_val = 0;
low_default_is_valid = (cu->header.version >= 4);
break;
case language_ada:
case language_m2:
case language_pascal:
- low = 1;
+ low.data.const_val = 1;
low_default_is_valid = (cu->header.version >= 4);
break;
default:
- low = 0;
+ low.data.const_val = 0;
low_default_is_valid = 0;
break;
}
- /* FIXME: For variable sized arrays either of these could be
- a variable rather than a constant value. We'll allow it,
- but we don't know how to handle it. */
attr = dwarf2_attr (die, DW_AT_lower_bound, cu);
if (attr)
- low = dwarf2_get_attr_constant_value (attr, low);
+ attr_to_dynamic_prop (attr, die, cu, &low);
else if (!low_default_is_valid)
complaint (&symfile_complaints, _("Missing DW_AT_lower_bound "
"- DIE at 0x%x [in module %s]"),
die->offset.sect_off, objfile_name (cu->objfile));
attr = dwarf2_attr (die, DW_AT_upper_bound, cu);
- if (attr)
- {
- if (attr_form_is_block (attr) || attr_form_is_ref (attr))
- {
- /* GCC encodes arrays with unspecified or dynamic length
- with a DW_FORM_block1 attribute or a reference attribute.
- FIXME: GDB does not yet know how to handle dynamic
- arrays properly, treat them as arrays with unspecified
- length for now.
-
- FIXME: jimb/2003-09-22: GDB does not really know
- how to handle arrays of unspecified length
- either; we just represent them as zero-length
- arrays. Choose an appropriate upper bound given
- the lower bound we've computed above. */
- high = low - 1;
- }
- else
- high = dwarf2_get_attr_constant_value (attr, 1);
- }
- else
+ if (!attr_to_dynamic_prop (attr, die, cu, &high))
{
attr = dwarf2_attr (die, DW_AT_count, cu);
- if (attr)
- {
- int count = dwarf2_get_attr_constant_value (attr, 1);
- high = low + count - 1;
- }
- else
+ if (attr_to_dynamic_prop (attr, die, cu, &high))
{
- /* Unspecified array length. */
- high = low - 1;
+ /* If bounds are constant do the final calculation here. */
+ if (low.kind == PROP_CONST && high.kind == PROP_CONST)
+ high.data.const_val = low.data.const_val + high.data.const_val - 1;
+ else
+ high_bound_is_count = 1;
}
}
the base type is signed. */
negative_mask =
(LONGEST) -1 << (TYPE_LENGTH (base_type) * TARGET_CHAR_BIT - 1);
- if (!TYPE_UNSIGNED (base_type) && (low & negative_mask))
- low |= negative_mask;
- if (!TYPE_UNSIGNED (base_type) && (high & negative_mask))
- high |= negative_mask;
+ if (low.kind == PROP_CONST
+ && !TYPE_UNSIGNED (base_type) && (low.data.const_val & negative_mask))
+ low.data.const_val |= negative_mask;
+ if (high.kind == PROP_CONST
+ && !TYPE_UNSIGNED (base_type) && (high.data.const_val & negative_mask))
+ high.data.const_val |= negative_mask;
- range_type = create_range_type (NULL, orig_base_type, low, high);
+ range_type = create_range_type (NULL, orig_base_type, &low, &high);
- /* Mark arrays with dynamic length at least as an array of unspecified
- length. GDB could check the boundary but before it gets implemented at
- least allow accessing the array elements. */
- if (attr && attr_form_is_block (attr))
- TYPE_HIGH_BOUND_UNDEFINED (range_type) = 1;
+ if (high_bound_is_count)
+ TYPE_RANGE_DATA (range_type)->flag_upper_bound_is_count = 1;
/* Ada expects an empty array on no boundary attributes. */
if (attr == NULL && cu->language != language_ada)
- TYPE_HIGH_BOUND_UNDEFINED (range_type) = 1;
+ TYPE_HIGH_BOUND_KIND (range_type) = PROP_UNDEFINED;
name = dwarf2_name (die, cu);
if (name)
/* 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_unit_groups. */
+ build_type_psymtabs_1. */
static void
abbrev_table_free_cleanup (void *table_ptr)
if (sibling_ptr < info_ptr)
complaint (&symfile_complaints,
_("DW_AT_sibling points backwards"));
+ else if (sibling_ptr > reader->buffer_end)
+ dwarf2_section_buffer_overflow_complaint (reader->die_section);
else
part_die->sibling = sibling_ptr;
}
ULONGEST str_index =
read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
- DW_STRING (attr) = read_str_index (reader, cu, str_index);
+ DW_STRING (attr) = read_str_index (reader, str_index);
DW_STRING_IS_CANONICAL (attr) = 0;
info_ptr += bytes_read;
}
This is only used by the Fission support. */
static const char *
-read_str_index (const struct die_reader_specs *reader,
- struct dwarf2_cu *cu, ULONGEST str_index)
+read_str_index (const struct die_reader_specs *reader, ULONGEST str_index)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
const char *objf_name = objfile_name (objfile);
bfd *abfd = objfile->obfd;
+ struct dwarf2_cu *cu = reader->cu;
struct dwarf2_section_info *str_section = &reader->dwo_file->sections.str;
struct dwarf2_section_info *str_offsets_section =
&reader->dwo_file->sections.str_offsets;
return name;
}
return "";
+ case DW_TAG_enumeration_type:
+ parent_type = read_type_die (parent, cu);
+ if (TYPE_DECLARED_CLASS (parent_type))
+ {
+ if (TYPE_TAG_NAME (parent_type) != NULL)
+ return TYPE_TAG_NAME (parent_type);
+ return "";
+ }
+ /* Fall through. */
default:
return determine_prefix (parent, cu);
}