Kernel does not expect VAR entries to have types starting from BTF_TYPE_TAG. Specifically, the code like below will be rejected: struct rq __percpu runqueues; ... rq = (struct rq *)bpf_per_cpu_ptr(&runqueues, cpu); ... rq->cpu ... // rq type is now PTR_TO_BTF_ID The access to 'rq->cpu' would be checked by a call to kernel/bpf/btf.c:btf_struct_access() which invokes btf_struct_walk(), using rq's type as a starting point. The btf_struct_walk() wants the first type in a chain to be STRUCT or UNION and does not skip modifiers. Before introduction of support for 'btf:type_tag' such situations were not possible, as TYPE_TAG entries were always preceded by PTR entries. Signed-off-by: Eduard Zingerman <eddyz87@xxxxxxxxx> --- btf_encoder.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/btf_encoder.c b/btf_encoder.c index 65f6e71..300d9c2 100644 --- a/btf_encoder.c +++ b/btf_encoder.c @@ -1498,6 +1498,19 @@ static bool ftype__has_arg_names(const struct ftype *ftype) return true; } +static type_id_t skip_btf_type_tags(struct cu *cu, type_id_t id) +{ + for (;;) { + struct tag *tag = cu__type(cu, id); + + if (tag == NULL || tag->tag != DW_TAG_LLVM_annotation) + break; + id = tag->type; + } + + return id; +} + static int btf_encoder__encode_cu_variables(struct btf_encoder *encoder) { struct cu *cu = encoder->cu; @@ -1583,7 +1596,22 @@ static int btf_encoder__encode_cu_variables(struct btf_encoder *encoder) continue; } - type = var->ip.tag.type + encoder->type_id_off; + /* Kernel does not expect VAR entries to have types starting from BTF_TYPE_TAG. + * Specifically, the code like below will be rejected: + * + * struct rq __percpu runqueues; + * ... + * rq = (struct rq *)bpf_per_cpu_ptr(&runqueues, cpu); + * ... rq->cpu ... // rq type is now PTR_TO_BTF_ID + * + * The access to 'rq->cpu' would be checked by a call to + * kernel/bpf/btf.c:btf_struct_access() which invokes btf_struct_walk(), + * using rq's type as a starting point. The btf_struct_walk() wants the + * first type in a chain to be STRUCT or UNION and does not skip modifiers. + * + * Thus, call skip_btf_type_tags() here. + */ + type = skip_btf_type_tags(cu, var->ip.tag.type) + encoder->type_id_off; linkage = var->external ? BTF_VAR_GLOBAL_ALLOCATED : BTF_VAR_STATIC; if (encoder->verbose) { -- 2.40.1