Re: [RFA, doc RFA] Work around binutils/15021

Doug Evans
2013-01-17T21:04:57Z

Tom Tromey writes:
> >>>>> "Doug" == Doug Evans <dje@google.com> writes:
>
> Doug> Regression tested with gdb-generated .gdb_index version 7 (by hacking the
> Doug> gdb-under-test to generate version 7), version 8, with dwz, and with gold.
>
> I think index version bumps require a documentation update and also a
> binutils patch.
>
> Doug> Work around binutils/15021
>
> IIUC, the version bump is part of the workaround for the gold bug,
> right? The idea being that gold will generate version 7 indices,
> causing gdb to take the "inclusion" path. (I'm just trying to make sure
> I understand what is going on.)
>
> Doug> + This is also used to work around a difference between the way gold
> Doug> + generates .gdb_index version <=7 and the way gdb does. Arguably this
> Doug> + is a gold bug.
>
> To me it doesn't seem arguable, but I'm curious to know what the case is
> for it not being a gold bug.
>
> Doug> @@ -19634,7 +19660,7 @@ dwarf2_per_objfile_free (struct objfile
>
> Doug> for (ix = 0; ix < dwarf2_per_objfile->n_comp_units; ++ix)
> Doug> VEC_free (dwarf2_per_cu_ptr,
> Doug> - dwarf2_per_objfile->all_comp_units[ix]->s.imported_symtabs);
> Doug> + dwarf2_per_objfile->all_comp_units[ix]->imported_symtabs);
>
> If follow_die_sig can be called when one TU refers to another TU, then
> it seems like the TU could have a non-empty 'imported_symtabs', meaning
> that the loop here should also iterate over TUs.

How's this?

Eli, this has a doc change.

2013-01-17 Doug Evans <dje@google.com>

Work around binutils/15021
* dwarf2read.c (dwarf2_per_cu_data): Split imported_symtabs and
type_unit_group out of union s. All uses updated.
(read_index_from_section): Watch for index version 8.
(follow_die_sig): If using .gdb_index version <= 7, record the TU as
an imported symtab.
(write_psymtabs_to_index): Increment version number to 8.

doc/
* gdb.texinfo (Index Section Format): Document .gdb_index version 8.

Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.731
diff -u -p -r1.731 dwarf2read.c
--- dwarf2read.c 15 Jan 2013 21:32:36 -0000 1.731
+++ dwarf2read.c 17 Jan 2013 20:57:32 -0000
@@ -566,19 +566,29 @@ struct dwarf2_per_cu_data
struct dwarf2_per_cu_quick_data *quick;
} v;

- union
- {
- /* The CUs we import using DW_TAG_imported_unit. This is filled in
- while reading psymtabs, used to compute the psymtab dependencies,
- and then cleared. Then it is filled in again while reading full
- symbols, and only deleted when the objfile is destroyed. */
- VEC (dwarf2_per_cu_ptr) *imported_symtabs;
-
- /* Type units are grouped by their DW_AT_stmt_list entry so that they
- can share them. If this is a TU, this points to the containing
- symtab. */
- struct type_unit_group *type_unit_group;
- } s;
+ /* The CUs we import using DW_TAG_imported_unit. This is filled in
+ while reading psymtabs, used to compute the psymtab dependencies,
+ and then cleared. Then it is filled in again while reading full
+ symbols, and only deleted when the objfile is destroyed.
+
+ This is also used to work around a difference between the way gold
+ generates .gdb_index version <=7 and the way gdb does. Arguably this
+ is a gold bug. For symbols coming from TUs, gold records in the index
+ the CU that includes the TU instead of the TU itself. This breaks
+ dw2_lookup_symbol: It assumes that if the index says symbol X lives
+ in CU/TU Y, then one need only expand Y and a subsequent lookup in Y
+ will find X. Alas TUs live in their own symtab, so after expanding CU Y
+ we need to look in TU Z to find X. Fortunately, this is akin to
+ DW_TAG_imported_unit, so we just use the same mechanism: For
+ .gdb_index version <=7 this also records the TUs that the CU referred
+ to. Concurrently with this change gdb was modified to emit version 8
+ indices so we only pay a price for gold generated indices. */
+ VEC (dwarf2_per_cu_ptr) *imported_symtabs;
+
+ /* Type units are grouped by their DW_AT_stmt_list entry so that they
+ can share them. If this is a TU, this points to the containing
+ symtab. */
+ struct type_unit_group *type_unit_group;
};

/* Entry in the signatured_types hash table. */
@@ -2690,9 +2700,14 @@ to use the section anyway."),
}
return 0;
}
+ /* Version 7 indices generated by gold refer to the CU for a symbol instead
+ of the TU (for symbols coming from TUs). It's just a performance bug, and
+ we can't distinguish gdb-generated indices from gold-generated ones, so
+ nothing to do here. */
+
/* Indexes with higher version than the one supported by GDB may be no
longer backward compatible. */
- if (version > 7)
+ if (version > 8)
return 0;

map->version = version;
@@ -2963,7 +2978,7 @@ dw2_get_file_names (struct objfile *objf
DWO file. */
if (this_cu->is_debug_types)
{
- struct type_unit_group *tu_group = this_cu->s.type_unit_group;
+ struct type_unit_group *tu_group = this_cu->type_unit_group;

init_cutu_and_read_dies (tu_group->t.first_tu, NULL, 0, 0,
dw2_get_file_names_reader, tu_group);
@@ -4994,10 +5009,10 @@ process_psymtab_comp_unit_reader (const
(objfile->static_psymbols.list + pst->statics_offset);
sort_pst_symbols (objfile, pst);

- if (!VEC_empty (dwarf2_per_cu_ptr, cu->per_cu->s.imported_symtabs))
+ if (!VEC_empty (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs))
{
int i;
- int len = VEC_length (dwarf2_per_cu_ptr, cu->per_cu->s.imported_symtabs);
+ int len = VEC_length (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs);
struct dwarf2_per_cu_data *iter;

/* Fill in 'dependencies' here; we fill in 'users' in a
@@ -5006,12 +5021,12 @@ process_psymtab_comp_unit_reader (const
pst->dependencies = obstack_alloc (&objfile->objfile_obstack,
len * sizeof (struct symtab *));
for (i = 0;
- VEC_iterate (dwarf2_per_cu_ptr, cu->per_cu->s.imported_symtabs,
+ VEC_iterate (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs,
i, iter);
++i)
pst->dependencies[i] = iter->v.psymtab;

- VEC_free (dwarf2_per_cu_ptr, cu->per_cu->s.imported_symtabs);
+ VEC_free (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs);
}

/* Get the list of files included in the current compilation unit,
@@ -5109,7 +5124,7 @@ create_type_unit_group (struct dwarf2_cu
per_cu = &tu_group->per_cu;
per_cu->objfile = objfile;
per_cu->is_debug_types = 1;
- per_cu->s.type_unit_group = tu_group;
+ per_cu->type_unit_group = tu_group;

if (dwarf2_per_objfile->using_index)
{
@@ -5446,7 +5461,7 @@ build_type_psymtab_dependencies (void **
++i)
{
pst->dependencies[i] = iter->v.psymtab;
- iter->s.type_unit_group = tu_group;
+ iter->type_unit_group = tu_group;
}

VEC_free (dwarf2_per_cu_ptr, tu_group->t.tus);
@@ -5767,7 +5782,7 @@ scan_partial_symbols (struct partial_die
process_psymtab_comp_unit (per_cu, 1);

VEC_safe_push (dwarf2_per_cu_ptr,
- cu->per_cu->s.imported_symtabs, per_cu);
+ cu->per_cu->imported_symtabs, per_cu);
}
break;
default:
@@ -6899,7 +6914,7 @@ recursively_compute_inclusions (VEC (dwa
VEC_safe_push (dwarf2_per_cu_ptr, *result, per_cu);

for (ix = 0;
- VEC_iterate (dwarf2_per_cu_ptr, per_cu->s.imported_symtabs, ix, iter);
+ VEC_iterate (dwarf2_per_cu_ptr, per_cu->imported_symtabs, ix, iter);
++ix)
recursively_compute_inclusions (result, all_children, iter);
}
@@ -6912,7 +6927,7 @@ compute_symtab_includes (struct dwarf2_p
{
gdb_assert (! per_cu->is_debug_types);

- if (!VEC_empty (dwarf2_per_cu_ptr, per_cu->s.imported_symtabs))
+ if (!VEC_empty (dwarf2_per_cu_ptr, per_cu->imported_symtabs))
{
int ix, len;
struct dwarf2_per_cu_data *iter;
@@ -6928,13 +6943,14 @@ compute_symtab_includes (struct dwarf2_p
NULL, xcalloc, xfree);

for (ix = 0;
- VEC_iterate (dwarf2_per_cu_ptr, per_cu->s.imported_symtabs,
+ VEC_iterate (dwarf2_per_cu_ptr, per_cu->imported_symtabs,
ix, iter);
++ix)
recursively_compute_inclusions (&result_children, all_children, iter);

- /* Now we have a transitive closure of all the included CUs, so
- we can convert it to a list of symtabs. */
+ /* Now we have a transitive closure of all the included CUs, and
+ for .gdb_index version 7 the included TUs, so we can convert it
+ to a list of symtabs. */
len = VEC_length (dwarf2_per_cu_ptr, result_children);
symtab->includes
= obstack_alloc (&dwarf2_per_objfile->objfile->objfile_obstack,
@@ -7017,7 +7033,7 @@ process_full_comp_unit (struct dwarf2_pe

static_block
= end_symtab_get_static_block (highpc + baseaddr, objfile, 0,
- per_cu->s.imported_symtabs != NULL);
+ per_cu->imported_symtabs != NULL);

/* If the comp unit has DW_AT_ranges, it may have discontiguous ranges.
Also, DW_AT_ranges may record ranges not belonging to any child DIEs
@@ -7113,10 +7129,10 @@ process_full_type_unit (struct dwarf2_pe
If this is the first TU to use this symtab, complete the construction
of it with end_expandable_symtab. Otherwise, complete the addition of
this TU's symbols to the existing symtab. */
- if (per_cu->s.type_unit_group->primary_symtab == NULL)
+ if (per_cu->type_unit_group->primary_symtab == NULL)
{
symtab = end_expandable_symtab (0, objfile, SECT_OFF_TEXT (objfile));
- per_cu->s.type_unit_group->primary_symtab = symtab;
+ per_cu->type_unit_group->primary_symtab = symtab;

if (symtab != NULL)
{
@@ -7131,8 +7147,8 @@ process_full_type_unit (struct dwarf2_pe
else
{
augment_type_symtab (objfile,
- per_cu->s.type_unit_group->primary_symtab);
- symtab = per_cu->s.type_unit_group->primary_symtab;
+ per_cu->type_unit_group->primary_symtab);
+ symtab = per_cu->type_unit_group->primary_symtab;
}

if (dwarf2_per_objfile->using_index)
@@ -7178,7 +7194,7 @@ process_imported_unit_die (struct die_in
if (maybe_queue_comp_unit (cu, per_cu, cu->language))
load_full_comp_unit (per_cu, cu->language);

- VEC_safe_push (dwarf2_per_cu_ptr, cu->per_cu->s.imported_symtabs,
+ VEC_safe_push (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs,
per_cu);
}
}
@@ -8067,9 +8083,9 @@ setup_type_unit_groups (struct die_info

/* If we're using .gdb_index (includes -readnow) then
per_cu->s.type_unit_group may not have been set up yet. */
- if (per_cu->s.type_unit_group == NULL)
- per_cu->s.type_unit_group = get_type_unit_group (cu, attr);
- tu_group = per_cu->s.type_unit_group;
+ if (per_cu->type_unit_group == NULL)
+ per_cu->type_unit_group = get_type_unit_group (cu, attr);
+ tu_group = per_cu->type_unit_group;

/* If we've already processed this stmt_list there's no real need to
do it again, we could fake it and just recreate the part we need
@@ -17620,6 +17636,16 @@ follow_die_sig (struct die_info *src_die
temp_die.offset.sect_off);
if (die)
{
+ /* For .gdb_index version 7 keep track of included TUs.
+ http://sourceware.org/bugzilla/show_bug.cgi?id=15021. */
+ if (dwarf2_per_objfile->index_table != NULL
+ && dwarf2_per_objfile->index_table->version <= 7)
+ {
+ VEC_safe_push (dwarf2_per_cu_ptr,
+ (*ref_cu)->per_cu->imported_symtabs,
+ sig_cu->per_cu);
+ }
+
*ref_cu = sig_cu;
return die;
}
@@ -19670,7 +19696,11 @@ dwarf2_per_objfile_free (struct objfile

for (ix = 0; ix < dwarf2_per_objfile->n_comp_units; ++ix)
VEC_free (dwarf2_per_cu_ptr,
- dwarf2_per_objfile->all_comp_units[ix]->s.imported_symtabs);
+ dwarf2_per_objfile->all_comp_units[ix]->imported_symtabs);
+
+ for (ix = 0; ix < dwarf2_per_objfile->n_type_units; ++ix)
+ VEC_free (dwarf2_per_cu_ptr,
+ dwarf2_per_objfile->all_type_units[ix]->per_cu.imported_symtabs);

VEC_free (dwarf2_section_info_def, data->types);

@@ -20492,7 +20522,7 @@ write_psymtabs_to_index (struct objfile
total_len = size_of_contents;

/* The version number. */
- val = MAYBE_SWAP (7);
+ val = MAYBE_SWAP (8);
obstack_grow (&contents, &val, sizeof (val));

/* The offset of the CU list from the start of the file. */
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.1042
diff -u -p -r1.1042 gdb.texinfo
--- doc/gdb.texinfo 16 Jan 2013 17:31:39 -0000 1.1042
+++ doc/gdb.texinfo 17 Jan 2013 20:57:33 -0000
@@ -41031,12 +41031,18 @@ unless otherwise noted:

@enumerate
@item
-The version number, currently 7. Versions 1, 2 and 3 are obsolete.
+The version number, currently 8. Versions 1, 2 and 3 are obsolete.
Version 4 uses a different hashing function from versions 5 and 6.
Version 6 includes symbols for inlined functions, whereas versions 4
and 5 do not. Version 7 adds attributes to the CU indices in the
-symbol table. @value{GDBN} will only read version 4, 5, or 6 indices
+symbol table. Version 8 specifies that symbols from DWARF type units
+(@samp{DW_TAG_type_unit}) refer to the type unit's symbol table and not the
+compilation unit (@samp{DW_TAG_comp_unit}) using the type.
+
+@value{GDBN} will only read version 4, 5, or 6 indices
by specifying @code{set use-deprecated-index-sections on}.
+GDB has a workaround for potentially broken version 7 indices so it is
+currently not flagged as deprecated.

@item
The offset, from the start of the file, of the CU list.