[PATCH dwarves v2 2/5] btf_loader: A hack for BTF import of btf_type_tag attributes

Eduard Zingerman
2023-03-14T23:04:37Z

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@gmail.com>
---
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