/* The number of compilation units in ALL_COMP_UNITS. */
int n_comp_units;
+ /* The number of .debug_types-related CUs. */
+ int n_type_comp_units;
+
+ /* The .debug_types-related CUs. */
+ struct dwarf2_per_cu_data **type_comp_units;
+
/* A chain of compilation units that are currently read in, so that
they can be freed later. */
struct dwarf2_per_cu_data *read_in_chain;
static void create_all_comp_units (struct objfile *);
+static int create_debug_types_hash_table (struct objfile *objfile);
+
static void load_full_comp_unit (struct dwarf2_per_cu_data *,
struct objfile *);
static void init_cu_die_reader (struct die_reader_specs *reader,
struct dwarf2_cu *cu);
+static htab_t allocate_signatured_type_hash_table (struct objfile *objfile);
+
#if WORDS_BIGENDIAN
/* Convert VALUE between big- and little-endian. */
return per_cu->v.quick->symtab;
}
+/* Return the CU given its index. */
+static struct dwarf2_per_cu_data *
+dw2_get_cu (int index)
+{
+ if (index >= dwarf2_per_objfile->n_comp_units)
+ {
+ index -= dwarf2_per_objfile->n_comp_units;
+ return dwarf2_per_objfile->type_comp_units[index];
+ }
+ return dwarf2_per_objfile->all_comp_units[index];
+}
+
/* A helper function that knows how to read a 64-bit value in a way
that doesn't make gdb die. Returns 1 if the conversion went ok, 0
otherwise. */
the CU objects for this objfile. Return 0 if something went wrong,
1 if everything went ok. */
static int
-create_cus_from_index (struct objfile *objfile, struct mapped_index *index,
- const gdb_byte *cu_list, offset_type cu_list_elements)
+create_cus_from_index (struct objfile *objfile, const gdb_byte *cu_list,
+ offset_type cu_list_elements)
{
offset_type i;
- const char *entry;
dwarf2_per_objfile->n_comp_units = cu_list_elements / 2;
dwarf2_per_objfile->all_comp_units
return 1;
}
+/* Create the signatured type hash table from the index. */
+static int
+create_signatured_type_hash_from_index (struct objfile *objfile,
+ const gdb_byte *bytes,
+ offset_type elements)
+{
+ offset_type i;
+ htab_t type_hash;
+
+ dwarf2_per_objfile->n_type_comp_units = elements / 3;
+ dwarf2_per_objfile->type_comp_units
+ = obstack_alloc (&objfile->objfile_obstack,
+ dwarf2_per_objfile->n_type_comp_units
+ * sizeof (struct dwarf2_per_cu_data *));
+
+ type_hash = allocate_signatured_type_hash_table (objfile);
+
+ for (i = 0; i < elements; i += 3)
+ {
+ struct signatured_type *type_sig;
+ ULONGEST offset, type_offset, signature;
+ void **slot;
+
+ if (!extract_cu_value (bytes, &offset)
+ || !extract_cu_value (bytes + 8, &type_offset))
+ return 0;
+ signature = extract_unsigned_integer (bytes + 16, 8, BFD_ENDIAN_LITTLE);
+ bytes += 3 * 8;
+
+ type_sig = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct signatured_type);
+ type_sig->signature = signature;
+ type_sig->offset = offset;
+ type_sig->type_offset = type_offset;
+ type_sig->per_cu.from_debug_types = 1;
+ type_sig->per_cu.offset = offset;
+ type_sig->per_cu.objfile = objfile;
+ type_sig->per_cu.v.quick
+ = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct dwarf2_per_cu_quick_data);
+
+ slot = htab_find_slot (type_hash, type_sig, INSERT);
+ *slot = type_sig;
+
+ dwarf2_per_objfile->type_comp_units[i / 3] = &type_sig->per_cu;
+ }
+
+ dwarf2_per_objfile->signatured_types = type_hash;
+
+ return 1;
+}
+
/* Read the address map data from the mapped index, and use it to
populate the objfile's psymtabs_addrmap. */
static void
iter += 4;
addrmap_set_empty (mutable_map, lo + baseaddr, hi + baseaddr - 1,
- dwarf2_per_objfile->all_comp_units[cu_index]);
+ dw2_get_cu (cu_index));
}
objfile->psymtabs_addrmap = addrmap_create_fixed (mutable_map,
char *addr;
struct mapped_index *map;
offset_type *metadata;
- const gdb_byte *cu_list;
- offset_type cu_list_elements;
+ const gdb_byte *cu_list, *types_list;
+ offset_type version, cu_list_elements, types_list_elements;
+ int i;
if (dwarf2_per_objfile->gdb_index.asection == NULL
|| dwarf2_per_objfile->gdb_index.size == 0)
addr = dwarf2_per_objfile->gdb_index.buffer;
/* Version check. */
- if (MAYBE_SWAP (*(offset_type *) addr) != 1)
+ version = MAYBE_SWAP (*(offset_type *) addr);
+ if (version == 1)
+ {
+ /* Index version 1 neglected to account for .debug_types. So,
+ if we see .debug_types, we cannot use this index. */
+ if (dwarf2_per_objfile->types.asection != NULL
+ && dwarf2_per_objfile->types.size != 0)
+ return 0;
+ }
+ else if (version != 2)
return 0;
map = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct mapped_index);
map->total_size = dwarf2_per_objfile->gdb_index.size;
metadata = (offset_type *) (addr + sizeof (offset_type));
- cu_list = addr + MAYBE_SWAP (metadata[0]);
- cu_list_elements = ((MAYBE_SWAP (metadata[1]) - MAYBE_SWAP (metadata[0]))
+
+ i = 0;
+ cu_list = addr + MAYBE_SWAP (metadata[i]);
+ cu_list_elements = ((MAYBE_SWAP (metadata[i + 1]) - MAYBE_SWAP (metadata[i]))
/ 8);
- map->address_table = addr + MAYBE_SWAP (metadata[1]);
- map->address_table_size = (MAYBE_SWAP (metadata[2])
- - MAYBE_SWAP (metadata[1]));
- map->index_table = (offset_type *) (addr + MAYBE_SWAP (metadata[2]));
- map->index_table_slots = ((MAYBE_SWAP (metadata[3])
- - MAYBE_SWAP (metadata[2]))
+ ++i;
+
+ if (version == 2)
+ {
+ types_list = addr + MAYBE_SWAP (metadata[i]);
+ types_list_elements = ((MAYBE_SWAP (metadata[i + 1])
+ - MAYBE_SWAP (metadata[i]))
+ / 8);
+ ++i;
+ }
+
+ map->address_table = addr + MAYBE_SWAP (metadata[i]);
+ map->address_table_size = (MAYBE_SWAP (metadata[i + 1])
+ - MAYBE_SWAP (metadata[i]));
+ ++i;
+
+ map->index_table = (offset_type *) (addr + MAYBE_SWAP (metadata[i]));
+ map->index_table_slots = ((MAYBE_SWAP (metadata[i + 1])
+ - MAYBE_SWAP (metadata[i]))
/ (2 * sizeof (offset_type)));
- map->constant_pool = addr + MAYBE_SWAP (metadata[3]);
+ ++i;
- if (!create_cus_from_index (objfile, map, cu_list, cu_list_elements))
+ map->constant_pool = addr + MAYBE_SWAP (metadata[i]);
+
+ if (!create_cus_from_index (objfile, cu_list, cu_list_elements))
+ return 0;
+
+ if (version == 2
+ && types_list_elements
+ && !create_signatured_type_hash_from_index (objfile, types_list,
+ types_list_elements))
return 0;
create_addrmap_from_index (objfile, map);
int index;
dw2_setup (objfile);
index = dwarf2_per_objfile->n_comp_units - 1;
- return dw2_instantiate_symtab (objfile,
- dwarf2_per_objfile->all_comp_units[index]);
+ return dw2_instantiate_symtab (objfile, dw2_get_cu (index));
}
static void
int i;
dw2_setup (objfile);
- for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+ for (i = 0; i < (dwarf2_per_objfile->n_comp_units
+ + dwarf2_per_objfile->n_type_comp_units); ++i)
{
- struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i];
+ struct dwarf2_per_cu_data *cu = dw2_get_cu (i);
if (cu->v.quick->full_names)
{
struct dwarf2_per_cu_data *base_cu = NULL;
dw2_setup (objfile);
- for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+ for (i = 0; i < (dwarf2_per_objfile->n_comp_units
+ + dwarf2_per_objfile->n_type_comp_units); ++i)
{
int j;
- struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i];
+ struct dwarf2_per_cu_data *cu = dw2_get_cu (i);
if (cu->v.quick->symtab)
continue;
for (i = 0; i < len; ++i)
{
offset_type cu_index = MAYBE_SWAP (vec[i + 1]);
- struct dwarf2_per_cu_data *cu;
- cu = dwarf2_per_objfile->all_comp_units[cu_index];
+ struct dwarf2_per_cu_data *cu = dw2_get_cu (cu_index);
+
dw2_instantiate_symtab (objfile, cu);
}
}
dw2_setup (objfile);
count = 0;
- for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+ for (i = 0; i < (dwarf2_per_objfile->n_comp_units
+ + dwarf2_per_objfile->n_type_comp_units); ++i)
{
- struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i];
+ struct dwarf2_per_cu_data *cu = dw2_get_cu (i);
if (!cu->v.quick->symtab)
++count;
int i;
dw2_setup (objfile);
- for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+
+ for (i = 0; i < (dwarf2_per_objfile->n_comp_units
+ + dwarf2_per_objfile->n_type_comp_units); ++i)
{
- struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i];
+ struct dwarf2_per_cu_data *cu = dw2_get_cu (i);
dw2_instantiate_symtab (objfile, cu);
}
int i;
dw2_setup (objfile);
- for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+ for (i = 0; i < (dwarf2_per_objfile->n_comp_units
+ + dwarf2_per_objfile->n_type_comp_units); ++i)
{
int j;
- struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i];
+ struct dwarf2_per_cu_data *cu = dw2_get_cu (i);
if (cu->v.quick->symtab)
continue;
should be rewritten so that it doesn't require a custom hook. It
could just use the ordinary symbol tables. */
/* vec[0] is the length, which must always be >0. */
- cu = dwarf2_per_objfile->all_comp_units[MAYBE_SWAP (vec[1])];
+ cu = dw2_get_cu (MAYBE_SWAP (vec[1]));
dw2_require_line_header (objfile, cu);
if (!cu->v.quick->lines)
if (!dwarf2_per_objfile->index_table)
return;
- for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+ for (i = 0; i < (dwarf2_per_objfile->n_comp_units
+ + dwarf2_per_objfile->n_type_comp_units); ++i)
{
int j;
- struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i];
+ struct dwarf2_per_cu_data *cu = dw2_get_cu (i);
cu->v.quick->mark = 0;
if (cu->v.quick->symtab)
vec_len = MAYBE_SWAP (vec[0]);
for (vec_idx = 0; vec_idx < vec_len; ++vec_idx)
{
- struct dwarf2_per_cu_data *cu
- = dwarf2_per_objfile->all_comp_units[MAYBE_SWAP (vec[vec_idx + 1])];
+ struct dwarf2_per_cu_data *cu;
+
+ cu = dw2_get_cu (MAYBE_SWAP (vec[vec_idx + 1]));
if (cu->v.quick->mark)
dw2_instantiate_symtab (objfile, cu);
}
int i;
dw2_setup (objfile);
- for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+ for (i = 0; i < (dwarf2_per_objfile->n_comp_units
+ + dwarf2_per_objfile->n_type_comp_units); ++i)
{
int j;
- struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i];
+ struct dwarf2_per_cu_data *cu = dw2_get_cu (i);
if (cu->v.quick->symtab)
continue;
dwarf2_per_objfile->using_index = 1;
create_all_comp_units (objfile);
+ create_debug_types_hash_table (objfile);
- for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+ for (i = 0; i < (dwarf2_per_objfile->n_comp_units
+ + dwarf2_per_objfile->n_type_comp_units); ++i)
{
- struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i];
+ struct dwarf2_per_cu_data *cu = dw2_get_cu (i);
cu->v.quick = OBSTACK_ZALLOC (&objfile->objfile_obstack,
struct dwarf2_per_cu_quick_data);
return lhs->signature == rhs->signature;
}
+/* Allocate a hash table for signatured types. */
+
+static htab_t
+allocate_signatured_type_hash_table (struct objfile *objfile)
+{
+ return htab_create_alloc_ex (41,
+ hash_type_signature,
+ eq_type_signature,
+ NULL,
+ &objfile->objfile_obstack,
+ hashtab_obstack_allocate,
+ dummy_obstack_deallocate);
+}
+
+/* A helper function to add a signatured type CU to a list. */
+
+static int
+add_signatured_type_cu_to_list (void **slot, void *datum)
+{
+ struct signatured_type *sigt = *slot;
+ struct dwarf2_per_cu_data ***datap = datum;
+
+ **datap = &sigt->per_cu;
+ ++*datap;
+
+ return 1;
+}
+
/* Create the hash table of all entries in the .debug_types section.
The result is zero if there is an error (e.g. missing .debug_types section),
otherwise non-zero. */
{
gdb_byte *info_ptr;
htab_t types_htab;
+ struct dwarf2_per_cu_data **iter;
dwarf2_read_section (objfile, &dwarf2_per_objfile->types);
info_ptr = dwarf2_per_objfile->types.buffer;
return 0;
}
- types_htab = htab_create_alloc_ex (41,
- hash_type_signature,
- eq_type_signature,
- NULL,
- &objfile->objfile_obstack,
- hashtab_obstack_allocate,
- dummy_obstack_deallocate);
+ types_htab = allocate_signatured_type_hash_table (objfile);
if (dwarf2_die_debug)
fprintf_unfiltered (gdb_stdlog, "Signatured types:\n");
type_sig->offset = offset;
type_sig->type_offset = type_offset;
type_sig->per_cu.objfile = objfile;
+ type_sig->per_cu.from_debug_types = 1;
slot = htab_find_slot (types_htab, type_sig, INSERT);
gdb_assert (slot != NULL);
dwarf2_per_objfile->signatured_types = types_htab;
+ dwarf2_per_objfile->n_type_comp_units = htab_elements (types_htab);
+ dwarf2_per_objfile->type_comp_units
+ = obstack_alloc (&objfile->objfile_obstack,
+ dwarf2_per_objfile->n_type_comp_units
+ * sizeof (struct dwarf2_per_cu_data *));
+ iter = &dwarf2_per_objfile->type_comp_units[0];
+ htab_traverse_noresize (types_htab, add_signatured_type_cu_to_list, &iter);
+ gdb_assert (iter - &dwarf2_per_objfile->type_comp_units[0]
+ == dwarf2_per_objfile->n_type_comp_units);
+
return 1;
}
struct dwarf2_per_cu_data *this_cu;
this_cu = &entry->per_cu;
- this_cu->from_debug_types = 1;
gdb_assert (dwarf2_per_objfile->types.readin);
process_psymtab_comp_unit (objfile, this_cu,
read_signatured_type (struct objfile *objfile,
struct signatured_type *type_sig)
{
- gdb_byte *types_ptr = dwarf2_per_objfile->types.buffer + type_sig->offset;
+ gdb_byte *types_ptr;
struct die_reader_specs reader_specs;
struct dwarf2_cu *cu;
ULONGEST signature;
struct cleanup *back_to, *free_cu_cleanup;
struct attribute *attr;
+ dwarf2_read_section (objfile, &dwarf2_per_objfile->types);
+ types_ptr = dwarf2_per_objfile->types.buffer + type_sig->offset;
+
gdb_assert (type_sig->per_cu.cu == NULL);
cu = xmalloc (sizeof (struct dwarf2_cu));
char addr[8];
CORE_ADDR baseaddr;
+ /* Don't bother recording empty ranges. */
+ if (pst->textlow == pst->texthigh)
+ return;
+
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
store_unsigned_integer (addr, 8, BFD_ENDIAN_LITTLE, pst->textlow - baseaddr);
unlink (*filename);
}
+/* A helper struct used when iterating over debug_types. */
+struct signatured_type_index_data
+{
+ struct objfile *objfile;
+ struct mapped_symtab *symtab;
+ struct obstack *types_list;
+ int cu_index;
+};
+
+/* A helper function that writes a single signatured_type to an
+ obstack. */
+static int
+write_one_signatured_type (void **slot, void *d)
+{
+ struct signatured_type_index_data *info = d;
+ struct signatured_type *entry = (struct signatured_type *) *slot;
+ struct dwarf2_per_cu_data *cu = &entry->per_cu;
+ struct partial_symtab *psymtab = cu->v.psymtab;
+ gdb_byte val[8];
+
+ write_psymbols (info->symtab,
+ info->objfile->global_psymbols.list + psymtab->globals_offset,
+ psymtab->n_global_syms, info->cu_index);
+ write_psymbols (info->symtab,
+ info->objfile->static_psymbols.list + psymtab->statics_offset,
+ psymtab->n_static_syms, info->cu_index);
+
+ store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, entry->offset);
+ obstack_grow (info->types_list, val, 8);
+ store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, entry->type_offset);
+ obstack_grow (info->types_list, val, 8);
+ store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, entry->signature);
+ obstack_grow (info->types_list, val, 8);
+
+ ++info->cu_index;
+
+ return 1;
+}
+
/* Create an index file for OBJFILE in the directory DIR. */
static void
write_psymtabs_to_index (struct objfile *objfile, const char *dir)
{
struct cleanup *cleanup;
char *filename, *cleanup_filename;
- struct obstack contents, addr_obstack, constant_pool, symtab_obstack, cu_list;
+ struct obstack contents, addr_obstack, constant_pool, symtab_obstack;
+ struct obstack cu_list, types_cu_list;
int i;
FILE *out_file;
struct mapped_symtab *symtab;
obstack_init (&cu_list);
make_cleanup_obstack_free (&cu_list);
+ obstack_init (&types_cu_list);
+ make_cleanup_obstack_free (&types_cu_list);
+
+ /* The list is already sorted, so we don't need to do additional
+ work here. Also, the debug_types entries do not appear in
+ all_comp_units, but only in their own hash table. */
for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i];
obstack_grow (&cu_list, val, 8);
}
+ /* Write out the .debug_type entries, if any. */
+ if (dwarf2_per_objfile->signatured_types)
+ {
+ struct signatured_type_index_data sig_data;
+
+ sig_data.objfile = objfile;
+ sig_data.symtab = symtab;
+ sig_data.types_list = &types_cu_list;
+ sig_data.cu_index = dwarf2_per_objfile->n_comp_units;
+ htab_traverse_noresize (dwarf2_per_objfile->signatured_types,
+ write_one_signatured_type, &sig_data);
+ }
+
obstack_init (&constant_pool);
make_cleanup_obstack_free (&constant_pool);
obstack_init (&symtab_obstack);
obstack_init (&contents);
make_cleanup_obstack_free (&contents);
- size_of_contents = 5 * sizeof (offset_type);
+ size_of_contents = 6 * sizeof (offset_type);
total_len = size_of_contents;
/* The version number. */
- val = MAYBE_SWAP (1);
+ val = MAYBE_SWAP (2);
obstack_grow (&contents, &val, sizeof (val));
/* The offset of the CU list from the start of the file. */
obstack_grow (&contents, &val, sizeof (val));
total_len += obstack_object_size (&cu_list);
+ /* The offset of the types CU list from the start of the file. */
+ val = MAYBE_SWAP (total_len);
+ obstack_grow (&contents, &val, sizeof (val));
+ total_len += obstack_object_size (&types_cu_list);
+
/* The offset of the address table from the start of the file. */
val = MAYBE_SWAP (total_len);
obstack_grow (&contents, &val, sizeof (val));
write_obstack (out_file, &contents);
write_obstack (out_file, &cu_list);
+ write_obstack (out_file, &types_cu_list);
write_obstack (out_file, &addr_obstack);
write_obstack (out_file, &symtab_obstack);
write_obstack (out_file, &constant_pool);
1. The file header. This is a sequence of values, of offset_type
unless otherwise noted:
- [0] The version number. Currently 1.
+ [0] The version number. Currently 1 or 2. The differences are
+ noted below. Version 1 did not account for .debug_types sections;
+ the presence of a .debug_types section invalidates any version 1
+ index that may exist.
[1] The offset, from the start of the file, of the CU list.
+ [1.5] In version 2, the offset, from the start of the file, of the
+ types CU list. This offset does not appear in version 1. Note
+ that this can be empty, in which case this offset will be equal to
+ the next offset.
[2] The offset, from the start of the file, of the address section.
[3] The offset, from the start of the file, of the symbol table.
[4] The offset, from the start of the file, of the constant pool.
2. The CU list. This is a sequence of pairs of 64-bit
- little-endian values. The first element in each pair is the offset
- of a CU in the .debug_info section. The second element in each
- pair is the length of that CU. References to a CU elsewhere in the
- map are done using a CU index, which is just the 0-based index into
- this table.
+ little-endian values, sorted by the CU offset. The first element
+ in each pair is the offset of a CU in the .debug_info section. The
+ second element in each pair is the length of that CU. References
+ to a CU elsewhere in the map are done using a CU index, which is
+ just the 0-based index into this table. Note that if there are
+ type CUs, then conceptually CUs and type CUs form a single list for
+ the purposes of CU indices.
+
+ 2.5 The types CU list. This does not appear in a version 1 index.
+ This is a sequence of triplets of 64-bit little-endian values. In
+ a triplet, the first value is the CU offset, the second value is
+ the type offset in the CU, and the third value is the type
+ signature. The types CU list is not sorted.
3. The address section. The address section consists of a sequence
of address entries. Each address entry has three elements.