Re: BTF type tags not emitted properly when using macros

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





On 2/19/22 11:13 PM, Kumar Kartikeya Dwivedi wrote:
Hi list,

I noticed another problem in LLVM HEAD wrt BTF type tags.

When I have a file like bad.c:

  ; cat bad.c
#define __kptr __attribute__((btf_type_tag("btf_id")))
#define __kptr_ref __kptr __attribute__((btf_type_tag("ref")))
#define __kptr_percpu __kptr __attribute__((btf_type_tag("percpu")))
#define __kptr_user __kptr __attribute__((btf_type_tag("user")))

struct map_value {
         int __kptr *a;
         int __kptr_ref *b;
         int __kptr_percpu *c;
         int __kptr_user *d;
};

struct map_value *func(void);

int main(void)
{
         struct map_value *p = func();
         return *p->a + *p->b + *p->c + *p->d;
}

All tags are not emitted to BTF (neither are they there in llvm-dwarfdump output):

  ; ./src/linux/kptr-map/tools/bpf/bpftool/bpftool btf dump file bad.o format raw
[1] FUNC_PROTO '(anon)' ret_type_id=2 vlen=0
[2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
[3] FUNC 'main' type_id=1 linkage=global
[4] FUNC_PROTO '(anon)' ret_type_id=5 vlen=0
[5] PTR '(anon)' type_id=6
[6] STRUCT 'map_value' size=32 vlen=4
         'a' type_id=8 bits_offset=0
         'b' type_id=11 bits_offset=64
         'c' type_id=11 bits_offset=128
         'd' type_id=11 bits_offset=192
[7] TYPE_TAG 'btf_id' type_id=2
[8] PTR '(anon)' type_id=7
[9] TYPE_TAG 'btf_id' type_id=2
[10] TYPE_TAG 'ref' type_id=9
[11] PTR '(anon)' type_id=10
[12] FUNC 'func' type_id=4 linkage=extern

Notice that only btf_id (__kptr) and btf_id + ref (__kptr_ref) are emitted
properly, and then rest of members use type_id=11, instead of emitting more type
tags.

Thanks for reporting. I think clang frontend may have bugs in handling nested macros. Will debug this.


When I use a mix of macro and direct attributes, or just attributes, it does work:

; cat good.c
#define __kptr __attribute__((btf_type_tag("btf_id")))

struct map_value {
         int __kptr *a;
         int __kptr __attribute__((btf_type_tag("ref"))) *b;
         int __kptr __attribute__((btf_type_tag("percpu"))) *c;
         int __kptr __attribute__((btf_type_tag("user"))) *d;
};

struct map_value *func(void);

int main(void)
{
         struct map_value *p = func();
         return *p->a + *p->b + *p->c + *p->d;
}

Now all tags are there in BTF:

  ; ./src/linux/kptr-map/tools/bpf/bpftool/bpftool btf dump file good.o format raw
[1] FUNC_PROTO '(anon)' ret_type_id=2 vlen=0
[2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
[3] FUNC 'main' type_id=1 linkage=global
[4] FUNC_PROTO '(anon)' ret_type_id=5 vlen=0
[5] PTR '(anon)' type_id=6
[6] STRUCT 'map_value' size=32 vlen=4
         'a' type_id=8 bits_offset=0
         'b' type_id=11 bits_offset=64
         'c' type_id=14 bits_offset=128
         'd' type_id=17 bits_offset=192
[7] TYPE_TAG 'btf_id' type_id=2
[8] PTR '(anon)' type_id=7
[9] TYPE_TAG 'btf_id' type_id=2
[10] TYPE_TAG 'ref' type_id=9
[11] PTR '(anon)' type_id=10
[12] TYPE_TAG 'btf_id' type_id=2
[13] TYPE_TAG 'percpu' type_id=12
[14] PTR '(anon)' type_id=13
[15] TYPE_TAG 'btf_id' type_id=2
[16] TYPE_TAG 'user' type_id=15
[17] PTR '(anon)' type_id=16
[18] FUNC 'func' type_id=4 linkage=extern

In both cases, the preprocessed source (using -E) looks to be the same:

  ; /home/kkd/src/llvm-project/llvm/build/bin/clang --target=bpf -g -O2 -c bad.c -E
# 1 "bad.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 323 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "bad.c" 2

struct map_value {
  int __attribute__((btf_type_tag("btf_id"))) *a;
  int __attribute__((btf_type_tag("btf_id"))) __attribute__((btf_type_tag("ref"))) *b;
  int __attribute__((btf_type_tag("btf_id"))) __attribute__((btf_type_tag("percpu"))) *c;
  int __attribute__((btf_type_tag("btf_id"))) __attribute__((btf_type_tag("user"))) *d;
};

struct map_value *func(void);

int main(void)
{
  struct map_value *p = func();
  return *p->a + *p->b + *p->c + *p->d;
}

  ; /home/kkd/src/llvm-project/llvm/build/bin/clang --target=bpf -g -O2 -c good.c -E
# 1 "good.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 323 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "good.c" 2

struct map_value {
  int __attribute__((btf_type_tag("btf_id"))) *a;
  int __attribute__((btf_type_tag("btf_id"))) __attribute__((btf_type_tag("ref"))) *b;
  int __attribute__((btf_type_tag("btf_id"))) __attribute__((btf_type_tag("percpu"))) *c;
  int __attribute__((btf_type_tag("btf_id"))) __attribute__((btf_type_tag("user"))) *d;
};

struct map_value *func(void);

int main(void)
{
  struct map_value *p = func();
  return *p->a + *p->b + *p->c + *p->d;
}

--

Please let me know if I made some dumb mistake.

  ; /home/kkd/src/llvm-project/llvm/build/bin/clang --version
clang version 15.0.0 (https://github.com/llvm/llvm-project.git 290e482342826ee4c65bd6d2aece25736d3f0c7b)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/kkd/src/llvm-project/llvm/build/bin

A side note, but it seems it could avoid emitting the same type tag multiple
times to save on space. I.e. in the case of other members, their ref, percpu,
user tag could point to the same btf_id type tag that the first member's
BTF_KIND_PTR points to.

Right, we might have some type duplication here. I am aware of this since this ONLY happens when types in ptr -> [other modifier types] -> base_type where [other modifier types] might be duplicated due to
particular llvm BPF backend implementation. In general, this should
not take much space. Since you are mentioning this, I will try to
improve it.


Thanks.
--
Kartikeya



[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux