Skip to content

Commit 43dcea4

Browse files
committed
btf: generate and output DECL_TAG and TYPE_TAG records
Support the btf_decl_tag and btf_type_tag attributes in BTF by creating and emitting BTF_KIND_DECL_TAG and BTF_KIND_TYPE_TAG records, respectively, for them. Some care is required when -gprune-btf is in effect to avoid emitting decl or type tags for declarations or types which have been pruned and will not be emitted in BTF. gcc/ * btfout.cc (get_btf_kind): Handle DECL_TAG and TYPE_TAG kinds. (btf_calc_num_vbytes): Likewise. (btf_asm_type): Likewise. (output_asm_btf_vlen_bytes): Likewise. (output_btf_tags): New. (btf_output): Call it here. (btf_add_used_type): Replace with simple wrapper around... (btf_add_used_type_1): ...the implementation. Handle BTF_KIND_DECL_TAG and BTF_KIND_TYPE_TAG. (btf_add_vars): Update btf_add_used_type call. (btf_assign_tag_ids): New. (btf_mark_type_used): Update btf_add_used_type call. (btf_collect_pruned_types): Likewise. Handle type and decl tags. (btf_finish): Call btf_assign_tag_ids. gcc/testsuite/ * gcc.dg/debug/btf/btf-decl-tag-1.c: New test. * gcc.dg/debug/btf/btf-decl-tag-2.c: New test. * gcc.dg/debug/btf/btf-decl-tag-3.c: New test. * gcc.dg/debug/btf/btf-decl-tag-4.c: New test. * gcc.dg/debug/btf/btf-type-tag-1.c: New test. * gcc.dg/debug/btf/btf-type-tag-2.c: New test. * gcc.dg/debug/btf/btf-type-tag-3.c: New test. * gcc.dg/debug/btf/btf-type-tag-4.c: New test. * gcc.dg/debug/btf/btf-type-tag-c2x-1.c: New test. include/ * btf.h (BTF_KIND_DECL_TAG, BTF_KIND_TYPE_TAG) New defines. (struct btf_decl_tag): New.
1 parent 9c862a5 commit 43dcea4

File tree

11 files changed

+366
-24
lines changed

11 files changed

+366
-24
lines changed

gcc/btfout.cc

Lines changed: 147 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ get_btf_kind (uint32_t ctf_kind)
141141
case CTF_K_VOLATILE: return BTF_KIND_VOLATILE;
142142
case CTF_K_CONST: return BTF_KIND_CONST;
143143
case CTF_K_RESTRICT: return BTF_KIND_RESTRICT;
144+
case CTF_K_DECL_TAG: return BTF_KIND_DECL_TAG;
145+
case CTF_K_TYPE_TAG: return BTF_KIND_TYPE_TAG;
144146
default:;
145147
}
146148
return BTF_KIND_UNKN;
@@ -217,6 +219,7 @@ btf_calc_num_vbytes (ctf_dtdef_ref dtd)
217219
case BTF_KIND_CONST:
218220
case BTF_KIND_RESTRICT:
219221
case BTF_KIND_FUNC:
222+
case BTF_KIND_TYPE_TAG:
220223
/* These kinds have no vlen data. */
221224
break;
222225

@@ -256,6 +259,10 @@ btf_calc_num_vbytes (ctf_dtdef_ref dtd)
256259
vlen_bytes += vlen * sizeof (struct btf_var_secinfo);
257260
break;
258261

262+
case BTF_KIND_DECL_TAG:
263+
vlen_bytes += sizeof (struct btf_decl_tag);
264+
break;
265+
259266
default:
260267
break;
261268
}
@@ -452,6 +459,20 @@ btf_asm_type (ctf_dtdef_ref dtd)
452459
and should write 0. */
453460
dw2_asm_output_data (4, 0, "(unused)");
454461
return;
462+
case BTF_KIND_DECL_TAG:
463+
{
464+
if (dtd->ref_type)
465+
break;
466+
else if (dtd->dtd_u.dtu_tag.ref_var)
467+
{
468+
/* ref_type is NULL for decl tag attached to a variable. */
469+
ctf_dvdef_ref dvd = dtd->dtd_u.dtu_tag.ref_var;
470+
dw2_asm_output_data (4, dvd->dvd_id,
471+
"btt_type: (BTF_KIND_VAR '%s')",
472+
dvd->dvd_name);
473+
return;
474+
}
475+
}
455476
default:
456477
break;
457478
}
@@ -801,6 +822,12 @@ output_asm_btf_vlen_bytes (ctf_container_ref ctfc, ctf_dtdef_ref dtd)
801822
at this point. */
802823
gcc_unreachable ();
803824

825+
case BTF_KIND_DECL_TAG:
826+
dw2_asm_output_data (4, dtd->dtd_u.dtu_tag.component_idx,
827+
"component_idx=%d",
828+
dtd->dtd_u.dtu_tag.component_idx);
829+
break;
830+
804831
default:
805832
/* All other BTF type kinds have no variable length data. */
806833
break;
@@ -851,6 +878,20 @@ output_btf_func_types (void)
851878
btf_asm_func_type (ref);
852879
}
853880

881+
static void
882+
output_btf_tags (ctf_container_ref ctfc)
883+
{
884+
/* If pruning, tags which are not pruned have already been added to
885+
the used list and output by output_btf_types. */
886+
if (debug_prune_btf)
887+
return;
888+
889+
ctf_dtdef_ref dtd;
890+
unsigned i;
891+
FOR_EACH_VEC_ELT (*ctfc->ctfc_tags, i, dtd)
892+
output_asm_btf_type (ctfc, dtd);
893+
}
894+
854895
/* Output all BTF_KIND_DATASEC records. */
855896

856897
static void
@@ -869,6 +910,7 @@ btf_output (ctf_container_ref ctfc)
869910
output_btf_types (ctfc);
870911
output_btf_vars (ctfc);
871912
output_btf_func_types ();
913+
output_btf_tags (ctfc);
872914
output_btf_datasec_types ();
873915
output_btf_strs (ctfc);
874916
}
@@ -985,7 +1027,8 @@ static vec<struct btf_fixup> fixups;
9851027
is created and emitted. This vector stores them. */
9861028
static GTY (()) vec<ctf_dtdef_ref, va_gc> *forwards;
9871029

988-
/* Recursively add type DTD and any types it references to the used set.
1030+
/* Implementation of btf_add_used_type.
1031+
Recursively add type DTD and any types it references to the used set.
9891032
Return a type that should be used for references to DTD - usually DTD itself,
9901033
but may be NULL if DTD corresponds to a type which will not be emitted.
9911034
CHECK_PTR is true if one of the predecessors in recursive calls is a struct
@@ -996,8 +1039,8 @@ static GTY (()) vec<ctf_dtdef_ref, va_gc> *forwards;
9961039
CREATE_FIXUPS is false. */
9971040

9981041
static ctf_dtdef_ref
999-
btf_add_used_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd,
1000-
bool check_ptr, bool seen_ptr, bool create_fixups)
1042+
btf_add_used_type_1 (ctf_container_ref ctfc, ctf_dtdef_ref dtd,
1043+
bool check_ptr, bool seen_ptr, bool create_fixups)
10011044
{
10021045
if (dtd == NULL)
10031046
return NULL;
@@ -1029,8 +1072,9 @@ btf_add_used_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd,
10291072
fixups.unordered_remove (i);
10301073

10311074
/* Add the concrete base type. */
1032-
dtd->ref_type = btf_add_used_type (ctfc, dtd->ref_type, check_ptr,
1033-
seen_ptr, create_fixups);
1075+
dtd->ref_type = btf_add_used_type_1 (ctfc, dtd->ref_type,
1076+
check_ptr, seen_ptr,
1077+
create_fixups);
10341078
return dtd;
10351079
}
10361080
default:
@@ -1044,8 +1088,8 @@ btf_add_used_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd,
10441088
the reference to the bitfield. The slice type won't be emitted,
10451089
but we need the information in it when writing out the bitfield
10461090
encoding. */
1047-
btf_add_used_type (ctfc, dtd->dtd_u.dtu_slice.cts_type,
1048-
check_ptr, seen_ptr, create_fixups);
1091+
btf_add_used_type_1 (ctfc, dtd->dtd_u.dtu_slice.cts_type,
1092+
check_ptr, seen_ptr, create_fixups);
10491093
return dtd;
10501094
}
10511095

@@ -1069,7 +1113,11 @@ btf_add_used_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd,
10691113
case BTF_KIND_INT:
10701114
case BTF_KIND_FLOAT:
10711115
case BTF_KIND_FWD:
1072-
/* Leaf kinds which do not refer to any other types. */
1116+
case BTF_KIND_DECL_TAG:
1117+
/* Leaf kinds which do not refer to any other types.
1118+
BTF_KIND_DECL_TAG is a special case: we treat it as though it does not
1119+
refer to any other types, since we only want the DECL_TAG to be added
1120+
if the type to which it refers has already been added. */
10731121
break;
10741122

10751123
case BTF_KIND_FUNC:
@@ -1082,6 +1130,7 @@ btf_add_used_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd,
10821130
case BTF_KIND_CONST:
10831131
case BTF_KIND_VOLATILE:
10841132
case BTF_KIND_RESTRICT:
1133+
case BTF_KIND_TYPE_TAG:
10851134
{
10861135
/* These type kinds refer to exactly one other type. */
10871136
if (check_ptr && !seen_ptr)
@@ -1106,18 +1155,18 @@ btf_add_used_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd,
11061155
}
11071156

11081157
/* Add the type to which this type refers. */
1109-
dtd->ref_type = btf_add_used_type (ctfc, dtd->ref_type, check_ptr,
1110-
seen_ptr, create_fixups);
1158+
dtd->ref_type = btf_add_used_type_1 (ctfc, dtd->ref_type, check_ptr,
1159+
seen_ptr, create_fixups);
11111160
break;
11121161
}
11131162
case BTF_KIND_ARRAY:
11141163
{
11151164
/* Add element and index types. */
11161165
ctf_arinfo_t *arr = &(dtd->dtd_u.dtu_arr);
1117-
arr->ctr_contents = btf_add_used_type (ctfc, arr->ctr_contents, false,
1118-
false, create_fixups);
1119-
arr->ctr_index = btf_add_used_type (ctfc, arr->ctr_index, false, false,
1120-
create_fixups);
1166+
arr->ctr_contents = btf_add_used_type_1 (ctfc, arr->ctr_contents,
1167+
false, false, create_fixups);
1168+
arr->ctr_index = btf_add_used_type_1 (ctfc, arr->ctr_index, false,
1169+
false, create_fixups);
11211170
break;
11221171
}
11231172
case BTF_KIND_STRUCT:
@@ -1133,8 +1182,8 @@ btf_add_used_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd,
11331182
/* Add member type for struct/union members. For enums, only the
11341183
enumerator names are needed. */
11351184
if (kind == BTF_KIND_STRUCT || kind == BTF_KIND_UNION)
1136-
dmd->dmd_type = btf_add_used_type (ctfc, dmd->dmd_type, true,
1137-
false, create_fixups);
1185+
dmd->dmd_type = btf_add_used_type_1 (ctfc, dmd->dmd_type, true,
1186+
false, create_fixups);
11381187
ctf_add_string (ctfc, dmd->dmd_name, &(dmd->dmd_name_offset),
11391188
CTF_STRTAB);
11401189
}
@@ -1143,16 +1192,17 @@ btf_add_used_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd,
11431192
case BTF_KIND_FUNC_PROTO:
11441193
{
11451194
/* Add return type. */
1146-
dtd->ref_type = btf_add_used_type (ctfc, dtd->ref_type, false, false,
1147-
create_fixups);
1195+
dtd->ref_type = btf_add_used_type_1 (ctfc, dtd->ref_type, false, false,
1196+
create_fixups);
11481197

11491198
/* Add arg types. */
11501199
ctf_func_arg_t * farg;
11511200
for (farg = dtd->dtd_u.dtu_argv;
11521201
farg != NULL; farg = (ctf_func_arg_t *) ctf_farg_list_next (farg))
11531202
{
1154-
farg->farg_type = btf_add_used_type (ctfc, farg->farg_type, false,
1155-
false, create_fixups);
1203+
farg->farg_type = btf_add_used_type_1 (ctfc, farg->farg_type,
1204+
false, false,
1205+
create_fixups);
11561206
/* Note: argument names are stored in the auxilliary string table,
11571207
since CTF does not include arg names. That table has not been
11581208
cleared, so no need to re-add argument names here. */
@@ -1166,6 +1216,16 @@ btf_add_used_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd,
11661216
return dtd;
11671217
}
11681218

1219+
/* Recursively add type DTD and any types it references to the used set.
1220+
Return a type that should be used for references to DTD - usually DTD itself,
1221+
but may be NULL if DTD corresponds to a type which will not be emitted. */
1222+
1223+
static ctf_dtdef_ref
1224+
btf_add_used_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd)
1225+
{
1226+
return btf_add_used_type_1 (ctfc, dtd, false, false, true);
1227+
}
1228+
11691229
/* Initial entry point of BTF generation, called at early_finish () after
11701230
CTF information has possibly been output. Translate all CTF information
11711231
to BTF, and do any processing that must be done early, such as creating
@@ -1402,7 +1462,7 @@ btf_add_vars (ctf_container_ref ctfc)
14021462
ctf_dmdef_t *dmd;
14031463
for (dmd = dtd->dtd_u.dtu_members;
14041464
dmd != NULL; dmd = (ctf_dmdef_t *) ctf_dmd_list_next (dmd))
1405-
btf_add_used_type (ctfc, dmd->dmd_type, false, false, true);
1465+
btf_add_used_type (ctfc, dmd->dmd_type);
14061466
}
14071467
}
14081468
}
@@ -1488,6 +1548,39 @@ btf_assign_var_ids (ctf_container_ref ctfc)
14881548
}
14891549
}
14901550

1551+
/* Assign BTF IDs for type and decl tags and account for their size. */
1552+
1553+
static void
1554+
btf_assign_tag_ids (ctf_container_ref ctfc)
1555+
{
1556+
size_t num_tags = vec_safe_length (ctfc->ctfc_tags);
1557+
if (num_tags == 0)
1558+
return;
1559+
1560+
unsigned int i;
1561+
ctf_dtdef_ref dtd;
1562+
FOR_EACH_VEC_ELT (*ctfc->ctfc_tags, i, dtd)
1563+
{
1564+
/* Assign BTF id. */
1565+
ctf_id_t id = ctfc->ctfc_nextid++;
1566+
gcc_assert (id <= BTF_MAX_TYPE);
1567+
dtd->dtd_type = id;
1568+
1569+
/* Tags on functions will have a ref_type pointing to the
1570+
FUNC_PROTO, we want them to point the FUNC record instead. */
1571+
ctf_dtdef_ref *pdtd = NULL;
1572+
if (dtd->ref_type && (pdtd = func_map->get (dtd->ref_type)) != NULL)
1573+
dtd->ref_type = *pdtd;
1574+
1575+
/* Strings for tags are stored in the auxiliary strtab, which is
1576+
concatenated after the regular strtab. ctti_name only accounts
1577+
for offset in the auxiliary strtab until this point. */
1578+
dtd->dtd_data.ctti_name += ctfc_get_strtab_len (ctfc, CTF_STRTAB);
1579+
ctfc->ctfc_num_types++;
1580+
ctfc->ctfc_num_vlen_bytes += btf_calc_num_vbytes (dtd);
1581+
}
1582+
}
1583+
14911584
/* Assign BTF IDs for datasec records and account for their size. */
14921585

14931586
static void
@@ -1522,7 +1615,7 @@ btf_mark_type_used (tree t)
15221615
if (!dtd)
15231616
return;
15241617

1525-
btf_add_used_type (ctfc, dtd, false, false, true);
1618+
btf_add_used_type (ctfc, dtd);
15261619
}
15271620

15281621
/* Callback used for assembling the only-used-types list. Note that this is
@@ -1549,7 +1642,7 @@ btf_collect_pruned_types (ctf_container_ref ctfc)
15491642
size_t i;
15501643
FOR_EACH_VEC_ELT (*funcs, i, dtd)
15511644
{
1552-
btf_add_used_type (ctfc, dtd->ref_type, false, false, true);
1645+
btf_add_used_type (ctfc, dtd->ref_type);
15531646
ctf_add_string (ctfc, dtd->dtd_name, &(dtd->dtd_data.ctti_name),
15541647
CTF_STRTAB);
15551648
}
@@ -1558,10 +1651,33 @@ btf_collect_pruned_types (ctf_container_ref ctfc)
15581651
for (i = 0; i < ctfc->ctfc_vars_list_count; i++)
15591652
{
15601653
ctf_dvdef_ref dvd = ctfc->ctfc_vars_list[i];
1561-
btf_add_used_type (ctfc, dvd->dvd_type, false, false, true);
1654+
btf_add_used_type (ctfc, dvd->dvd_type);
15621655
ctf_add_string (ctfc, dvd->dvd_name, &(dvd->dvd_name_offset), CTF_STRTAB);
15631656
}
15641657

1658+
/* Used type tags will be added by recursive btf_add_used_type calls above.
1659+
For decl tags, scan the list and only add those decl tags whose referent
1660+
types are marked as used. We may have pruned a struct type with members
1661+
annotated by a decl tag. */
1662+
FOR_EACH_VEC_ELT (*ctfc->ctfc_tags, i, dtd)
1663+
{
1664+
/* Only add decl tags whose referent types have not been pruned.
1665+
Variables are never pruned, so decl tags on variables are always
1666+
used. */
1667+
if (btf_dtd_kind (dtd) == BTF_KIND_DECL_TAG
1668+
&& ((dtd->ref_type && btf_used_types->contains (dtd->ref_type))
1669+
|| (dtd->dtd_u.dtu_tag.ref_var)))
1670+
btf_add_used_type (ctfc, dtd);
1671+
1672+
/* Tags on functions or function args will have a ref_type pointing to the
1673+
FUNC_PROTO, we want them to point the FUNC record instead. */
1674+
ctf_dtdef_ref *pdtd = NULL;
1675+
if (dtd->ref_type
1676+
&& btf_used_types->contains (dtd->ref_type)
1677+
&& (pdtd = func_map->get (dtd->ref_type)) != NULL)
1678+
dtd->ref_type = *pdtd;
1679+
}
1680+
15651681
/* Process fixups. If the base type was never added, create a forward for it
15661682
and adjust the reference to point to that. If it was added, then nothing
15671683
needs to change. */
@@ -1634,6 +1750,13 @@ btf_finish (void)
16341750

16351751
btf_assign_var_ids (tu_ctfc);
16361752
btf_assign_func_ids (tu_ctfc);
1753+
1754+
/* Both decl and type tags may be pruned if the types/decls to which they
1755+
refer are pruned. This is handled in btf_collect_pruned_types, and
1756+
through that process they have also been assigned ids already. */
1757+
if (!debug_prune_btf)
1758+
btf_assign_tag_ids (tu_ctfc);
1759+
16371760
btf_assign_datasec_ids (tu_ctfc);
16381761

16391762
/* Finally, write out the complete .BTF section. */
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/* Test simple BTF decl tag generation for variables. */
2+
/* { dg-do compile } */
3+
/* { dg-options "-O0 -gbtf -dA" } */
4+
5+
#define __tag1 __attribute__((btf_decl_tag ("decl1")))
6+
#define __tag2 __attribute__((btf_decl_tag ("decl2")))
7+
#define __tag3 __attribute__((btf_decl_tag ("decl3")))
8+
9+
int x __tag1 __tag2;
10+
int y __tag1;
11+
12+
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl1'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_VAR 'x'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=-1" 1} } */
13+
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl2'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_VAR 'x'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=-1" 1} } */
14+
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl1'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_VAR 'y'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=-1" 1} } */
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* Test BTF decl tag generation for structs. */
2+
/* { dg-do compile } */
3+
/* { dg-options "-O0 -gbtf -dA" } */
4+
5+
#define __tag1 __attribute__((btf_decl_tag ("decl1")))
6+
#define __tag2 __attribute__((btf_decl_tag ("decl2")))
7+
#define __tag3 __attribute__((btf_decl_tag ("decl3")))
8+
9+
struct Foo {
10+
int a;
11+
int b __tag3 __tag2;
12+
char *z __tag1;
13+
};
14+
15+
struct Foo f __tag1 __tag2;
16+
17+
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl2'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_STRUCT 'Foo'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=1" 1} } */
18+
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl3'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_STRUCT 'Foo'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=1" 1} } */
19+
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl1'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_STRUCT 'Foo'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=2" 1} } */
20+
21+
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl1'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_VAR 'f'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=-1" 1} } */
22+
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl2'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_VAR 'f'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=-1" 1} } */

0 commit comments

Comments
 (0)