Skip to content

Commit ac7027f

Browse files
committed
dwarf: create annotation DIEs for btf tags
The btf_decl_tag and btf_type_tag attributes provide a means to annotate declarations and types respectively with arbitrary user provided strings. These strings are recorded in debug information for post-compilation uses, and despite the name they are meant to be recorded in DWARF as well as BTF. New DWARF extensions DW_TAG_GNU_annotation and DW_AT_GNU_annotation are used to represent these user annotations in DWARF. This patch introduces the new DWARF extension DIE and attribute, and generates them as necessary to represent user annotations from btf_decl_tag and btf_type_tag. The format of the new DIE is as follows: DW_TAG_GNU_annotation DW_AT_name: "btf_decl_tag" or "btf_type_tag" DW_AT_const_value: <arbitrary user-supplied string> DW_AT_GNU_annotation: <reference to another TAG_GNU_annotation DIE> DW_AT_GNU_annotation is a new attribute extension used to refer to these new annotation DIEs. If non-null in any given declaration or type DIE, it is a reference to a DW_TAG_GNU_annotation DIE holding an annotation for that declaration or type. In addition, the DW_TAG_GNU_annotation DIEs may also have a non-null DW_AT_GNU_annotation, referring to another annotation DIE. This allows chains of annotation DIEs to be formed, such as in the case where a single declaration has multiple instances of btf_decl_tag with different string annotations. gcc/ * dwarf2out.cc (struct annotation_node, struct annotation_node_hasher) (btf_tag_htab): New ancillary structures and hash table. (annotation_node_hasher::hash, annotation_node_hasher::equal): New. (hash_btf_tag, gen_btf_tag_dies, maybe_gen_btf_type_tag_dies) (maybe_gen_btf_decl_tag_dies): New functions. (modified_type_die): Add new argument to pass type attributes. Handle btf_type_tag, and update recursive calls. (base_type_for_mode): Add new arg for modified_type_die call. (add_type_attribute): Likewise. (gen_array_type_die): Call maybe_gen_btf_type_tag_dies for the type. (gen_formal_parameter_die): Call maybe_gen_btf_decl_tag_dies for the parameter. (override_type_for_decl_p): Add new arg for modified_type_die call. (force_type_die): Likewise. (gen_tagged_type_die): Call maybe_gen_btf_type_tag_dies for the type. (gen_decl_die): Call maybe_gen_btf_decl_tag_dies for the decl. (dwarf2out_finish): Empty btf_tag_htab. (dwarf2out_cc_finalize): Delete btf_tag_htab hash table. include/ * dwarf2.def (DW_TAG_GNU_annotation): New DWARF extension. (DW_AT_GNU_annotation): Likewise. gcc/testsuite/ * gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-1.c: New test. * gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-2.c: New test. * gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-3.c: New test. * gcc.dg/debug/dwarf2/dwarf-btf-type-tag-1.c: New test. * gcc.dg/debug/dwarf2/dwarf-btf-type-tag-2.c: New test. * gcc.dg/debug/dwarf2/dwarf-btf-type-tag-3.c: New test. * gcc.dg/debug/dwarf2/dwarf-btf-type-tag-4.c: New test. * gcc.dg/debug/dwarf2/dwarf-btf-type-tag-5.c: New test. * gcc.dg/debug/dwarf2/dwarf-btf-type-tag-6.c: New test. * gcc.dg/debug/dwarf2/dwarf-btf-type-tag-7.c: New test. * gcc.dg/debug/dwarf2/dwarf-btf-type-tag-8.c: New test. * gcc.dg/debug/dwarf2/dwarf-btf-type-tag-9.c: New test. * gcc.dg/debug/dwarf2/dwarf-btf-type-tag-10.c: New test.
1 parent 7e80927 commit ac7027f

15 files changed

+598
-27
lines changed

gcc/dwarf2out.cc

Lines changed: 301 additions & 27 deletions
Large diffs are not rendered by default.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/* Test simple generation of DW_TAG_GNU_annotation DIE for
2+
btf_decl_tag attribute. */
3+
/* { dg-do compile } */
4+
/* { dg-options "-gdwarf -dA" } */
5+
6+
int *foo __attribute__((btf_decl_tag ("my_foo")));
7+
8+
/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_GNU_annotation" 1 } } */
9+
/* { dg-final { scan-assembler-times " DW_AT_name: \"btf_decl_tag\"" 1 } } */
10+
/* { dg-final { scan-assembler-times " DW_AT_const_value: \"my_foo\"" 1 } } */
11+
/* { dg-final { scan-assembler-times " DW_AT_GNU_annotation" 1 } } */
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* Test dwarf generation for btf_decl_tag on struct and union members. */
2+
/* { dg-do compile } */
3+
/* { dg-options "-gdwarf -dA" } */
4+
5+
#define __tag1 __attribute__((btf_decl_tag ("decl1")))
6+
#define __tag2 __attribute__((btf_decl_tag ("decl2")))
7+
8+
union U {
9+
int i __tag1;
10+
unsigned char ub[4];
11+
};
12+
13+
struct S {
14+
union U u;
15+
int b __tag2;
16+
char *z __tag1;
17+
};
18+
19+
struct S my_s __tag1 __tag2;
20+
21+
/* We must have two occurrences of one of the two annotation DIEs due to
22+
the different attribute sets between declarations above. */
23+
/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_GNU_annotation" 3 } } */
24+
/* { dg-final { scan-assembler-times " DW_AT_name: \"btf_decl_tag\"" 3 } } */
25+
/* { dg-final { scan-assembler-times " DW_AT_GNU_annotation" 5 } } */
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/* Test dwarf generation for btf_decl_tag on functions and function args. */
2+
/* { dg-do compile } */
3+
/* { dg-options "-gdwarf -dA" } */
4+
5+
#define __tag1 __attribute__((btf_decl_tag ("decl1")))
6+
#define __tag2 __attribute__((btf_decl_tag ("decl2")))
7+
8+
int __tag1 __tag2 func (int arg_a __tag1, int arg_b __tag2)
9+
{
10+
return arg_a * arg_b;
11+
}
12+
13+
int foo (int x) {
14+
return func (x, x + 1);
15+
}
16+
17+
/* In this case one of the decl tag DIEs must be duplicated due to differing
18+
DW_AT_GNU_annotation chain between the three uses. */
19+
/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_GNU_annotation" 3 } } */
20+
/* { dg-final { scan-assembler-times " DW_AT_name: \"btf_decl_tag\"" 3 } } */
21+
/* { dg-final { scan-assembler-times " DW_AT_GNU_annotation" 4 } } */
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/* Test simple generation for btf_type_tag attribute. */
2+
/* { dg-do compile } */
3+
/* { dg-options "-gdwarf -dA" } */
4+
5+
int * __attribute__((btf_type_tag("__user"))) ptr;
6+
7+
/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_GNU_annotation" 1 } } */
8+
/* { dg-final { scan-assembler-times " DW_AT_name: \"btf_type_tag\"" 1 } } */
9+
/* { dg-final { scan-assembler-times " DW_AT_const_value: \"__user\"" 1 } } */
10+
/* { dg-final { scan-assembler-times " DW_AT_GNU_annotation" 1 } } */
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/* Test btf_type_tag and btf_decl_tag on a function.
2+
Here the decl_tag applies to the function, and the type_tag applies
3+
to the return type. */
4+
/* { dg-do compile } */
5+
/* { dg-options "-gdwarf -dA" } */
6+
7+
int * __attribute__((btf_type_tag ("A")))
8+
__attribute__((btf_decl_tag ("decl")))
9+
foo (int *x, int *y)
10+
{
11+
if (x && y && *x > *y)
12+
return x;
13+
return y;
14+
}
15+
16+
/* Ideally, verify that AT_GNU_annotation in the subprogram DIE refers to
17+
the decl_tag annotation DIE, and the AT_GNU_annotation in the return
18+
type refers to the type_tag... */
19+
/* { dg-final { scan-assembler-times " DW_AT_name: \"btf_type_tag\"" 1 } } */
20+
/* { dg-final { scan-assembler-times " DW_AT_name: \"btf_decl_tag\"" 1 } } */
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/* Test that DW_TAG_GNU_annotation DIEs for attribute btf_type_tag are shared
2+
where possible. */
3+
/* { dg-do compile } */
4+
/* { dg-options "-gdwarf -dA" } */
5+
6+
#define __tag1 __attribute__((btf_type_tag("tag1")))
7+
#define __tag2 __attribute__((btf_type_tag("tag2")))
8+
9+
int __tag1 foo;
10+
char * __tag1 __tag2 bar;
11+
12+
struct S
13+
{
14+
unsigned char bytes[8];
15+
unsigned long __tag1 t;
16+
void *ptr;
17+
};
18+
19+
struct S * __tag1 __tag2 my_S;
20+
21+
/* Only 2 DW_TAG_GNU_annotation DIEs should be generated, one each for "tag1"
22+
and "tag2", and they should be reused. */
23+
/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_GNU_annotation" 2 } } */
24+
/* { dg-final { scan-assembler-times " DW_AT_name: \"btf_type_tag\"" 2 } } */
25+
/* { dg-final { scan-assembler-times " DW_AT_const_value: \"tag1\"" 1 } } */
26+
/* { dg-final { scan-assembler-times " DW_AT_const_value: \"tag2\"" 1 } } */
27+
28+
/* Each attribute-ed type shall refer via DW_AT_GNU_annotation to the
29+
appropriate annotation DIE, including the annotation DIE for "tag2" which
30+
is always chained to the DIE for "tag1" in this construction. */
31+
/* { dg-final { scan-assembler-times " DW_AT_GNU_annotation" 5 } } */
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/* Test dwarf generation for btf_type_tag with cv-quals and typedefs. */
2+
/* { dg-do compile } */
3+
/* { dg-options "-gdwarf -dA" } */
4+
5+
#define __tag1 __attribute__((btf_type_tag ("tag1")))
6+
#define __tag2 __attribute__((btf_type_tag ("tag2")))
7+
8+
typedef const int foo;
9+
typedef int __tag1 bar;
10+
11+
foo __tag2 x;
12+
const bar y;
13+
14+
/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_GNU_annotation" 2 } } */
15+
/* { dg-final { scan-assembler-times " DW_AT_name: \"btf_type_tag\"" 2 } } */
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/* Test generating annotation DIEs for struct/union/enum types. */
2+
/* { dg-do compile } */
3+
/* { dg-options "-gdwarf -dA" } */
4+
5+
enum E
6+
{
7+
ONE,
8+
TWO
9+
} __attribute__((btf_type_tag("foo")));
10+
11+
enum E some_e;
12+
13+
struct S
14+
{
15+
int i;
16+
char c;
17+
} __attribute__((btf_type_tag("foo")));
18+
19+
typedef struct S S1;
20+
S1 plain_s1;
21+
const S1 const_s1;
22+
23+
union U
24+
{
25+
int x;
26+
char y;
27+
} __attribute__((btf_type_tag("foo")));
28+
29+
volatile union U volatile_u;
30+
31+
/* One annotation DIE may be shared by all three annotated types. */
32+
/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_GNU_annotation" 1 } } */
33+
/* { dg-final { scan-assembler-times " DW_AT_name: \"btf_type_tag\"" 1 } } */
34+
/* { dg-final { scan-assembler-times " DW_AT_GNU_annotation" 3 } } */
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/* Test generation for btf_type_tag attribute on array type. */
2+
/* { dg-do compile } */
3+
/* { dg-options "-gdwarf -dA" } */
4+
5+
int arr[8] __attribute__((btf_type_tag("tagged_arr")));
6+
7+
/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_GNU_annotation" 1 } } */
8+
/* { dg-final { scan-assembler-times " DW_AT_name: \"btf_type_tag\"" 1 } } */
9+
/* { dg-final { scan-assembler-times " DW_AT_const_value: \"tagged_arr\"" 1 } } */
10+
/* { dg-final { scan-assembler-times " DW_AT_GNU_annotation" 1 } } */

0 commit comments

Comments
 (0)