aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2021-01-20 18:51:04 +0100
committerJakub Jelinek <jakub@redhat.com>2021-01-20 18:51:04 +0100
commit27c792895bd809115c1f70672835b7fdff74d318 (patch)
tree0c439950e4d1b271eecdf318125c5ca67ab07cc4 /gcc
parent4334b524274203125193a08a8485250c41c2daa9 (diff)
downloadgcc-27c792895bd809115c1f70672835b7fdff74d318.zip
gcc-27c792895bd809115c1f70672835b7fdff74d318.tar.gz
gcc-27c792895bd809115c1f70672835b7fdff74d318.tar.bz2
debug: Fix up DWARF 5 -g -flto -ffat-lto-objects [PR98765]
As mentioned in the PR, with -gdwarf-5 (or -g now) -flto -ffat-lto-objects, users can't strip the LTO sections with strip -p -R .gnu.lto_* -R .gnu.debuglto_* -N __gnu_lto_v1 anymore when GCC is configured against recent binutils. The problem is that in that case .gnu.debuglto_.debug_line_str section is then used, which is fine for references to strings in .gnu.debuglto_.* sections, but not when those references are in .debug_info section too; those should really reference separate strings in .debug_line_str section. For .gnu.debuglto_.debug_str vs. .debug_str we handle it right, we reset_indirect_string the strings and thus force creation of new labels for the second time. But for DW_FORM_line_strp as the patch shows, there were multiple problems. First one was that reset_indirect_string, even when called through traverse on debug_line_str_hash, didn't do anything at all (fixed by first hunk). The second bug was that the DW_FORM_line_strp strings, which were supposed to be only visible through debug_line_str_hash, leaked into debug_str_hash (second hunk). And the third thing is that when we reset debug_line_str_hash, we should still make those strings DW_FORM_line_strp if they are accessed. One could do it by reinstantiating DW_FORM_line_strp right away in reset_indirect_string and not clear debug_line_str_hash, but that has the disadvantage that we then force emitting .debug_line_str strings that aren't really needed - we need those from the CU DIEs' DW_AT_name and DW_AT_comp_dir attributes, but when emitting .debug_line section through assembler, we don't need to emit the strings we only needed for .gnu.debuglto_.debug_line which is always emitted by the compiler. 2021-01-20 Jakub Jelinek <jakub@redhat.com> PR debug/98765 * dwarf2out.c (reset_indirect_string): Also reset indirect strings with DW_FORM_line_strp form. (prune_unused_types_update_strings): Don't add into debug_str_hash indirect strings with DW_FORM_line_strp form. (adjust_name_comp_dir): New function. (dwarf2out_finish): Call it on CU DIEs after resetting debug_line_str_hash.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/dwarf2out.c42
1 files changed, 39 insertions, 3 deletions
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 93e5d15..77ea494 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -4733,7 +4733,9 @@ int
reset_indirect_string (indirect_string_node **h, void *)
{
struct indirect_string_node *node = *h;
- if (node->form == DW_FORM_strp || node->form == dwarf_FORM (DW_FORM_strx))
+ if (node->form == DW_FORM_strp
+ || node->form == DW_FORM_line_strp
+ || node->form == dwarf_FORM (DW_FORM_strx))
{
free (node->label);
node->label = NULL;
@@ -29477,8 +29479,9 @@ prune_unused_types_update_strings (dw_die_ref die)
s->refcount++;
/* Avoid unnecessarily putting strings that are used less than
twice in the hash table. */
- if (s->refcount
- == ((DEBUG_STR_SECTION_FLAGS & SECTION_MERGE) ? 1 : 2))
+ if (s->form != DW_FORM_line_strp
+ && (s->refcount
+ == ((DEBUG_STR_SECTION_FLAGS & SECTION_MERGE) ? 1 : 2)))
{
indirect_string_node **slot
= debug_str_hash->find_slot_with_hash (s->str,
@@ -31325,6 +31328,33 @@ reset_dies (dw_die_ref die)
FOR_EACH_CHILD (die, c, reset_dies (c));
}
+/* reset_indirect_string removed the references coming from DW_AT_name
+ and DW_AT_comp_dir attributes on compilation unit DIEs. Readd them as
+ .debug_line_str strings again. */
+
+static void
+adjust_name_comp_dir (dw_die_ref die)
+{
+ for (int i = 0; i < 2; i++)
+ {
+ dwarf_attribute attr_kind = i ? DW_AT_comp_dir : DW_AT_name;
+ dw_attr_node *a = get_AT (die, attr_kind);
+ if (a == NULL || a->dw_attr_val.val_class != dw_val_class_str)
+ continue;
+
+ if (!debug_line_str_hash)
+ debug_line_str_hash
+ = hash_table<indirect_string_hasher>::create_ggc (10);
+
+ struct indirect_string_node *node
+ = find_AT_string_in_table (a->dw_attr_val.v.val_str->str,
+ debug_line_str_hash);
+ set_indirect_string (node);
+ node->form = DW_FORM_line_strp;
+ a->dw_attr_val.v.val_str = node;
+ }
+}
+
/* Output stuff that dwarf requires at the end of every file,
and generate the DWARF-2 debugging info. */
@@ -31398,6 +31428,12 @@ dwarf2out_finish (const char *filename)
{
debug_line_str_hash->traverse<void *, reset_indirect_string> (NULL);
debug_line_str_hash = NULL;
+ if (asm_outputs_debug_line_str ())
+ {
+ adjust_name_comp_dir (comp_unit_die ());
+ for (limbo_die_node *node = cu_die_list; node; node = node->next)
+ adjust_name_comp_dir (node->die);
+ }
}
}