On 10/13/25 09:28, David Faust wrote:
> 
> 
> On 10/13/25 00:16, Richard Biener wrote:
>> On Sat, Oct 11, 2025 at 3:21 AM David Faust <[email protected]> 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.
>>> +        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.  */
>>
>> A bug in the DWARF implementation or in the users use of attributes?
>> The latter should not be diagnosed with an assert.
> 
> A bug in the DWARF implementation.

Hmm, Ping.  Is this patch OK?
Or would you rather I remove the if (flag_checking) block and its assert?

> 
> It would mean for example that we have somehow processed two distinct types
> like
> 
>   int __attribute__((btf_type_tag ("A"))) foo;
>   int __attribute__((btf_type_tag ("B"))) bar;
> 
> And tried to share the base int DIE between them, despite having
> incompatible sets of type_tag.  Cases like this should always result
> in two distinct type DIEs.  This happens naturally for types, since
> we get two distinct integer type TREE nodes each with the appropriate
> TYPE_ATTRIBUTES, and each integer type is processed once.
> 
> Catching such a bug in the implementation was the intent of the
> gcc_checking_assert (existing == tag_die), but that didn't properly
> account for cases with declaration tags like:
> 
>   int foo __attribute__((btf_decl_tag ("tag1")));
>   int foo __attribute__((btf_decl_tag ("tag2")));
> 
> In this case, the decl 'foo' is processed once each time it appears.
> 
> First, DECL_ATTRIBUTES ('foo') contains only tag1, and we annotate
> the DIE for it with an AT_GNU_annotation pointing to DIE for tag1.
> 
> The second time, DECL_ATTRIBUTES ('foo') is the list (tag2, tag1).
> So 'existing' is the DIE for tag1, and 'tag_die' is the DIE for tag2,
> which then points via AT_GNU_annotation to the DIE for tag1.
> 
> This is correct, but the simple (existing == tag_die) was too strict.
> Instead we should look for existing in tag_die's chain.  If it is not
> there at all, that would indicate a bug in the implementation, since
> tag1 is still present in DECL_ATTRIBUTES for foo.
> 
>>
>>> +             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);
>>>      }
>>>
>>>    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 } } */
>>> --
>>> 2.51.0
>>>
> 

Reply via email to