Pahole does not print type names correctly for the following example, when BTF loader is used: #define __tag1 __attribute__((btf_type_tag("tag1"))) struct st { int __tag1 *a; } g; Here is the pahole output: $ clang -target bpf -g -c test.c -o test.o $ pahole -F btf test.o BTF: idx: 2, Unknown kind 18 struct st { <ERROR > a; /* 0 8 */ ... }; Note the type name for field `a`. This commit adds a workaround for this issue: it creates a tag instance with tag->tag set to `DW_TAG_LLVM_annotation` and `tag->type` pointing to the type wrapped by `BTF_KIND_TYPE_TAG`, `int` for the example above. Note that this is not a complete replication of behavior of DWARF loader. When DWARF is processed type tag instances are added to the annotations list of the parent pointer type. However, this is sufficient to fix the printing issue and helps with `btfdiff` script. Signed-off-by: Eduard Zingerman <eddyz87@xxxxxxxxx> --- btf_loader.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/btf_loader.c b/btf_loader.c index e579323..3fe07d0 100644 --- a/btf_loader.c +++ b/btf_loader.c @@ -429,10 +429,11 @@ static int create_new_tag(struct cu *cu, int type, const struct btf_type *tp, ui return -ENOMEM; switch (type) { - case BTF_KIND_CONST: tag->tag = DW_TAG_const_type; break; - case BTF_KIND_PTR: tag->tag = DW_TAG_pointer_type; break; - case BTF_KIND_RESTRICT: tag->tag = DW_TAG_restrict_type; break; - case BTF_KIND_VOLATILE: tag->tag = DW_TAG_volatile_type; break; + case BTF_KIND_CONST: tag->tag = DW_TAG_const_type; break; + case BTF_KIND_PTR: tag->tag = DW_TAG_pointer_type; break; + case BTF_KIND_RESTRICT: tag->tag = DW_TAG_restrict_type; break; + case BTF_KIND_VOLATILE: tag->tag = DW_TAG_volatile_type; break; + case BTF_KIND_TYPE_TAG: tag->tag = DW_TAG_LLVM_annotation; break; default: free(tag); printf("%s: Unknown type %d\n\n", __func__, type); @@ -489,6 +490,12 @@ static int btf__load_types(struct btf *btf, struct cu *cu) case BTF_KIND_PTR: case BTF_KIND_CONST: case BTF_KIND_RESTRICT: + /* For type tag it's a bit of a lie. + * In DWARF it is encoded as a child tag of whatever type it + * applies to. Here we load it as a standalone tag with a pointer + * to a next type only to have a valid ID in the types table. + */ + case BTF_KIND_TYPE_TAG: err = create_new_tag(cu, type, type_ptr, type_index); break; case BTF_KIND_UNKN: -- 2.39.1