* [PAHOLE v5 0/5] support for DW_TAG_GNU_annotation and fixes
@ 2026-06-18 0:57 Vineet Gupta
2026-06-18 0:57 ` [PAHOLE v5 1/5] btf_loader: Handle decl tag component_idx for parameters Vineet Gupta
` (4 more replies)
0 siblings, 5 replies; 12+ messages in thread
From: Vineet Gupta @ 2026-06-18 0:57 UTC (permalink / raw)
To: dwarves
Cc: bpf, Andrii Nakryiko, acme, Alan Maguire, Emil Tsalapatis,
jose.marchesi, David Faust, Yonghong Song, Vineet Gupta
Hi,
This series handles gcc generated DW_TAG_GNU_annotation with the end
goal to finally enable CONFIG_PAHOLE_HAS_BTF_TAG for gcc kerenel builds.
Patches 1/5 and 5/5 are newly introduced in v5 per Alan's ask.
P.S.: I've optimistically included Reviewed-by/Acked-by from Emil and
Yonghong respectively on v4 [4] but those were before additional changes
in v5 from Alan for a few things. Please let me know if that's no longer
true.
[4] https://lore.kernel.org/bpf/20260602195512.1511013-1-vineet.gupta@linux.dev/
Thx,
-Vineet
Alan Maguire (2):
btf_loader: Handle decl tag component_idx for parameters
tests: Add btf_type_tag ordering test
Vineet Gupta (3):
dwarf_loader: Extract die__add_btf_type_tag() helper [NFC]
dwarf_loader: Add support for DW_TAG_GNU_annotation
tests: Support GCC in pfunct-btf-decl-tags test
btf_encoder.c | 1 +
btf_loader.c | 46 ++++++++-
dutil.h | 11 ++
dwarf_loader.c | 185 +++++++++++++++++++++++++++-------
dwarves.h | 2 +-
dwarves_fprintf.c | 32 ++++--
tests/btf_type_tag_order.sh | 179 ++++++++++++++++++++++++++++++++
tests/pfunct-btf-decl-tags.sh | 93 ++++++++++++-----
8 files changed, 478 insertions(+), 71 deletions(-)
create mode 100755 tests/btf_type_tag_order.sh
--
2.54.0
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PAHOLE v5 1/5] btf_loader: Handle decl tag component_idx for parameters
2026-06-18 0:57 [PAHOLE v5 0/5] support for DW_TAG_GNU_annotation and fixes Vineet Gupta
@ 2026-06-18 0:57 ` Vineet Gupta
2026-06-18 4:46 ` Emil Tsalapatis
2026-06-18 0:57 ` [PAHOLE v5 2/5] dwarf_loader: Extract die__add_btf_type_tag() helper [NFC] Vineet Gupta
` (3 subsequent siblings)
4 siblings, 1 reply; 12+ messages in thread
From: Vineet Gupta @ 2026-06-18 0:57 UTC (permalink / raw)
To: dwarves
Cc: bpf, Andrii Nakryiko, acme, Alan Maguire, Emil Tsalapatis,
jose.marchesi, David Faust, Yonghong Song, Vineet Gupta
From: Alan Maguire <alan.maguire@oracle.com>
A BTF_KIND_DECL_TAG with a non-negative component_idx applies to a
specific function parameter (or struct/union member), not to the
function itself. btf_loader.c however attached every decl tag to the
type named by btf_type->type, so parameter decl tags were recorded on
the function rather than on the parameter, and pfunct never printed
them with the parameter.
Resolve a non-negative component_idx to the corresponding parameter via
new helpers ftype__parameter()/function__parameter(), and attach the
tag there. Teach the pretty printer to emit a parameter's attributes by
factoring the function-level attribute loop into tag__attributes_fprintf()
and calling it from ftype__fprintf_parms() for each parameter.
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
---
btf_loader.c | 46 +++++++++++++++++++++++++++++++++++++++++++++-
dwarves_fprintf.c | 20 ++++++++++++++++----
2 files changed, 61 insertions(+), 5 deletions(-)
diff --git a/btf_loader.c b/btf_loader.c
index b591219a245d..9bb52c3c5801 100644
--- a/btf_loader.c
+++ b/btf_loader.c
@@ -477,12 +477,56 @@ static struct attributes *attributes__realloc(struct attributes *attributes, con
return result;
}
+static struct tag *ftype__parameter(const struct ftype *ftype, int component_idx)
+{
+ struct parameter *pos;
+ int idx = 0;
+
+ ftype__for_each_parameter(ftype, pos) {
+ if (idx == component_idx)
+ return &pos->tag;
+ ++idx;
+ }
+
+ return NULL;
+}
+
+static struct tag *function__parameter(const struct function *func, struct cu *cu,
+ int component_idx)
+{
+ struct tag *tag;
+
+ if (component_idx < 0)
+ return NULL;
+
+ tag = cu__type(cu, func->proto.tag.type);
+ if (tag == NULL)
+ return NULL;
+
+ return ftype__parameter(tag__ftype(tag), component_idx);
+}
+
static int process_decl_tag(struct cu *cu, const struct btf_type *tp)
{
+ int component_idx = btf_decl_tag(tp)->component_idx;
struct tag *tag = cu__type(cu, tp->type);
struct attributes *tmp;
- if (tag == NULL)
+ if (component_idx >= 0) {
+ struct tag *func_tag = cu__function(cu, tp->type);
+
+ if (func_tag != NULL) {
+ tag = function__parameter(tag__function(func_tag), cu,
+ component_idx);
+ if (tag == NULL) {
+ fprintf(stderr, "WARNING: BTF_KIND_DECL_TAG for unknown parameter %d in BTF id %d\n",
+ component_idx, tp->type);
+ return 0;
+ }
+ }
+ }
+
+ if (tag == NULL && component_idx < 0)
tag = cu__function(cu, tp->type);
if (tag == NULL)
diff --git a/dwarves_fprintf.c b/dwarves_fprintf.c
index 1ec478c2a027..54f483244bd2 100644
--- a/dwarves_fprintf.c
+++ b/dwarves_fprintf.c
@@ -1199,6 +1199,18 @@ const char *function__prototype(const struct function *func,
bf, len);
}
+static size_t tag__attributes_fprintf(const struct tag *tag, FILE *fp)
+{
+ size_t printed = 0;
+ int i;
+
+ if (tag->attributes)
+ for (i = 0; i < tag->attributes->cnt; ++i)
+ printed += fprintf(fp, "%s ", tag->attributes->values[i]);
+
+ return printed;
+}
+
size_t ftype__fprintf_parms(const struct ftype *ftype,
const struct cu *cu, int indent,
const struct conf_fprintf *conf, FILE *fp)
@@ -1240,6 +1252,7 @@ size_t ftype__fprintf_parms(const struct ftype *ftype,
if (n)
return printed + n;
if (ptype->tag == DW_TAG_subroutine_type) {
+ printed += tag__attributes_fprintf(&pos->tag, fp);
printed +=
ftype__fprintf(tag__ftype(ptype),
cu, name, 0, 1, 0,
@@ -1248,12 +1261,14 @@ size_t ftype__fprintf_parms(const struct ftype *ftype,
}
}
} else if (type->tag == DW_TAG_subroutine_type) {
+ printed += tag__attributes_fprintf(&pos->tag, fp);
printed += ftype__fprintf(tag__ftype(type), cu, name,
true, 0, 0, 0, conf, fp);
continue;
}
stype = tag__name(type, cu, sbf, sizeof(sbf), conf);
print_it:
+ printed += tag__attributes_fprintf(&pos->tag, fp);
printed += fprintf(fp, "%s%s%s", stype, name ? " " : "",
name ?: "");
}
@@ -1405,11 +1420,8 @@ static size_t function__fprintf(const struct tag *tag, const struct cu *cu,
struct ftype *ftype = func->btf ? tag__ftype(cu__type(cu, func->proto.tag.type)) : &func->proto;
size_t printed = 0;
bool inlined = !conf->strip_inline && function__declared_inline(func);
- int i;
- if (tag->attributes)
- for (i = 0; i < tag->attributes->cnt; ++i)
- printed += fprintf(fp, "%s ", tag->attributes->values[i]);
+ printed += tag__attributes_fprintf(tag, fp);
if (func->virtuality == DW_VIRTUALITY_virtual ||
func->virtuality == DW_VIRTUALITY_pure_virtual)
--
2.54.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PAHOLE v5 2/5] dwarf_loader: Extract die__add_btf_type_tag() helper [NFC]
2026-06-18 0:57 [PAHOLE v5 0/5] support for DW_TAG_GNU_annotation and fixes Vineet Gupta
2026-06-18 0:57 ` [PAHOLE v5 1/5] btf_loader: Handle decl tag component_idx for parameters Vineet Gupta
@ 2026-06-18 0:57 ` Vineet Gupta
2026-06-18 0:57 ` [PAHOLE v5 3/5] dwarf_loader: Add support for DW_TAG_GNU_annotation Vineet Gupta
` (2 subsequent siblings)
4 siblings, 0 replies; 12+ messages in thread
From: Vineet Gupta @ 2026-06-18 0:57 UTC (permalink / raw)
To: dwarves
Cc: bpf, Andrii Nakryiko, acme, Alan Maguire, Emil Tsalapatis,
jose.marchesi, David Faust, Yonghong Song, Vineet Gupta
NFC change preparing for DW_TAG_GNU_annotation support.
Extract the btf_type_tag annotation creation logic into helper
die__add_btf_type_tag().
Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
Acked-by: Yonghong Song <yonghong.song@linux.dev>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
---
Changes since v [4]
- Collected the review tags [Emil, Yonghong]
Changes since v3 [3]
- Fix comment to kernel style [Arnaldo]
Changes since v2 [2]
- die__add_btf_type_tag() returns pointer not error code [Alan]
Changes since v1 [1]
- NFC reinstate some original comments
[4] https://lore.kernel.org/bpf/20260602195512.1511013-1-vineet.gupta@linux.dev/
[3] https://lore.kernel.org/bpf/20260601183511.594100-1-vineet.gupta@linux.dev/
[2] https://lore.kernel.org/bpf/20260528223616.2035618-1-vineet.gupta@linux.dev/
[1] https://lore.kernel.org/bpf/20260526181818.4159927-1-vineet.gupta@linux.dev/
---
dwarf_loader.c | 58 +++++++++++++++++++++++++++++---------------------
1 file changed, 34 insertions(+), 24 deletions(-)
diff --git a/dwarf_loader.c b/dwarf_loader.c
index 16fb7becffee..42a0f3f74ce3 100644
--- a/dwarf_loader.c
+++ b/dwarf_loader.c
@@ -1600,14 +1600,44 @@ static struct btf_type_tag_type *die__create_new_btf_type_tag_type(Dwarf_Die *di
return tag;
}
+static struct btf_type_tag_ptr_type *die__add_btf_type_tag(struct btf_type_tag_ptr_type *tag,
+ Dwarf_Die *die, Dwarf_Die *adie,
+ struct cu *cu, struct conf_load *conf)
+{
+ struct btf_type_tag_type *annot;
+ uint32_t id;
+
+ if (tag == NULL) {
+ tag = die__create_new_btf_type_tag_ptr_type(die, cu);
+ if (!tag)
+ return NULL;
+ }
+
+ annot = die__create_new_btf_type_tag_type(adie, cu, conf);
+ if (annot == NULL)
+ return NULL;
+
+ if (cu__table_add_tag(cu, &annot->tag, &id) < 0)
+ return NULL;
+
+ struct dwarf_tag *dtag = tag__dwarf(&annot->tag);
+ dtag->small_id = id;
+ cu__hash(cu, &annot->tag);
+
+ /*
+ * Prepends: for annotations tag1 -> tag2 -> tag3,
+ * the tag->tags list ends up as tag3 -> tag2 -> tag1.
+ */
+ list_add(&annot->node, &tag->tags);
+ return tag;
+}
+
static struct tag *die__create_new_pointer_tag(Dwarf_Die *die, struct cu *cu,
struct conf_load *conf)
{
struct btf_type_tag_ptr_type *tag = NULL;
- struct btf_type_tag_type *annot;
Dwarf_Die *cdie, child;
const char *name;
- uint32_t id;
/* If no child tags or skipping btf_type_tag encoding, just create a new tag
* and return
@@ -1627,29 +1657,9 @@ static struct tag *die__create_new_pointer_tag(Dwarf_Die *die, struct cu *cu,
if (strcmp(name, "btf_type_tag") != 0)
continue;
- if (tag == NULL) {
- /* Create a btf_type_tag_ptr type. */
- tag = die__create_new_btf_type_tag_ptr_type(die, cu);
- if (!tag)
- return NULL;
- }
-
- /* Create a btf_type_tag type for this annotation. */
- annot = die__create_new_btf_type_tag_type(cdie, cu, conf);
- if (annot == NULL)
- return NULL;
-
- if (cu__table_add_tag(cu, &annot->tag, &id) < 0)
+ tag = die__add_btf_type_tag(tag, die, cdie, cu, conf);
+ if (tag == NULL)
return NULL;
-
- struct dwarf_tag *dtag = tag__dwarf(&annot->tag);
- dtag->small_id = id;
- cu__hash(cu, &annot->tag);
-
- /* For a list of DW_TAG_LLVM_annotation like tag1 -> tag2 -> tag3,
- * the tag->tags contains tag3 -> tag2 -> tag1.
- */
- list_add(&annot->node, &tag->tags);
} while (dwarf_siblingof(cdie, cdie) == 0);
return tag ? &tag->tag : tag__new(die, cu);
--
2.54.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PAHOLE v5 3/5] dwarf_loader: Add support for DW_TAG_GNU_annotation
2026-06-18 0:57 [PAHOLE v5 0/5] support for DW_TAG_GNU_annotation and fixes Vineet Gupta
2026-06-18 0:57 ` [PAHOLE v5 1/5] btf_loader: Handle decl tag component_idx for parameters Vineet Gupta
2026-06-18 0:57 ` [PAHOLE v5 2/5] dwarf_loader: Extract die__add_btf_type_tag() helper [NFC] Vineet Gupta
@ 2026-06-18 0:57 ` Vineet Gupta
2026-06-18 0:57 ` [PAHOLE v5 4/5] tests: Support GCC in pfunct-btf-decl-tags test Vineet Gupta
2026-06-18 0:57 ` [PAHOLE v5 5/5] tests: Add btf_type_tag ordering test Vineet Gupta
4 siblings, 0 replies; 12+ messages in thread
From: Vineet Gupta @ 2026-06-18 0:57 UTC (permalink / raw)
To: dwarves
Cc: bpf, Andrii Nakryiko, acme, Alan Maguire, Emil Tsalapatis,
jose.marchesi, David Faust, Yonghong Song, Vineet Gupta
gcc 16 was the first release to support DW_TAG_GNU_annotations and this
patch enables the same in pahole. Bulk of changes are dwarf_loader but
btf_encoder also gains support with minimal changes.
GCC encodes btf_type_tag and btf_decl_tag annotations differently from
LLVM. While LLVM uses DW_TAG_LLVM_annotation (0x6000) as child DIEs,
GCC uses DW_TAG_GNU_annotation (0x6001) as standalone sibling DIEs
referenced via DW_AT_GNU_annotation (0x2139) attributes, with chaining
through the same attribute on annotation DIEs themselves.
Handle both encoding styles:
For btf_type_tag (pointer annotations):
- Recognize DW_TAG_GNU_annotation alongside DW_TAG_LLVM_annotation in
child annotation scanning.
- Follow DW_AT_GNU_annotation attribute chains on pointer types for
GCC-style btf_type_tag resolution.
- Normalize DW_TAG_GNU_annotation to DW_TAG_LLVM_annotation in the
internal representation so downstream code works unchanged.
- Preserve btf_type_tag emission order across both formats: LLVM child
DIEs come in source order and are prepended (reversed) into the tag
list, while a GCC DW_AT_GNU_annotation chain is already in BTF order
and is appended. die__add_btf_type_tag() takes a 'prepend' argument
to select between the two.
For btf_decl_tag (function/struct/member annotations):
- Add add_gnu_annotation_chain() to follow DW_AT_GNU_annotation
attribute chains on function, struct, and member DIEs.
- GCC puts DW_AT_GNU_annotation on the function/struct DIE itself
(not as child DIEs), referencing sibling annotation DIEs that chain
via the same attribute.
- Follow DW_AT_GNU_annotation chains on formal parameter DIEs so that
GCC-style parameter decl tags are loaded too.
Also:
- Silently skip standalone DW_TAG_GNU_annotation DIEs at CU level.
- Add tag__is_annotation() helper macro for annotation tag checks.
- Rename add_llvm_annotation -> add_tag_annotation,
skip_llvm_annotations -> skip_tag_annotations since these now
handle both LLVM and GNU annotation formats.
Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
Acked-by: Yonghong Song <yonghong.song@linux.dev>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
---
Changes since v4 [4]
- Handle gcc-style function paramter tags [Alan]
- Handle multi tag ordering correctly for LLVM and GCC [Alan]
- Collected the review tags [Emil, Yonghong]
Changes since v3 [3]
- Add helper tag__is_annotation [Emil]
- Rename some functions containing "llvm" as they are common to LLVM/GCC tags [Emil]
- Deduplicate checks before loop and inside loop in add_gnu_annotation_chain() and check_gnu_attr [Arnaldo]
- Fix some typos and move some comments [Emi]
Changes since v2 [2]
- Removed loop detection logic [Alan]
- Move test changes to different patch [Alan]
Changes since v1 [1]
- NFC Reduce indentation with early exits (Alexei offlist)
[4] https://lore.kernel.org/bpf/20260602195512.1511013-2-vineet.gupta@linux.dev/
[3] https://lore.kernel.org/bpf/20260601183511.594100-2-vineet.gupta@linux.dev/
[2] https://lore.kernel.org/bpf/20260528223616.2035618-2-vineet.gupta@linux.dev/
[1] https://lore.kernel.org/bpf/20260526181818.4159927-2-vineet.gupta@linux.dev/
---
btf_encoder.c | 1 +
dutil.h | 11 ++++
dwarf_loader.c | 141 +++++++++++++++++++++++++++++++++++++++-------
dwarves.h | 2 +-
dwarves_fprintf.c | 12 ++--
5 files changed, 141 insertions(+), 26 deletions(-)
diff --git a/btf_encoder.c b/btf_encoder.c
index 633bc6162ce0..d5af706d7638 100644
--- a/btf_encoder.c
+++ b/btf_encoder.c
@@ -1831,6 +1831,7 @@ static int btf_encoder__encode_tag(struct btf_encoder *encoder, struct tag *tag,
name = namespace__name(tag__namespace(tag));
return btf_encoder__add_ref_type(encoder, BTF_KIND_TYPEDEF, ref_type_id, name, false);
case DW_TAG_LLVM_annotation:
+ case DW_TAG_GNU_annotation:
name = tag__btf_type_tag(tag)->value;
return btf_encoder__add_ref_type(encoder, BTF_KIND_TYPE_TAG, ref_type_id, name, false);
case DW_TAG_structure_type:
diff --git a/dutil.h b/dutil.h
index ff78aa6dfd10..be02c68cf4a7 100644
--- a/dutil.h
+++ b/dutil.h
@@ -35,6 +35,17 @@
#define DW_TAG_LLVM_annotation 0x6000
#endif
+#ifndef DW_TAG_GNU_annotation
+#define DW_TAG_GNU_annotation 0x6001
+#endif
+
+#ifndef DW_AT_GNU_annotation
+#define DW_AT_GNU_annotation 0x2139
+#endif
+
+#define tag__is_annotation(tag) \
+ ((tag) == DW_TAG_LLVM_annotation || (tag) == DW_TAG_GNU_annotation)
+
static inline __attribute__((const)) bool is_power_of_2(unsigned long n)
{
return (n != 0 && ((n & (n - 1)) == 0));
diff --git a/dwarf_loader.c b/dwarf_loader.c
index 42a0f3f74ce3..8ce34cbb8ed6 100644
--- a/dwarf_loader.c
+++ b/dwarf_loader.c
@@ -908,7 +908,12 @@ static int tag__recode_dwarf_bitfield(struct tag *tag, struct cu *cu, uint16_t b
return -ENOMEM;
}
-static int add_llvm_annotation(Dwarf_Die *die, int component_idx, struct conf_load *conf,
+static bool die__tag_is_annotation(Dwarf_Die *die)
+{
+ return tag__is_annotation(dwarf_tag(die));
+}
+
+static int add_tag_annotation(Dwarf_Die *die, int component_idx, struct conf_load *conf,
struct list_head *head)
{
struct llvm_annotation *annot;
@@ -943,16 +948,48 @@ static int add_child_llvm_annotations(Dwarf_Die *die, int component_idx,
die = &child;
do {
- if (dwarf_tag(die) == DW_TAG_LLVM_annotation) {
- ret = add_llvm_annotation(die, component_idx, conf, head);
- if (ret)
- return ret;
- }
+ if (!die__tag_is_annotation(die))
+ continue;
+
+ ret = add_tag_annotation(die, component_idx, conf, head);
+ if (ret)
+ return ret;
} while (dwarf_siblingof(die, die) == 0);
return 0;
}
+/*
+ * Handle gcc style btf_decl_tag annotations attached directly to a DIE via
+ * the DW_AT_GNU_annotation attribute chain: functions, function parameters
+ * and struct/union members.
+ *
+ * Note: gcc does not yet emit decl tags for a whole struct/union or for a
+ * typedef, so calling this on such a DIE is harmless - the attribute is
+ * simply absent and the chain is empty.
+ *
+ * Pointers (btf_type_tag) are handled separately, inline in
+ * die__create_new_pointer_tag().
+ */
+static int add_gnu_annotation_chain(Dwarf_Die *die, int component_idx,
+ struct conf_load *conf, struct list_head *head)
+{
+ Dwarf_Attribute attr;
+ Dwarf_Die annot_die;
+
+ while (dwarf_attr(die, DW_AT_GNU_annotation, &attr) != NULL &&
+ dwarf_formref_die(&attr, &annot_die) != NULL &&
+ dwarf_tag(&annot_die) == DW_TAG_GNU_annotation) {
+ int ret = add_tag_annotation(&annot_die, component_idx, conf, head);
+ if (ret)
+ return ret;
+
+ die = &annot_die;
+ }
+
+ return 0;
+}
+
int class_member__dwarf_recode_bitfield(struct class_member *member,
struct cu *cu)
{
@@ -1596,13 +1633,16 @@ static struct btf_type_tag_type *die__create_new_btf_type_tag_type(Dwarf_Die *di
return NULL;
tag__init(&tag->tag, cu, die);
+ /* Normalize DW_TAG_GNU_annotation to DW_TAG_LLVM_annotation internally */
+ tag->tag.tag = DW_TAG_LLVM_annotation;
tag->value = attr_string(die, DW_AT_const_value, conf);
return tag;
}
static struct btf_type_tag_ptr_type *die__add_btf_type_tag(struct btf_type_tag_ptr_type *tag,
Dwarf_Die *die, Dwarf_Die *adie,
- struct cu *cu, struct conf_load *conf)
+ struct cu *cu, struct conf_load *conf,
+ bool prepend)
{
struct btf_type_tag_type *annot;
uint32_t id;
@@ -1625,10 +1665,23 @@ static struct btf_type_tag_ptr_type *die__add_btf_type_tag(struct btf_type_tag_p
cu__hash(cu, &annot->tag);
/*
- * Prepends: for annotations tag1 -> tag2 -> tag3,
- * the tag->tags list ends up as tag3 -> tag2 -> tag1.
+ * Consider:
+ * struct sample __tag(outer) __tag(inner) *global_ptr;
+ * The BTF chain should describe the pointer as:
+ * PTR -> TYPE_TAG "inner" -> TYPE_TAG "outer" -> STRUCT "sample"
+ * i.e. the tag nearest the '*' wraps the pointee first.
+ *
+ * LLVM emits the child annotation DIEs in source order (outer, inner),
+ * so we prepend to end up with inner -> outer.
+ *
+ * GCC's DW_AT_GNU_annotation chain is already walked from the outermost
+ * BTF wrapper (inner) towards the pointee, so we preserve that order by
+ * appending.
*/
- list_add(&annot->node, &tag->tags);
+ if (prepend)
+ list_add(&annot->node, &tag->tags);
+ else
+ list_add_tail(&annot->node, &tag->tags);
return tag;
}
@@ -1637,19 +1690,21 @@ static struct tag *die__create_new_pointer_tag(Dwarf_Die *die, struct cu *cu,
{
struct btf_type_tag_ptr_type *tag = NULL;
Dwarf_Die *cdie, child;
+ Dwarf_Attribute attr;
+ Dwarf_Die annot_die;
const char *name;
- /* If no child tags or skipping btf_type_tag encoding, just create a new tag
- * and return
- */
- if (!dwarf_haschildren(die) || dwarf_child(die, &child) != 0 ||
- conf->skip_encoding_btf_type_tag)
+ /* If skipping btf_type_tag encoding, just create a new tag, return */
+ if (conf->skip_encoding_btf_type_tag)
return tag__new(die, cu);
- /* Otherwise, check DW_TAG_LLVM_annotation child tags */
+ if (!dwarf_haschildren(die) || dwarf_child(die, &child) != 0)
+ goto check_gnu_attr;
+
+ /* Handle LLVM style annotation tags if present */
cdie = &child;
do {
- if (dwarf_tag(cdie) != DW_TAG_LLVM_annotation)
+ if (!die__tag_is_annotation(cdie))
continue;
/* Only check btf_type_tag annotations */
@@ -1657,11 +1712,33 @@ static struct tag *die__create_new_pointer_tag(Dwarf_Die *die, struct cu *cu,
if (strcmp(name, "btf_type_tag") != 0)
continue;
- tag = die__add_btf_type_tag(tag, die, cdie, cu, conf);
+ /* LLVM child DIEs are in source order; prepend to reverse. */
+ tag = die__add_btf_type_tag(tag, die, cdie, cu, conf, true);
if (tag == NULL)
return NULL;
} while (dwarf_siblingof(cdie, cdie) == 0);
+check_gnu_attr:
+ if (tag != NULL)
+ goto out;
+
+ /* Handle GCC-style DW_AT_GNU_annotation attribute */
+ while (dwarf_attr(die, DW_AT_GNU_annotation, &attr) != NULL &&
+ dwarf_formref_die(&attr, &annot_die) != NULL &&
+ dwarf_tag(&annot_die) == DW_TAG_GNU_annotation) {
+ name = attr_string(&annot_die, DW_AT_name, conf);
+ if (strcmp(name, "btf_type_tag") != 0)
+ break;
+
+ /* GCC chain is already in BTF order; append to preserve it. */
+ tag = die__add_btf_type_tag(tag, die, &annot_die, cu, conf, false);
+ if (tag == NULL)
+ return NULL;
+
+ die = &annot_die;
+ }
+
+out:
return tag ? &tag->tag : tag__new(die, cu);
}
@@ -1690,6 +1767,12 @@ static struct tag *die__create_new_class(Dwarf_Die *die, struct cu *cu, struct c
}
}
+ if (class != NULL &&
+ add_gnu_annotation_chain(die, -1, conf, &class->type.namespace.annots) != 0) {
+ class__delete(class, cu);
+ class = NULL;
+ }
+
return class ? &class->type.namespace.tag : NULL;
}
@@ -1822,6 +1905,8 @@ static struct tag *die__create_new_parameter(Dwarf_Die *die,
if (param_idx >= 0) {
if (add_child_llvm_annotations(die, param_idx, conf, &(tag__function(&ftype->tag)->annots)))
return NULL;
+ if (add_gnu_annotation_chain(die, param_idx, conf, &(tag__function(&ftype->tag)->annots)))
+ return NULL;
}
} else {
/*
@@ -2051,11 +2136,14 @@ static int die__process_class(Dwarf_Die *die, struct type *class,
cu__hash(cu, &member->tag);
if (add_child_llvm_annotations(die, member_idx, conf, &class->namespace.annots))
return -ENOMEM;
+ if (add_gnu_annotation_chain(die, member_idx, conf, &class->namespace.annots))
+ return -ENOMEM;
member_idx++;
}
continue;
case DW_TAG_LLVM_annotation:
- if (add_llvm_annotation(die, -1, conf, &class->namespace.annots))
+ case DW_TAG_GNU_annotation:
+ if (add_tag_annotation(die, -1, conf, &class->namespace.annots))
return -ENOMEM;
continue;
default: {
@@ -2360,7 +2448,8 @@ static int die__process_function(Dwarf_Die *die, struct ftype *ftype,
goto out_enomem;
continue;
case DW_TAG_LLVM_annotation:
- if (add_llvm_annotation(die, -1, conf, &(tag__function(&ftype->tag)->annots)))
+ case DW_TAG_GNU_annotation:
+ if (add_tag_annotation(die, -1, conf, &(tag__function(&ftype->tag)->annots)))
goto out_enomem;
continue;
default:
@@ -2408,6 +2497,12 @@ static struct tag *die__create_new_function(Dwarf_Die *die, struct cu *cu, struc
function = NULL;
}
+ if (function != NULL &&
+ add_gnu_annotation_chain(die, -1, conf, &function->annots) != 0) {
+ function__delete(function, cu);
+ function = NULL;
+ }
+
return function ? &function->proto.tag : NULL;
}
@@ -2469,6 +2564,9 @@ static struct tag *__die__process_tag(Dwarf_Die *die, struct cu *cu,
*/
tag = &unsupported_tag;
break;
+ case DW_TAG_GNU_annotation:
+ tag = &unsupported_tag;
+ break;
case DW_TAG_label:
if (conf->ignore_labels)
tag = &unsupported_tag; // callers will assume conf->ignore_labels is true
@@ -2494,7 +2592,8 @@ static int die__process_unit(Dwarf_Die *die, struct cu *cu, struct conf_load *co
// XXX special case DW_TAG_dwarf_procedure, appears when looking at a recent ~/bin/perf
// Investigate later how to properly support this...
if (dwarf_tag(die) != DW_TAG_dwarf_procedure &&
- dwarf_tag(die) != DW_TAG_label) // conf->ignore_labels == true, see die__process_tag()
+ dwarf_tag(die) != DW_TAG_label && // conf->ignore_labels == true, see die__process_tag()
+ dwarf_tag(die) != DW_TAG_GNU_annotation)
tag__print_not_supported(die);
continue;
}
diff --git a/dwarves.h b/dwarves.h
index 5ec16e750e83..75c311a2f8ee 100644
--- a/dwarves.h
+++ b/dwarves.h
@@ -670,7 +670,7 @@ static inline int tag__is_tag_type(const struct tag *tag)
tag->tag == DW_TAG_volatile_type ||
tag->tag == DW_TAG_atomic_type ||
tag->tag == DW_TAG_unspecified_type ||
- tag->tag == DW_TAG_LLVM_annotation;
+ tag__is_annotation(tag->tag);
}
static inline const char *tag__decl_file(const struct tag *tag,
diff --git a/dwarves_fprintf.c b/dwarves_fprintf.c
index 54f483244bd2..ab1c381db646 100644
--- a/dwarves_fprintf.c
+++ b/dwarves_fprintf.c
@@ -140,6 +140,8 @@ const char *dwarf_tag_name(const uint32_t tag)
return dwarf_gnu_tag_names[tag - DW_TAG_MIPS_loop];
else if (tag == DW_TAG_LLVM_annotation)
return "LLVM_annotation";
+ else if (tag == DW_TAG_GNU_annotation)
+ return "GNU_annotation";
return "INVALID";
}
@@ -658,6 +660,7 @@ static const char *__tag__name(const struct tag *tag, const struct cu *cu,
snprintf(bf, len, "%s", variable__name(tag__variable(tag)));
break;
case DW_TAG_LLVM_annotation:
+ case DW_TAG_GNU_annotation:
type = cu__type(cu, tag->type);
if (type == NULL && tag->type != 0)
tag__id_not_found_snprintf(bf, len, tag->type);
@@ -723,7 +726,7 @@ static size_t type__fprintf_stats(struct type *type, const struct cu *cu,
return printed;
}
-static type_id_t skip_llvm_annotations(const struct cu *cu, type_id_t id)
+static type_id_t skip_tag_annotations(const struct cu *cu, type_id_t id)
{
struct tag *type;
@@ -731,7 +734,7 @@ static type_id_t skip_llvm_annotations(const struct cu *cu, type_id_t id)
if (id == 0)
break;
type = cu__type(cu, id);
- if (type == NULL || type->tag != DW_TAG_LLVM_annotation || type->type == id)
+ if (type == NULL || !tag__is_annotation(type->tag) || type->type == id)
break;
id = type->type;
}
@@ -838,7 +841,7 @@ inner_struct:
next_type:
switch (type->tag) {
case DW_TAG_pointer_type: {
- type_id_t ptype_id = skip_llvm_annotations(cu, type->type);
+ type_id_t ptype_id = skip_tag_annotations(cu, type->type);
if (ptype_id != 0) {
int n;
@@ -936,7 +939,8 @@ print_modifier: {
else
printed += enumeration__fprintf(type, &tconf, fp);
break;
- case DW_TAG_LLVM_annotation: {
+ case DW_TAG_LLVM_annotation:
+ case DW_TAG_GNU_annotation: {
struct tag *ttype = cu__type(cu, type->type);
if (ttype) {
type = ttype;
--
2.54.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PAHOLE v5 4/5] tests: Support GCC in pfunct-btf-decl-tags test
2026-06-18 0:57 [PAHOLE v5 0/5] support for DW_TAG_GNU_annotation and fixes Vineet Gupta
` (2 preceding siblings ...)
2026-06-18 0:57 ` [PAHOLE v5 3/5] dwarf_loader: Add support for DW_TAG_GNU_annotation Vineet Gupta
@ 2026-06-18 0:57 ` Vineet Gupta
2026-06-18 0:57 ` [PAHOLE v5 5/5] tests: Add btf_type_tag ordering test Vineet Gupta
4 siblings, 0 replies; 12+ messages in thread
From: Vineet Gupta @ 2026-06-18 0:57 UTC (permalink / raw)
To: dwarves
Cc: bpf, Andrii Nakryiko, acme, Alan Maguire, Emil Tsalapatis,
jose.marchesi, David Faust, Yonghong Song, Vineet Gupta
GCC 16+ supports btf_decl_tag via DW_TAG_GNU_annotation. Update the
test to run with both GCC (>= 16) and clang when available, instead
of requiring clang only.
Compile the clang case natively and encode BTF with "pahole -J" (like
the GCC case) rather than emitting BPF-target BTF directly, so both
compilers exercise the same DWARF -> BTF path.
Add a function with a parameter decl tag (qux) to cover decl tags that
carry a component_idx, and make the awk post-processing pass through
lines that have no leading tags.
Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
Acked-by: Yonghong Song <yonghong.song@linux.dev>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
---
Changes since v4 [4]
- Test function param decl tag [Alan]
- Missing "pahole -j" for clang [Yonghong]
- Collected the review tags [Emil, Yonghong]
[4] https://lore.kernel.org/bpf/20260602195512.1511013-3-vineet.gupta@linux.dev/
---
tests/pfunct-btf-decl-tags.sh | 93 ++++++++++++++++++++++++++---------
1 file changed, 70 insertions(+), 23 deletions(-)
diff --git a/tests/pfunct-btf-decl-tags.sh b/tests/pfunct-btf-decl-tags.sh
index 35884b4e8687..520148b2ccef 100755
--- a/tests/pfunct-btf-decl-tags.sh
+++ b/tests/pfunct-btf-decl-tags.sh
@@ -6,43 +6,60 @@
source test_lib.sh
outdir=$(make_tmpdir)
-tmpobj=$(make_tmpobj)
# Comment this out to save test data.
trap cleanup EXIT
title_log "Check that pfunct can print btf_decl_tags read from BTF."
-# gcc now also supports decl tags as of gcc commit 43dcea48b8c,
-# in upstream version 16.
-# UPTODO: add a check here for that.
+# gcc 16+ supports decl tags via DW_TAG_GNU_annotation (gcc commit ac7027f180b).
+GCC=${GCC:-gcc}
CLANG=${CLANG:-clang}
-if ! command -v $CLANG > /dev/null; then
- error_log "Need clang for test $0"
+
+use_gcc=0
+if command -v $GCC > /dev/null; then
+ gcc_ver=$($GCC -dumpversion 2>/dev/null | cut -d. -f1)
+ if [ "$gcc_ver" -ge 16 ] 2>/dev/null; then
+ use_gcc=1
+ fi
+fi
+
+use_clang=0
+if command -v $CLANG > /dev/null; then
+ use_clang=1
+fi
+
+if [ "$use_gcc" -eq 0 ] && [ "$use_clang" -eq 0 ]; then
+ error_log "Need gcc >= 16 or clang for test $0"
test_fail
fi
-(cat <<EOF
+src=$(cat <<EOF
#define __tag(x) __attribute__((btf_decl_tag(#x)))
__tag(a) __tag(b) __tag(c) void foo(void) {}
__tag(a) __tag(b) void bar(void) {}
__tag(a) void buz(void) {}
+void qux(int __tag(param_a) arg) {}
EOF
-) | $CLANG --target=bpf -c -g -x c -o $tmpobj -
+)
# tags order is not guaranteed
sort_tags=$(cat <<EOF
{
-match(\$0,/^(.*) (void .*)/,tags_and_proto);
-tags = tags_and_proto[1];
-proto = tags_and_proto[2];
-split(tags, tags_arr ,/ /);
-asort(tags_arr);
-for (t in tags_arr) printf "%s ", tags_arr[t];
-print proto;
+delete tags_arr;
+if (match(\$0,/^(.*) (void .*)/,tags_and_proto)) {
+ tags = tags_and_proto[1];
+ proto = tags_and_proto[2];
+ split(tags, tags_arr ,/ /);
+ asort(tags_arr);
+ for (t in tags_arr) printf "%s ", tags_arr[t];
+ print proto;
+} else {
+ print \$0;
+}
}
EOF
)
@@ -51,19 +68,49 @@ expected=$(cat <<EOF
a b c void foo(void);
a b void bar(void);
a void buz(void);
+void qux(param_a int arg);
EOF
)
-out=$(pfunct -P -F btf $tmpobj | awk "$sort_tags" | sort)
-d=$(diff -u <(echo "$expected") <(echo "$out"))
+run_test() {
+ local compiler=$1
+ local tmpobj=$2
+
+ info_log "Testing with $compiler"
+ out=$(pfunct -P -F btf $tmpobj | awk "$sort_tags" | sort)
+ d=$(diff -u <(echo "$expected") <(echo "$out"))
+
+ if [[ "$d" == "" ]]; then
+ info_log " passed"
+ return 0
+ else
+ error_log "pfunct output does not match expected ($compiler):"
+ info_log "$d"
+ info_log
+ info_log "Complete output:"
+ info_log "$out"
+ return 1
+ fi
+}
+
+failed=0
+
+if [ "$use_gcc" -eq 1 ]; then
+ tmpobj=$(make_tmpobj)
+ echo "$src" | $GCC -c -g -x c -o $tmpobj - 2>/dev/null
+ pahole -J $tmpobj 2>/dev/null
+ run_test "$GCC (version $gcc_ver)" "$tmpobj" || failed=1
+fi
+
+if [ "$use_clang" -eq 1 ]; then
+ tmpobj=$(make_tmpobj)
+ echo "$src" | $CLANG -c -g -x c -o $tmpobj -
+ pahole -J $tmpobj 2>/dev/null
+ run_test "$CLANG" "$tmpobj" || failed=1
+fi
-if [[ "$d" == "" ]]; then
+if [ "$failed" -eq 0 ]; then
test_pass
else
- error_log "pfunct output does not match expected:"
- info_log "$d"
- info_log
- info_log "Complete output:"
- info_log "$out"
test_fail
fi
--
2.54.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PAHOLE v5 5/5] tests: Add btf_type_tag ordering test
2026-06-18 0:57 [PAHOLE v5 0/5] support for DW_TAG_GNU_annotation and fixes Vineet Gupta
` (3 preceding siblings ...)
2026-06-18 0:57 ` [PAHOLE v5 4/5] tests: Support GCC in pfunct-btf-decl-tags test Vineet Gupta
@ 2026-06-18 0:57 ` Vineet Gupta
2026-06-18 4:47 ` Emil Tsalapatis
4 siblings, 1 reply; 12+ messages in thread
From: Vineet Gupta @ 2026-06-18 0:57 UTC (permalink / raw)
To: dwarves
Cc: bpf, Andrii Nakryiko, acme, Alan Maguire, Emil Tsalapatis,
jose.marchesi, David Faust, Yonghong Song, Vineet Gupta
From: Alan Maguire <alan.maguire@oracle.com>
Add a test that compiles a pointer carrying two btf_type_tags
(__tag(outer) __tag(inner)) and checks the BTF that pahole emits to
ensure the tag chain is PTR -> TYPE_TAG inner -> TYPE_TAG outer ->
struct sample, i.e. the innermost tag is closest to the pointer.
This exercises the type_tag ordering for both encodings: LLVM emits the
annotations as child DIEs in source order (reversed when building the
tag list), while GCC chains them via DW_AT_GNU_annotation already in BTF
order. The test runs with gcc and clang when they support btf_type_tag,
and is skipped when bpftool is unavailable.
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
---
tests/btf_type_tag_order.sh | 179 ++++++++++++++++++++++++++++++++++++
1 file changed, 179 insertions(+)
create mode 100755 tests/btf_type_tag_order.sh
diff --git a/tests/btf_type_tag_order.sh b/tests/btf_type_tag_order.sh
new file mode 100755
index 000000000000..09d1ac346000
--- /dev/null
+++ b/tests/btf_type_tag_order.sh
@@ -0,0 +1,179 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-only
+
+# Check that pahole preserves btf_type_tag order when emitting BTF from DWARF.
+
+source test_lib.sh
+
+outdir=$(make_tmpdir)
+
+# Comment this out to save test data.
+trap cleanup EXIT
+
+title_log "Check BTF type tag order."
+
+GCC=${GCC:-gcc}
+CLANG=${CLANG:-clang}
+PAHOLE=${PAHOLE:-pahole}
+BPFTOOL=${BPFTOOL:-bpftool}
+
+if ! command -v "$BPFTOOL" > /dev/null; then
+ info_log "skip: bpftool not available"
+ test_skip
+fi
+
+compiler_has_btf_type_tag()
+{
+ local compiler=$1
+
+ if ! command -v "$compiler" > /dev/null; then
+ return 1
+ fi
+
+ "$compiler" -x c -E -P - <<'EOF' 2>/dev/null | grep -qx 1
+#ifndef __has_attribute
+#define __has_attribute(x) 0
+#endif
+#if __has_attribute(btf_type_tag)
+1
+#else
+0
+#endif
+EOF
+}
+
+use_gcc=0
+if compiler_has_btf_type_tag "$GCC"; then
+ use_gcc=1
+fi
+
+use_clang=0
+if compiler_has_btf_type_tag "$CLANG"; then
+ use_clang=1
+fi
+
+if [ "$use_gcc" -eq 0 ] && [ "$use_clang" -eq 0 ]; then
+ error_log "Need gcc or clang with btf_type_tag support for test $0"
+ test_fail
+fi
+
+src=$(cat <<EOF
+#define __tag(x) __attribute__((btf_type_tag(#x)))
+
+struct sample {
+ int value;
+};
+
+struct sample __tag(outer) __tag(inner) *global_ptr;
+
+EOF
+)
+
+check_type_tag_order()
+{
+ local btf=$1
+ local dump
+
+ if ! dump=$("$BPFTOOL" btf dump file "$btf"); then
+ return 1
+ fi
+
+ printf '%s\n' "$dump" | awk '
+ function parse_id(line, m) {
+ if (match(line, /^\[([0-9]+)\]/, m))
+ return m[1]
+ return 0
+ }
+ function parse_name(line, m) {
+ if (match(line, /\047([^\047]*)\047/, m))
+ return m[1]
+ return ""
+ }
+ function parse_type(line, m) {
+ if (match(line, /type_id=([0-9]+)/, m))
+ return m[1]
+ return 0
+ }
+ function check_ptr(ptr, id, tags, seen) {
+ id = type[ptr]
+ while (id != 0 && !seen[id]) {
+ seen[id] = 1
+ if (kind[id] == "TYPE_TAG") {
+ tags = tags (tags == "" ? "" : " -> ") name[id]
+ id = type[id]
+ continue
+ }
+ if (kind[id] == "STRUCT" && name[id] == "sample") {
+ if (tags == "inner -> outer")
+ exit 0
+ candidates = candidates (candidates == "" ? "" : ", ") tags
+ }
+ return
+ }
+ }
+ /^\[[0-9]+\]/ {
+ id = parse_id($0)
+ kind[id] = $2
+ name[id] = parse_name($0)
+ type[id] = parse_type($0)
+ if (kind[id] == "PTR")
+ ptrs[++nr_ptrs] = id
+ }
+ END {
+ for (i = 1; i <= nr_ptrs; i++)
+ check_ptr(ptrs[i])
+ if (candidates != "") {
+ print "type tag order mismatch; expected inner -> outer, found " candidates > "/dev/stderr"
+ exit 1
+ }
+ print "could not find tagged pointer to struct sample" > "/dev/stderr"
+ exit 1
+ }'
+}
+
+run_test()
+{
+ local compiler=$1
+ local tmpobj=$2
+ local btf=$3
+
+ info_log "Testing with $compiler"
+
+ if ! echo "$src" | "$compiler" -g -c -x c -o "$tmpobj" - 2>/dev/null; then
+ error_log "Could not compile type tag order test with $compiler"
+ return 1
+ fi
+
+ if ! "$PAHOLE" --btf_features=+type_tag --btf_encode_detached="$btf" "$tmpobj" 2>/dev/null; then
+ error_log "Could not encode BTF for $tmpobj"
+ return 1
+ fi
+
+ if check_type_tag_order "$btf"; then
+ info_log " passed"
+ return 0
+ fi
+
+ error_log "BTF type tag order does not match expected order ($compiler)"
+ return 1
+}
+
+failed=0
+
+if [ "$use_gcc" -eq 1 ]; then
+ tmpobj=$(make_tmpobj)
+ btf=${tmpobj%.o}.btf
+ run_test "$GCC" "$tmpobj" "$btf" || failed=1
+fi
+
+if [ "$use_clang" -eq 1 ]; then
+ tmpobj=$(make_tmpobj)
+ btf=${tmpobj%.o}.btf
+ run_test "$CLANG" "$tmpobj" "$btf" || failed=1
+fi
+
+if [ "$failed" -eq 0 ]; then
+ test_pass
+else
+ test_fail
+fi
--
2.54.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PAHOLE v5 1/5] btf_loader: Handle decl tag component_idx for parameters
2026-06-18 0:57 ` [PAHOLE v5 1/5] btf_loader: Handle decl tag component_idx for parameters Vineet Gupta
@ 2026-06-18 4:46 ` Emil Tsalapatis
2026-06-18 13:27 ` Arnaldo Carvalho de Melo
2026-06-18 14:38 ` Alan Maguire
0 siblings, 2 replies; 12+ messages in thread
From: Emil Tsalapatis @ 2026-06-18 4:46 UTC (permalink / raw)
To: Vineet Gupta, dwarves
Cc: bpf, Andrii Nakryiko, acme, Alan Maguire, Emil Tsalapatis,
jose.marchesi, David Faust, Yonghong Song
On Wed Jun 17, 2026 at 8:57 PM EDT, Vineet Gupta wrote:
> From: Alan Maguire <alan.maguire@oracle.com>
>
> A BTF_KIND_DECL_TAG with a non-negative component_idx applies to a
> specific function parameter (or struct/union member), not to the
> function itself. btf_loader.c however attached every decl tag to the
> type named by btf_type->type, so parameter decl tags were recorded on
> the function rather than on the parameter, and pfunct never printed
> them with the parameter.
>
> Resolve a non-negative component_idx to the corresponding parameter via
> new helpers ftype__parameter()/function__parameter(), and attach the
> tag there. Teach the pretty printer to emit a parameter's attributes by
> factoring the function-level attribute loop into tag__attributes_fprintf()
> and calling it from ftype__fprintf_parms() for each parameter.
>
> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
With one nit:
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
(Also feel free to keep the tags for the other 3 patches since the
changes are minimal).
</SNIP>
> + if (component_idx >= 0) {
> + struct tag *func_tag = cu__function(cu, tp->type);
> +
> + if (func_tag != NULL) {
> + tag = function__parameter(tag__function(func_tag), cu,
> + component_idx);
> + if (tag == NULL) {
> + fprintf(stderr, "WARNING: BTF_KIND_DECL_TAG for unknown parameter %d in BTF id %d\n",
> + component_idx, tp->type);
> + return 0;
> + }
> + }
> + }
> +
> + if (tag == NULL && component_idx < 0)
> tag = cu__function(cu, tp->type);
Nit, I think this can be simplified as follows:
tag = cu__function(cu, tp->type);
if (component_idx >= 0 && tag != NULL) {
tag = function__parameter(tag__function(tag), cu, component_idx);
if (tag == NULL) {
fprintf(stderr, "WARNING: BTF_KIND_DECL_TAG for unknown parameter %d in BTF id %d\n",
component_idx, tp->type);
return 0;
}
}
<SNIP>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PAHOLE v5 5/5] tests: Add btf_type_tag ordering test
2026-06-18 0:57 ` [PAHOLE v5 5/5] tests: Add btf_type_tag ordering test Vineet Gupta
@ 2026-06-18 4:47 ` Emil Tsalapatis
2026-06-18 13:25 ` Arnaldo Carvalho de Melo
0 siblings, 1 reply; 12+ messages in thread
From: Emil Tsalapatis @ 2026-06-18 4:47 UTC (permalink / raw)
To: Vineet Gupta, dwarves
Cc: bpf, Andrii Nakryiko, acme, Alan Maguire, Emil Tsalapatis,
jose.marchesi, David Faust, Yonghong Song
On Wed Jun 17, 2026 at 8:57 PM EDT, Vineet Gupta wrote:
> From: Alan Maguire <alan.maguire@oracle.com>
>
> Add a test that compiles a pointer carrying two btf_type_tags
> (__tag(outer) __tag(inner)) and checks the BTF that pahole emits to
> ensure the tag chain is PTR -> TYPE_TAG inner -> TYPE_TAG outer ->
> struct sample, i.e. the innermost tag is closest to the pointer.
>
> This exercises the type_tag ordering for both encodings: LLVM emits the
> annotations as child DIEs in source order (reversed when building the
> tag list), while GCC chains them via DW_AT_GNU_annotation already in BTF
> order. The test runs with gcc and clang when they support btf_type_tag,
> and is skipped when bpftool is unavailable.
>
> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
> ---
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
> tests/btf_type_tag_order.sh | 179 ++++++++++++++++++++++++++++++++++++
> 1 file changed, 179 insertions(+)
> create mode 100755 tests/btf_type_tag_order.sh
>
> diff --git a/tests/btf_type_tag_order.sh b/tests/btf_type_tag_order.sh
> new file mode 100755
> index 000000000000..09d1ac346000
> --- /dev/null
> +++ b/tests/btf_type_tag_order.sh
> @@ -0,0 +1,179 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0-only
> +
> +# Check that pahole preserves btf_type_tag order when emitting BTF from DWARF.
> +
> +source test_lib.sh
> +
> +outdir=$(make_tmpdir)
> +
> +# Comment this out to save test data.
> +trap cleanup EXIT
> +
> +title_log "Check BTF type tag order."
> +
> +GCC=${GCC:-gcc}
> +CLANG=${CLANG:-clang}
> +PAHOLE=${PAHOLE:-pahole}
> +BPFTOOL=${BPFTOOL:-bpftool}
> +
> +if ! command -v "$BPFTOOL" > /dev/null; then
> + info_log "skip: bpftool not available"
> + test_skip
> +fi
> +
> +compiler_has_btf_type_tag()
> +{
> + local compiler=$1
> +
> + if ! command -v "$compiler" > /dev/null; then
> + return 1
> + fi
> +
> + "$compiler" -x c -E -P - <<'EOF' 2>/dev/null | grep -qx 1
> +#ifndef __has_attribute
> +#define __has_attribute(x) 0
> +#endif
> +#if __has_attribute(btf_type_tag)
> +1
> +#else
> +0
> +#endif
> +EOF
> +}
> +
> +use_gcc=0
> +if compiler_has_btf_type_tag "$GCC"; then
> + use_gcc=1
> +fi
> +
> +use_clang=0
> +if compiler_has_btf_type_tag "$CLANG"; then
> + use_clang=1
> +fi
> +
> +if [ "$use_gcc" -eq 0 ] && [ "$use_clang" -eq 0 ]; then
> + error_log "Need gcc or clang with btf_type_tag support for test $0"
> + test_fail
> +fi
> +
> +src=$(cat <<EOF
> +#define __tag(x) __attribute__((btf_type_tag(#x)))
> +
> +struct sample {
> + int value;
> +};
> +
> +struct sample __tag(outer) __tag(inner) *global_ptr;
> +
> +EOF
> +)
> +
> +check_type_tag_order()
> +{
> + local btf=$1
> + local dump
> +
> + if ! dump=$("$BPFTOOL" btf dump file "$btf"); then
> + return 1
> + fi
> +
> + printf '%s\n' "$dump" | awk '
> + function parse_id(line, m) {
> + if (match(line, /^\[([0-9]+)\]/, m))
> + return m[1]
> + return 0
> + }
> + function parse_name(line, m) {
> + if (match(line, /\047([^\047]*)\047/, m))
> + return m[1]
> + return ""
> + }
> + function parse_type(line, m) {
> + if (match(line, /type_id=([0-9]+)/, m))
> + return m[1]
> + return 0
> + }
> + function check_ptr(ptr, id, tags, seen) {
> + id = type[ptr]
> + while (id != 0 && !seen[id]) {
> + seen[id] = 1
> + if (kind[id] == "TYPE_TAG") {
> + tags = tags (tags == "" ? "" : " -> ") name[id]
> + id = type[id]
> + continue
> + }
> + if (kind[id] == "STRUCT" && name[id] == "sample") {
> + if (tags == "inner -> outer")
> + exit 0
> + candidates = candidates (candidates == "" ? "" : ", ") tags
> + }
> + return
> + }
> + }
> + /^\[[0-9]+\]/ {
> + id = parse_id($0)
> + kind[id] = $2
> + name[id] = parse_name($0)
> + type[id] = parse_type($0)
> + if (kind[id] == "PTR")
> + ptrs[++nr_ptrs] = id
> + }
> + END {
> + for (i = 1; i <= nr_ptrs; i++)
> + check_ptr(ptrs[i])
> + if (candidates != "") {
> + print "type tag order mismatch; expected inner -> outer, found " candidates > "/dev/stderr"
> + exit 1
> + }
> + print "could not find tagged pointer to struct sample" > "/dev/stderr"
> + exit 1
> + }'
> +}
> +
> +run_test()
> +{
> + local compiler=$1
> + local tmpobj=$2
> + local btf=$3
> +
> + info_log "Testing with $compiler"
> +
> + if ! echo "$src" | "$compiler" -g -c -x c -o "$tmpobj" - 2>/dev/null; then
> + error_log "Could not compile type tag order test with $compiler"
> + return 1
> + fi
> +
> + if ! "$PAHOLE" --btf_features=+type_tag --btf_encode_detached="$btf" "$tmpobj" 2>/dev/null; then
> + error_log "Could not encode BTF for $tmpobj"
> + return 1
> + fi
> +
> + if check_type_tag_order "$btf"; then
> + info_log " passed"
> + return 0
> + fi
> +
> + error_log "BTF type tag order does not match expected order ($compiler)"
> + return 1
> +}
> +
> +failed=0
> +
> +if [ "$use_gcc" -eq 1 ]; then
> + tmpobj=$(make_tmpobj)
> + btf=${tmpobj%.o}.btf
> + run_test "$GCC" "$tmpobj" "$btf" || failed=1
> +fi
> +
> +if [ "$use_clang" -eq 1 ]; then
> + tmpobj=$(make_tmpobj)
> + btf=${tmpobj%.o}.btf
> + run_test "$CLANG" "$tmpobj" "$btf" || failed=1
> +fi
> +
> +if [ "$failed" -eq 0 ]; then
> + test_pass
> +else
> + test_fail
> +fi
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PAHOLE v5 5/5] tests: Add btf_type_tag ordering test
2026-06-18 4:47 ` Emil Tsalapatis
@ 2026-06-18 13:25 ` Arnaldo Carvalho de Melo
0 siblings, 0 replies; 12+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-06-18 13:25 UTC (permalink / raw)
To: Emil Tsalapatis
Cc: Vineet Gupta, dwarves, bpf, Andrii Nakryiko, Alan Maguire,
jose.marchesi, David Faust, Yonghong Song
On Thu, Jun 18, 2026 at 12:47:30AM -0400, Emil Tsalapatis wrote:
> On Wed Jun 17, 2026 at 8:57 PM EDT, Vineet Gupta wrote:
> > From: Alan Maguire <alan.maguire@oracle.com>
> >
> > Add a test that compiles a pointer carrying two btf_type_tags
> > (__tag(outer) __tag(inner)) and checks the BTF that pahole emits to
> > ensure the tag chain is PTR -> TYPE_TAG inner -> TYPE_TAG outer ->
> > struct sample, i.e. the innermost tag is closest to the pointer.
> >
> > This exercises the type_tag ordering for both encodings: LLVM emits the
> > annotations as child DIEs in source order (reversed when building the
> > tag list), while GCC chains them via DW_AT_GNU_annotation already in BTF
> > order. The test runs with gcc and clang when they support btf_type_tag,
> > and is skipped when bpftool is unavailable.
> >
> > Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> > Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
> > ---
>
> Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
Acked-by: Arnaldo Carvalho de Melo <acme@redhat.com>
- Arnaldo
> > tests/btf_type_tag_order.sh | 179 ++++++++++++++++++++++++++++++++++++
> > 1 file changed, 179 insertions(+)
> > create mode 100755 tests/btf_type_tag_order.sh
> >
> > diff --git a/tests/btf_type_tag_order.sh b/tests/btf_type_tag_order.sh
> > new file mode 100755
> > index 000000000000..09d1ac346000
> > --- /dev/null
> > +++ b/tests/btf_type_tag_order.sh
> > @@ -0,0 +1,179 @@
> > +#!/bin/bash
> > +# SPDX-License-Identifier: GPL-2.0-only
> > +
> > +# Check that pahole preserves btf_type_tag order when emitting BTF from DWARF.
> > +
> > +source test_lib.sh
> > +
> > +outdir=$(make_tmpdir)
> > +
> > +# Comment this out to save test data.
> > +trap cleanup EXIT
> > +
> > +title_log "Check BTF type tag order."
> > +
> > +GCC=${GCC:-gcc}
> > +CLANG=${CLANG:-clang}
> > +PAHOLE=${PAHOLE:-pahole}
> > +BPFTOOL=${BPFTOOL:-bpftool}
> > +
> > +if ! command -v "$BPFTOOL" > /dev/null; then
> > + info_log "skip: bpftool not available"
> > + test_skip
> > +fi
> > +
> > +compiler_has_btf_type_tag()
> > +{
> > + local compiler=$1
> > +
> > + if ! command -v "$compiler" > /dev/null; then
> > + return 1
> > + fi
> > +
> > + "$compiler" -x c -E -P - <<'EOF' 2>/dev/null | grep -qx 1
> > +#ifndef __has_attribute
> > +#define __has_attribute(x) 0
> > +#endif
> > +#if __has_attribute(btf_type_tag)
> > +1
> > +#else
> > +0
> > +#endif
> > +EOF
> > +}
> > +
> > +use_gcc=0
> > +if compiler_has_btf_type_tag "$GCC"; then
> > + use_gcc=1
> > +fi
> > +
> > +use_clang=0
> > +if compiler_has_btf_type_tag "$CLANG"; then
> > + use_clang=1
> > +fi
> > +
> > +if [ "$use_gcc" -eq 0 ] && [ "$use_clang" -eq 0 ]; then
> > + error_log "Need gcc or clang with btf_type_tag support for test $0"
> > + test_fail
> > +fi
> > +
> > +src=$(cat <<EOF
> > +#define __tag(x) __attribute__((btf_type_tag(#x)))
> > +
> > +struct sample {
> > + int value;
> > +};
> > +
> > +struct sample __tag(outer) __tag(inner) *global_ptr;
> > +
> > +EOF
> > +)
> > +
> > +check_type_tag_order()
> > +{
> > + local btf=$1
> > + local dump
> > +
> > + if ! dump=$("$BPFTOOL" btf dump file "$btf"); then
> > + return 1
> > + fi
> > +
> > + printf '%s\n' "$dump" | awk '
> > + function parse_id(line, m) {
> > + if (match(line, /^\[([0-9]+)\]/, m))
> > + return m[1]
> > + return 0
> > + }
> > + function parse_name(line, m) {
> > + if (match(line, /\047([^\047]*)\047/, m))
> > + return m[1]
> > + return ""
> > + }
> > + function parse_type(line, m) {
> > + if (match(line, /type_id=([0-9]+)/, m))
> > + return m[1]
> > + return 0
> > + }
> > + function check_ptr(ptr, id, tags, seen) {
> > + id = type[ptr]
> > + while (id != 0 && !seen[id]) {
> > + seen[id] = 1
> > + if (kind[id] == "TYPE_TAG") {
> > + tags = tags (tags == "" ? "" : " -> ") name[id]
> > + id = type[id]
> > + continue
> > + }
> > + if (kind[id] == "STRUCT" && name[id] == "sample") {
> > + if (tags == "inner -> outer")
> > + exit 0
> > + candidates = candidates (candidates == "" ? "" : ", ") tags
> > + }
> > + return
> > + }
> > + }
> > + /^\[[0-9]+\]/ {
> > + id = parse_id($0)
> > + kind[id] = $2
> > + name[id] = parse_name($0)
> > + type[id] = parse_type($0)
> > + if (kind[id] == "PTR")
> > + ptrs[++nr_ptrs] = id
> > + }
> > + END {
> > + for (i = 1; i <= nr_ptrs; i++)
> > + check_ptr(ptrs[i])
> > + if (candidates != "") {
> > + print "type tag order mismatch; expected inner -> outer, found " candidates > "/dev/stderr"
> > + exit 1
> > + }
> > + print "could not find tagged pointer to struct sample" > "/dev/stderr"
> > + exit 1
> > + }'
> > +}
> > +
> > +run_test()
> > +{
> > + local compiler=$1
> > + local tmpobj=$2
> > + local btf=$3
> > +
> > + info_log "Testing with $compiler"
> > +
> > + if ! echo "$src" | "$compiler" -g -c -x c -o "$tmpobj" - 2>/dev/null; then
> > + error_log "Could not compile type tag order test with $compiler"
> > + return 1
> > + fi
> > +
> > + if ! "$PAHOLE" --btf_features=+type_tag --btf_encode_detached="$btf" "$tmpobj" 2>/dev/null; then
> > + error_log "Could not encode BTF for $tmpobj"
> > + return 1
> > + fi
> > +
> > + if check_type_tag_order "$btf"; then
> > + info_log " passed"
> > + return 0
> > + fi
> > +
> > + error_log "BTF type tag order does not match expected order ($compiler)"
> > + return 1
> > +}
> > +
> > +failed=0
> > +
> > +if [ "$use_gcc" -eq 1 ]; then
> > + tmpobj=$(make_tmpobj)
> > + btf=${tmpobj%.o}.btf
> > + run_test "$GCC" "$tmpobj" "$btf" || failed=1
> > +fi
> > +
> > +if [ "$use_clang" -eq 1 ]; then
> > + tmpobj=$(make_tmpobj)
> > + btf=${tmpobj%.o}.btf
> > + run_test "$CLANG" "$tmpobj" "$btf" || failed=1
> > +fi
> > +
> > +if [ "$failed" -eq 0 ]; then
> > + test_pass
> > +else
> > + test_fail
> > +fi
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PAHOLE v5 1/5] btf_loader: Handle decl tag component_idx for parameters
2026-06-18 4:46 ` Emil Tsalapatis
@ 2026-06-18 13:27 ` Arnaldo Carvalho de Melo
2026-06-18 14:38 ` Alan Maguire
1 sibling, 0 replies; 12+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-06-18 13:27 UTC (permalink / raw)
To: Emil Tsalapatis
Cc: Vineet Gupta, dwarves, bpf, Andrii Nakryiko, Alan Maguire,
jose.marchesi, David Faust, Yonghong Song
On Thu, Jun 18, 2026 at 12:46:50AM -0400, Emil Tsalapatis wrote:
> On Wed Jun 17, 2026 at 8:57 PM EDT, Vineet Gupta wrote:
> > From: Alan Maguire <alan.maguire@oracle.com>
> >
> > A BTF_KIND_DECL_TAG with a non-negative component_idx applies to a
> > specific function parameter (or struct/union member), not to the
> > function itself. btf_loader.c however attached every decl tag to the
> > type named by btf_type->type, so parameter decl tags were recorded on
> > the function rather than on the parameter, and pfunct never printed
> > them with the parameter.
> >
> > Resolve a non-negative component_idx to the corresponding parameter via
> > new helpers ftype__parameter()/function__parameter(), and attach the
> > tag there. Teach the pretty printer to emit a parameter's attributes by
> > factoring the function-level attribute loop into tag__attributes_fprintf()
> > and calling it from ftype__fprintf_parms() for each parameter.
> >
> > Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> > Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
>
> With one nit:
>
> Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
>
> (Also feel free to keep the tags for the other 3 patches since the
> changes are minimal).
>
> </SNIP>
>
> > + if (component_idx >= 0) {
> > + struct tag *func_tag = cu__function(cu, tp->type);
> > +
> > + if (func_tag != NULL) {
> > + tag = function__parameter(tag__function(func_tag), cu,
> > + component_idx);
> > + if (tag == NULL) {
> > + fprintf(stderr, "WARNING: BTF_KIND_DECL_TAG for unknown parameter %d in BTF id %d\n",
> > + component_idx, tp->type);
> > + return 0;
> > + }
> > + }
> > + }
> > +
> > + if (tag == NULL && component_idx < 0)
> > tag = cu__function(cu, tp->type);
>
> Nit, I think this can be simplified as follows:
>
> tag = cu__function(cu, tp->type);
> if (component_idx >= 0 && tag != NULL) {
> tag = function__parameter(tag__function(tag), cu, component_idx);
> if (tag == NULL) {
> fprintf(stderr, "WARNING: BTF_KIND_DECL_TAG for unknown parameter %d in BTF id %d\n",
> component_idx, tp->type);
> return 0;
> }
> }
Agreed, and with that:
Acked-by: Arnaldo Carvalho de Melo <acme@redhat.com>
- Arnaldo
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PAHOLE v5 1/5] btf_loader: Handle decl tag component_idx for parameters
2026-06-18 4:46 ` Emil Tsalapatis
2026-06-18 13:27 ` Arnaldo Carvalho de Melo
@ 2026-06-18 14:38 ` Alan Maguire
2026-06-18 17:18 ` Vineet Gupta
1 sibling, 1 reply; 12+ messages in thread
From: Alan Maguire @ 2026-06-18 14:38 UTC (permalink / raw)
To: Emil Tsalapatis, Vineet Gupta, dwarves
Cc: bpf, Andrii Nakryiko, acme, jose.marchesi, David Faust,
Yonghong Song
On 18/06/2026 05:46, Emil Tsalapatis wrote:
> On Wed Jun 17, 2026 at 8:57 PM EDT, Vineet Gupta wrote:
>> From: Alan Maguire <alan.maguire@oracle.com>
>>
>> A BTF_KIND_DECL_TAG with a non-negative component_idx applies to a
>> specific function parameter (or struct/union member), not to the
>> function itself. btf_loader.c however attached every decl tag to the
>> type named by btf_type->type, so parameter decl tags were recorded on
>> the function rather than on the parameter, and pfunct never printed
>> them with the parameter.
>>
>> Resolve a non-negative component_idx to the corresponding parameter via
>> new helpers ftype__parameter()/function__parameter(), and attach the
>> tag there. Teach the pretty printer to emit a parameter's attributes by
>> factoring the function-level attribute loop into tag__attributes_fprintf()
>> and calling it from ftype__fprintf_parms() for each parameter.
>>
>> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
>> Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
>
> With one nit:
>
> Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
>
> (Also feel free to keep the tags for the other 3 patches since the
> changes are minimal).
>
> </SNIP>
>
>> + if (component_idx >= 0) {
>> + struct tag *func_tag = cu__function(cu, tp->type);
>> +
>> + if (func_tag != NULL) {
>> + tag = function__parameter(tag__function(func_tag), cu,
>> + component_idx);
>> + if (tag == NULL) {
>> + fprintf(stderr, "WARNING: BTF_KIND_DECL_TAG for unknown parameter %d in BTF id %d\n",
>> + component_idx, tp->type);
>> + return 0;
>> + }
>> + }
>> + }
>> +
>> + if (tag == NULL && component_idx < 0)
>> tag = cu__function(cu, tp->type);
>
> Nit, I think this can be simplified as follows:
>
> tag = cu__function(cu, tp->type);
> if (component_idx >= 0 && tag != NULL) {
> tag = function__parameter(tag__function(tag), cu, component_idx);
> if (tag == NULL) {
> fprintf(stderr, "WARNING: BTF_KIND_DECL_TAG for unknown parameter %d in BTF id %d\n",
> component_idx, tp->type);
> return 0;
> }
> }
>
> <SNIP>
yep, that looks good to me. if there are no other issues arising from this
round and Vineet is happy with that change I can roll it in when landing this
to save having to roll a v6.
One other issue; we need to install bpftool for CI. I'm working on a change to
support this (installing the version from the kernel tree), I'll try and get
this in place ASAP. Thanks!
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PAHOLE v5 1/5] btf_loader: Handle decl tag component_idx for parameters
2026-06-18 14:38 ` Alan Maguire
@ 2026-06-18 17:18 ` Vineet Gupta
0 siblings, 0 replies; 12+ messages in thread
From: Vineet Gupta @ 2026-06-18 17:18 UTC (permalink / raw)
To: Alan Maguire, Emil Tsalapatis, dwarves
Cc: bpf, Andrii Nakryiko, acme, jose.marchesi, David Faust,
Yonghong Song
On 6/18/26 7:38 AM, Alan Maguire wrote:
> On 18/06/2026 05:46, Emil Tsalapatis wrote:
>> On Wed Jun 17, 2026 at 8:57 PM EDT, Vineet Gupta wrote:
>>> From: Alan Maguire <alan.maguire@oracle.com>
>>>
>>> A BTF_KIND_DECL_TAG with a non-negative component_idx applies to a
>>> specific function parameter (or struct/union member), not to the
>>> function itself. btf_loader.c however attached every decl tag to the
>>> type named by btf_type->type, so parameter decl tags were recorded on
>>> the function rather than on the parameter, and pfunct never printed
>>> them with the parameter.
>>>
>>> Resolve a non-negative component_idx to the corresponding parameter via
>>> new helpers ftype__parameter()/function__parameter(), and attach the
>>> tag there. Teach the pretty printer to emit a parameter's attributes by
>>> factoring the function-level attribute loop into tag__attributes_fprintf()
>>> and calling it from ftype__fprintf_parms() for each parameter.
>>>
>>> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
>>> Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
>> With one nit:
>>
>> Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
>>
>> (Also feel free to keep the tags for the other 3 patches since the
>> changes are minimal).
>>
>> </SNIP>
>>
>>> + if (component_idx >= 0) {
>>> + struct tag *func_tag = cu__function(cu, tp->type);
>>> +
>>> + if (func_tag != NULL) {
>>> + tag = function__parameter(tag__function(func_tag), cu,
>>> + component_idx);
>>> + if (tag == NULL) {
>>> + fprintf(stderr, "WARNING: BTF_KIND_DECL_TAG for unknown parameter %d in BTF id %d\n",
>>> + component_idx, tp->type);
>>> + return 0;
>>> + }
>>> + }
>>> + }
>>> +
>>> + if (tag == NULL && component_idx < 0)
>>> tag = cu__function(cu, tp->type);
>> Nit, I think this can be simplified as follows:
>>
>> tag = cu__function(cu, tp->type);
>> if (component_idx >= 0 && tag != NULL) {
>> tag = function__parameter(tag__function(tag), cu, component_idx);
>> if (tag == NULL) {
>> fprintf(stderr, "WARNING: BTF_KIND_DECL_TAG for unknown parameter %d in BTF id %d\n",
>> component_idx, tp->type);
>> return 0;
>> }
>> }
>>
>> <SNIP>
> yep, that looks good to me. if there are no other issues arising from this
> round and Vineet is happy with that change I can roll it in when landing this
> to save having to roll a v6.
Cool, works for me and and indeed it will be nice to avoid a v6 :-)
Thx,
-Vineet
>
> One other issue; we need to install bpftool for CI. I'm working on a change to
> support this (installing the version from the kernel tree), I'll try and get
> this in place ASAP. Thanks!
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-06-18 17:18 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-18 0:57 [PAHOLE v5 0/5] support for DW_TAG_GNU_annotation and fixes Vineet Gupta
2026-06-18 0:57 ` [PAHOLE v5 1/5] btf_loader: Handle decl tag component_idx for parameters Vineet Gupta
2026-06-18 4:46 ` Emil Tsalapatis
2026-06-18 13:27 ` Arnaldo Carvalho de Melo
2026-06-18 14:38 ` Alan Maguire
2026-06-18 17:18 ` Vineet Gupta
2026-06-18 0:57 ` [PAHOLE v5 2/5] dwarf_loader: Extract die__add_btf_type_tag() helper [NFC] Vineet Gupta
2026-06-18 0:57 ` [PAHOLE v5 3/5] dwarf_loader: Add support for DW_TAG_GNU_annotation Vineet Gupta
2026-06-18 0:57 ` [PAHOLE v5 4/5] tests: Support GCC in pfunct-btf-decl-tags test Vineet Gupta
2026-06-18 0:57 ` [PAHOLE v5 5/5] tests: Add btf_type_tag ordering test Vineet Gupta
2026-06-18 4:47 ` Emil Tsalapatis
2026-06-18 13:25 ` Arnaldo Carvalho de Melo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox