On 10/12/25 22:53, Jose E. Marchesi wrote:
> 
>> The check in gen_btf_tag_dies which asserted that if the target DIE
>> already had an annotation then it must be the same as the one we are
>> attempting to add was too strict.  It is valid for multiple declarations
>> of the same object to appear with different decl_tags, in which case the
>> tags are accumulated in the DECL_ATTRIBUTES, but the existing tag may
>> not be the same as the one being added.  This was not handled correctly
>> and led to the ICE reported in the PR.
>>
>> The more accurate requirement for consistency is that if there is an
>> existing chain of annotations, then it is a sub-chain of the one we are
>> adding in the current pass.  This patch fixes gen_btf_tag_dies to use
>> the more accurate check and properly handle the case in the PR.
>>
>> Bootstrapped and tested on x86_64-linux-gnu.
>>
>> OK for trunk?
>> Thanks
>>
>>      PR debug/122248
>>
>> gcc/
>>
>>      * dwarf2out.cc (gen_btf_tag_dies): Handle repeated declarations
>>      of the same object with different decl_tags and improve accuracy
>>      of the consistency check under flag_checking.
>>
>> gcc/testsuite/
>>
>>      * gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-4.c: New.
>>      * gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-5.c: New.
>>      * gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-6.c: New.
>> ---
>>  gcc/dwarf2out.cc                              | 27 +++++++++++---
>>  .../debug/dwarf2/dwarf-btf-decl-tag-4.c       | 28 +++++++++++++++
>>  .../debug/dwarf2/dwarf-btf-decl-tag-5.c       | 35 +++++++++++++++++++
>>  .../debug/dwarf2/dwarf-btf-decl-tag-6.c       | 24 +++++++++++++
>>  4 files changed, 109 insertions(+), 5 deletions(-)
>>  create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-4.c
>>  create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-5.c
>>  create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-6.c
>>
>> diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
>> index a817c69c95a..8fe6e3321e1 100644
>> --- a/gcc/dwarf2out.cc
>> +++ b/gcc/dwarf2out.cc
>> @@ -13843,13 +13843,30 @@ gen_btf_tag_dies (tree attr, dw_die_ref die)
>>    if (die)
>>      {
>>        /* Add AT_GNU_annotation referring to the annotation DIE.
>> -     It may have already been added, some global declarations are processed
>> -     twice, but if so it must be the same or we have a bug.  */
>> +     There may be an existing annotation chain, as in the case of global
>> +     decls which may can processed (and declared) multiple times.

I just noticed a typo in the comment here: "may be" or "can be" became
"may can".  Fixed locally.

>> +     Each time a global decl is processed it may have additional
>> +     decl_tags, but the set should never shrink.  */
>>        dw_die_ref existing = get_AT_ref (die, DW_AT_GNU_annotation);
>>        if (existing)
>> -    gcc_checking_assert (existing == tag_die);
>> -      else
>> -    add_AT_die_ref (die, DW_AT_GNU_annotation, tag_die);
>> +    {
>> +      if (flag_checking)
>> +        {
>> +          /* If there is an existing annotation chain, then it must be a
>> +             sub-chain of this one, i.e. its head must be somewhere in the
>> +             chain from tag_die.  Otherwise we may have a bug.  */
>> +          dw_die_ref d = tag_die;
>> +          while (d && d != existing)
>> +            d = get_AT_ref (die, DW_AT_GNU_annotation);
>> +
>> +          gcc_assert (d);
>> +        }
>> +
>> +      /* Remove the existing annotation and replace it with the new.  */
>> +      remove_AT (die, DW_AT_GNU_annotation);
>> +    }
>> +
>> +      add_AT_die_ref (die, DW_AT_GNU_annotation, tag_die);
> 
> tag_die here contains the accummulated tags?

Yes, it is the result of building the complete chain of tags
on the given object from TYPE_ATTRIBUTES or DECL_ATTRIBUTES.

If an object is re-declared with different decl_tags, they
accumulate in DECL_ATTRIBUTES.

so e.g. if __tag1 and __tag2 are btf_decl_tags, then

  struct S { ... };
  struct S foo __tag1;
  struct S foo __tag2;

The decl 'foo' is processed twice.
First, DECL_ATTRIBUTES ('foo') is the list (__tag1).
And tag_die is the lone DIE for tag1.

Second, DECL_ATTRIBUTES ('foo') is (__tag2, __tag1).
Now tag_die is the chain of two DIEs: tag2 -> tag1.

The work of building the chain as necessary is already done
by the existing implementation, so we can just swap existing
with the new head-of-chain.

> 
>>      }
>>  
>>    return tag_die;
>> diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-4.c 
>> b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-4.c
>> new file mode 100644
>> index 00000000000..6fdcdc6e864
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-4.c
>> @@ -0,0 +1,28 @@
>> +/* Test DWARF generation for decl_tags on global decls appearing multiple
>> +   times with different decl_tags.  PR122248.  */
>> +/* { dg-do compile } */
>> +/* { dg-options "-gdwarf -dA" } */
>> +
>> +#define __tag1 __attribute__((btf_decl_tag ("tag1")))
>> +#define __tag2 __attribute__((btf_decl_tag ("tag2")))
>> +#define __tag3 __attribute__((btf_decl_tag ("tag3")))
>> +#define __tag4 __attribute__((btf_decl_tag ("tag4")))
>> +
>> +int foo __tag1;
>> +int foo __tag2;
>> +
>> +/* Result: foo has __tag1 and __tag2.  */
>> +
>> +int bar __tag3;
>> +int bar;
>> +
>> +/* Result: bar has __tag3.  */
>> +
>> +int baz;
>> +int baz __tag4;
>> +
>> +/* Result: baz has __tag4.  */
>> +
>> +/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) 
>> DW_TAG_GNU_annotation" 4 } } */
>> +/* { dg-final { scan-assembler-times " DW_AT_GNU_annotation" 4 } } */
>> +
>> diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-5.c 
>> b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-5.c
>> new file mode 100644
>> index 00000000000..c7cb60ca986
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-5.c
>> @@ -0,0 +1,35 @@
>> +/* Test DWARF generation for decl_tags on global decls appearing multiple
>> +   times with different decl_tags.  PR122248.  */
>> +/* { dg-do compile } */
>> +/* { dg-options "-gdwarf -dA" } */
>> +
>> +#define __tag1 __attribute__((btf_decl_tag ("tag1")))
>> +#define __tag2 __attribute__((btf_decl_tag ("tag2")))
>> +#define __tag3 __attribute__((btf_decl_tag ("tag3")))
>> +
>> +struct S
>> +{
>> +  int x;
>> +  char c;
>> +};
>> +
>> +extern struct S foo __tag1;
>> +struct S foo __tag2;
>> +
>> +/* Result: non-completing variable DIE for 'foo' has tag1, and the
>> +   completing DIE (with AT_specification) for 'foo' has tag2 -> tag1.  */
>> +
>> +extern int a __tag3;
>> +int a;
>> +
>> +/* Result: non-completing variable DIE for a has tag3, and the
>> +   completing DIE (with AT_specification) for 'a' also refers to tag3.  */
>> +
>> +/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) 
>> DW_TAG_GNU_annotation" 3 } } */
>> +
>> +/* 5 AT_GNU annotations:
>> +   - foo -> tag1
>> +   - foo -> tag2 -> tag1
>> +   - a -> tag3
>> +   - a -> tag3 */
>> +/* { dg-final { scan-assembler-times " DW_AT_GNU_annotation" 5 } } */
>> diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-6.c 
>> b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-6.c
>> new file mode 100644
>> index 00000000000..dd89d1142b9
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-6.c
>> @@ -0,0 +1,24 @@
>> +/* Test DWARF generation for decl_tags on global decls appearing multiple
>> +   times with different decl_tags.  PR122248.  */
>> +/* { dg-do compile } */
>> +/* { dg-options "-gdwarf -dA" } */
>> +
>> +#define __tag1 __attribute__((btf_decl_tag ("tag1")))
>> +#define __tag2 __attribute__((btf_decl_tag ("tag2")))
>> +#define __tag3 __attribute__((btf_decl_tag ("tag3")))
>> +
>> +__tag1
>> +extern int
>> +do_thing (int);
>> +
>> +__tag2
>> +__tag3
>> +int
>> +do_thing (int x)
>> +{
>> +  return x * x;
>> +}
>> +
>> +/* Result: do_thing has all 3 tags.  */
>> +/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) 
>> DW_TAG_GNU_annotation" 3 } } */
>> +/* { dg-final { scan-assembler-times " DW_AT_GNU_annotation" 3 } } */

Reply via email to