I wrote the BTF loader from the CTF loader, where the size of
enumerations is expressed in bits, while BTF encodes it in bytes, fix
it.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
BTF_KIND_FUNC is generated by llvm (latest trunk, 8.0 or later).
Without BTF_KIND_FUNC support, we will see the following errors,
-bash-4.4$ cat t.c
struct t {
int a;
char b1:1;
char b2:3;
int c;
} g;
int main() { return 0; }
-bash-4.4$ clang -O2 -target bpf -g -c t.c -Xclang -target-feature -Xclang +dwarfris
-bash-4.4$ pahole -F btf t.o
BTF: idx: 3, off: 28, Unknown
struct t {
int a; /* 0 4 */
/* Bitfield combined with previous fields */
<ERROR(__class__fprintf:1342): 5 not found!>
/* Bitfield combined with previous fields */
<ERROR(__class__fprintf:1342): 5 not found!>
int c; /* 8 4 */
/* size: 12, cachelines: 1, members: 4 */
/* last cacheline: 12 bytes */
/* BRAIN FART ALERT! 12 != 8 + 0(holes), diff = 4 */
};
-bash-4.4$
The reason is that llvm generates BTF_KIND_FUNC which btf_loader does not
recognize.
This patch added support for BTF_KIND_FUNC. Since BTF_KIND_FUNC represents
a defined subprogram and not a real type. A null type is used to
represent BTF_KIND_FUNC to avoid skipping type index.
With this fix:
-bash-4.4$ pahole -F btf t.o
struct t {
int a; /* 0 4 */
char b1:1; /* 4: 0 1 */
char b2:3; /* 4: 1 1 */
int c; /* 8 4 */
/* size: 12, cachelines: 1, members: 4 */
/* last cacheline: 12 bytes */
/* BRAIN FART ALERT! 12 != 9 + 0(holes), diff = 3 */
};
Signed-off-by: Yonghong Song <yhs@fb.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Martin KaFai Lau <kafai@fb.com>
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Commit 2a82d593be ("btf: Add kind_flag support for btf_loader") added
kind_flag supported in btf_loader to get correct bitfield_size and
bit_offset for struct/union members. The commit unnecessarily stored
the bit in the structure type which is not used later.
So let us remove the kind_flag from the struct type and any other
changes whose purpose is to set this bit.
Signed-off-by: Yonghong Song <yhs@fb.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Martin KaFai Lau <kafai@fb.com>
Fixes: 2a82d593be ("btf: Add kind_flag support for btf_loader")
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Yonghong explains:
<quote>
The bitfield offset in BTF starts from lower number to bigger one. That
is, it is always following the big endian convention, bitfield_offset
will be smaller if close to the top of structure.
This is different from what dwarf is doing, which will show different
things on little endian vs. big endian.
You can make simple adjustment based on all available info. In
btf_encoder.s, we did similar adjustment for little endian from
dwarf to btf.
</>
So fix it up while loading, so that the rebuilt C output shows the same
thing from BTF and from DWARF.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
For struct/union members, the struct/union type info kind_flag is needed
to calculate correct bitfield_size and bit_offset.
if (kind_flag) {
bitfield_size = BTF_MEMBER_BITFIELD_SIZE(member->offset);
bit_offset = BTF_MEMBER_BIT_OFFSET(member->offset);
} else {
bitfield_size = 0;
bit_offset = member->offset;
}
Note that bitfield_size and bit_offset will not depend on the member
type. The member type will help calculate correct bitfield_offset,
byte_size, byte_offset, bit_size.
For example, with the fix, we will be able to display
bit offset and bitfield size properly.
-bash-4.4$ cat t.c
struct t {
int a:2;
int b:3;
int c:2;
} g;
-bash-4.4$ gcc -c -O2 -g t.c
-bash-4.4$ pahole -JV t.o
File t.o:
[1] STRUCT t kind_flag=1 size=4 vlen=3
a type_id=2 bitfield_size=2 bits_offset=0
b type_id=2 bitfield_size=3 bits_offset=2
c type_id=2 bitfield_size=2 bits_offset=5
[2] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
-bash-4.4$ pahole -F btf t.o
struct t {
int a:2; /* 0: 0 4 */
int b:3; /* 0: 2 4 */
int c:2; /* 0: 5 4 */
/* size: 4, cachelines: 1, members: 3 */
/* bit_padding: 25 bits */
/* last cacheline: 4 bytes */
};
Note that the above offset showing is different from the below dwarf as
BTF bitfield_offset is always the offset from the start of structure,
kindly like big endian encoding. This may need adjustment to be
conforming to the dwarf dump format.
-bash-4.4$ pahole -F dwarf t.o
struct t {
int a:2; /* 0:30 4 */
int b:3; /* 0:27 4 */
int c:2; /* 0:25 4 */
/* size: 4, cachelines: 1, members: 3 */
/* bit_padding: 25 bits */
/* last cacheline: 4 bytes */
};
Signed-off-by: Yonghong Song <yhs@fb.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Martin KaFai Lau <kafai@fb.com>
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>