Re: [0/4] RFC: add DWARF index support

Tom Tromey
2010-07-22T20:54:12Z

Tom> The bigger problem is that I completely forgot about .debug_types.
Tom> I am not certain that a simple fix will work if we have both
Tom> .debug_types and .gdb_index. I will try that out.

Tom> I think this is going to need an index version bump.
Tom> I am still looking into it.

Here is what I am testing.

This also fixes a bug in dwarf2_initialize_objfile that prevents
-readnow from working when .debug_types exists. If necessary this can
be fixed separately, though such a fix would have to be backed out when
this patch goes in.

I bumped the index version number because I believe we've built some
version 1 indices in the Fedora buildroots already.

Tom

2010-07-22 Tom Tromey <tromey@redhat.com>

* dwarf2read.c (dwarf2_per_cu_data_ptr): Remove.
(struct dwarf2_per_objfile) <n_type_comp_units, type_comp_units>:
New fields.
(dw2_get_cu): New function.
(create_cus_from_index): Remove unused argument.
(create_signatured_type_hash_from_index): New function.
(create_addrmap_from_index): Update.
(dwarf2_read_index): Handle version 2.
(dw2_find_last_source_symtab, dw2_forget_cached_source_info)
(dw2_lookup_symtab, dw2_do_expand_symtabs_matching)
(dw2_print_stats, dw2_expand_all_symtabs)
(dw2_expand_symtabs_with_filename, dw2_find_symbol_file)
(dw2_expand_symtabs_matching, dw2_map_symbol_filenames): Update.
(dwarf2_initialize_objfile): Call create_debug_types_hash_table.
(allocate_signatured_type_hash_table): New function.
(add_signatured_type_cu_to_list): Likewise.
(create_debug_types_hash_table): Use them. Set type_comp_units.
(read_signatured_type): Ensure section data is available.
(add_address_entry): Don't record empty ranges.
(struct signatured_type_index_data): New.
(write_one_signatured_type): New function.
(write_psymtabs_to_index): Write type CUs.
(save_gdb_index_command): Update comment.

diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 8084f42..7ab18e4 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -155,9 +155,6 @@ struct mapped_index
const char *constant_pool;
};

-typedef struct dwarf2_per_cu_data *dwarf2_per_cu_data_ptr;
-DEF_VEC_P (dwarf2_per_cu_data_ptr);
-
struct dwarf2_per_objfile
{
struct dwarf2_section_info info;
@@ -182,6 +179,12 @@ struct dwarf2_per_objfile
/* 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;
@@ -1192,6 +1195,8 @@ static struct type *set_die_type (struct die_info *, struct type *,

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 *);

@@ -1229,6 +1234,8 @@ static gdb_byte *partial_read_comp_unit_head (struct comp_unit_head *header,
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. */
@@ -1605,6 +1612,18 @@ dw2_instantiate_symtab (struct objfile *objfile,
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. */
@@ -1631,11 +1650,10 @@ extract_cu_value (const char *bytes, ULONGEST *result)
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
@@ -1666,6 +1684,58 @@ create_cus_from_index (struct objfile *objfile, struct mapped_index *index,
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
@@ -1697,7 +1767,7 @@ create_addrmap_from_index (struct objfile *objfile, struct mapped_index *index)
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,
@@ -1767,8 +1837,9 @@ dwarf2_read_index (struct objfile *objfile)
struct mapped_index *map;
offset_type val, *metadata;
char buf1[8], buf2[8];
- 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)
@@ -1777,26 +1848,58 @@ dwarf2_read_index (struct objfile *objfile)

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 = st.st_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;
+
+ map->constant_pool = addr + MAYBE_SWAP (metadata[i]);

- if (!create_cus_from_index (objfile, map, cu_list, cu_list_elements))
+ 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);
@@ -1923,8 +2026,7 @@ dw2_find_last_source_symtab (struct objfile *objfile)
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
@@ -1933,9 +2035,10 @@ dw2_forget_cached_source_info (struct objfile *objfile)
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)
{
@@ -1957,10 +2060,11 @@ dw2_lookup_symtab (struct objfile *objfile, const char *name,
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;
@@ -2052,8 +2156,8 @@ dw2_do_expand_symtabs_matching (struct objfile *objfile, const char *name)
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);
}
}
@@ -2075,9 +2179,10 @@ dw2_print_stats (struct objfile *objfile)

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;
@@ -2111,9 +2216,11 @@ dw2_expand_all_symtabs (struct objfile *objfile)
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);
}
@@ -2126,10 +2233,11 @@ dw2_expand_symtabs_with_filename (struct objfile *objfile,
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;
@@ -2170,7 +2278,7 @@ dw2_find_symbol_file (struct objfile *objfile, const char *name)
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)
@@ -2209,10 +2317,11 @@ dw2_expand_symtabs_matching (struct objfile *objfile,
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)
@@ -2257,8 +2366,9 @@ dw2_expand_symtabs_matching (struct objfile *objfile,
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);
}
@@ -2328,10 +2438,11 @@ dw2_map_symbol_filenames (struct objfile *objfile,
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;
@@ -2392,10 +2503,12 @@ dwarf2_initialize_objfile (struct objfile *objfile)

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);
@@ -2609,6 +2722,34 @@ eq_type_signature (const void *item_lhs, const void *item_rhs)
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. */
@@ -2618,6 +2759,7 @@ create_debug_types_hash_table (struct objfile *objfile)
{
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;
@@ -2628,13 +2770,7 @@ create_debug_types_hash_table (struct objfile *objfile)
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");
@@ -2695,6 +2831,16 @@ create_debug_types_hash_table (struct objfile *objfile)

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;
}

@@ -12051,13 +12197,16 @@ static void
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));
@@ -13881,6 +14030,10 @@ add_address_entry (struct objfile *objfile,
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);
@@ -13926,13 +14079,53 @@ unlink_if_set (void *p)
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;
@@ -13968,6 +14161,12 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
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];
@@ -13989,6 +14188,19 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
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);
@@ -13997,11 +14209,11 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)

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. */
@@ -14009,6 +14221,11 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
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));
@@ -14028,6 +14245,7 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)

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);
@@ -14052,18 +14270,33 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)

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 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.