On Wed, 2025-02-12 at 12:15 -0800, Ihor Solodrai wrote: [...] > diff --git a/btf_encoder.c b/btf_encoder.c > index 965e8f0..3cec106 100644 > --- a/btf_encoder.c > +++ b/btf_encoder.c [...] > +static int btf__tag_bpf_arena_ptr(struct btf *btf, int ptr_id) > +{ > + const struct btf_type *ptr; > + int tagged_type_id; > + > + ptr = btf__type_by_id(btf, ptr_id); > + if (!btf_is_ptr(ptr)) > + return -EINVAL; > + > + tagged_type_id = btf__add_type_attr(btf, BPF_ARENA_ATTR, ptr->type); > + if (tagged_type_id < 0) > + return tagged_type_id; > + > + return btf__add_ptr(btf, tagged_type_id); > +} I might be confused, but this is a bit strange. The type constructed here is: ptr -> type_tag -> t. However, address_space is an attribute of a pointer, not a pointed type. I think that correct sequence should be: type_tag -> ptr -> t. This would make libbpf emit C declaration as follows: void * __attribute__((address_space(1))) ptr; Instead of current: void __attribute__((address_space(1))) * ptr; clang generates identical IR for both declarations: @ptr = dso_local global ptr addrspace(1) null, align 8 Thus, imo, this function should be simplified as below: static int btf__tag_bpf_arena_ptr(struct btf *btf, int ptr_id) { const struct btf_type *ptr; ptr = btf__type_by_id(btf, ptr_id); if (!btf_is_ptr(ptr)) return -EINVAL; return btf__add_type_attr(btf, BPF_ARENA_ATTR, ptr_id); } [...]