2018-04-19 05:55:57 +07:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
|
|
|
/* Copyright (c) 2018 Facebook */
|
|
|
|
#ifndef _UAPI__LINUX_BTF_H__
|
|
|
|
#define _UAPI__LINUX_BTF_H__
|
|
|
|
|
|
|
|
#include <linux/types.h>
|
|
|
|
|
|
|
|
#define BTF_MAGIC 0xeB9F
|
|
|
|
#define BTF_VERSION 1
|
|
|
|
|
|
|
|
struct btf_header {
|
|
|
|
__u16 magic;
|
|
|
|
__u8 version;
|
|
|
|
__u8 flags;
|
2018-05-23 04:57:18 +07:00
|
|
|
__u32 hdr_len;
|
2018-04-19 05:55:57 +07:00
|
|
|
|
|
|
|
/* All offsets are in bytes relative to the end of this header */
|
|
|
|
__u32 type_off; /* offset of type section */
|
2018-05-23 04:57:18 +07:00
|
|
|
__u32 type_len; /* length of type section */
|
2018-04-19 05:55:57 +07:00
|
|
|
__u32 str_off; /* offset of string section */
|
|
|
|
__u32 str_len; /* length of string section */
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Max # of type identifier */
|
2019-09-18 00:45:38 +07:00
|
|
|
#define BTF_MAX_TYPE 0x000fffff
|
2018-04-19 05:55:57 +07:00
|
|
|
/* Max offset into the string section */
|
2019-09-18 00:45:38 +07:00
|
|
|
#define BTF_MAX_NAME_OFFSET 0x00ffffff
|
2018-04-19 05:55:57 +07:00
|
|
|
/* Max # of struct/union/enum members or func args */
|
|
|
|
#define BTF_MAX_VLEN 0xffff
|
|
|
|
|
|
|
|
struct btf_type {
|
2018-04-21 23:48:23 +07:00
|
|
|
__u32 name_off;
|
2018-04-19 05:55:57 +07:00
|
|
|
/* "info" bits arrangement
|
|
|
|
* bits 0-15: vlen (e.g. # of struct's members)
|
|
|
|
* bits 16-23: unused
|
2018-05-23 04:57:20 +07:00
|
|
|
* bits 24-27: kind (e.g. int, ptr, array...etc)
|
bpf: btf: fix struct/union/fwd types with kind_flag
This patch fixed two issues with BTF. One is related to
struct/union bitfield encoding and the other is related to
forward type.
Issue #1 and solution:
======================
Current btf encoding of bitfield follows what pahole generates.
For each bitfield, pahole will duplicate the type chain and
put the bitfield size at the final int or enum type.
Since the BTF enum type cannot encode bit size,
pahole workarounds the issue by generating
an int type whenever the enum bit size is not 32.
For example,
-bash-4.4$ cat t.c
typedef int ___int;
enum A { A1, A2, A3 };
struct t {
int a[5];
___int b:4;
volatile enum A c:4;
} g;
-bash-4.4$ gcc -c -O2 -g t.c
The current kernel supports the following BTF encoding:
$ pahole -JV t.o
[1] TYPEDEF ___int type_id=2
[2] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
[3] ENUM A size=4 vlen=3
A1 val=0
A2 val=1
A3 val=2
[4] STRUCT t size=24 vlen=3
a type_id=5 bits_offset=0
b type_id=9 bits_offset=160
c type_id=11 bits_offset=164
[5] ARRAY (anon) type_id=2 index_type_id=2 nr_elems=5
[6] INT sizetype size=8 bit_offset=0 nr_bits=64 encoding=(none)
[7] VOLATILE (anon) type_id=3
[8] INT int size=1 bit_offset=0 nr_bits=4 encoding=(none)
[9] TYPEDEF ___int type_id=8
[10] INT (anon) size=1 bit_offset=0 nr_bits=4 encoding=SIGNED
[11] VOLATILE (anon) type_id=10
Two issues are in the above:
. by changing enum type to int, we lost the original
type information and this will not be ideal later
when we try to convert BTF to a header file.
. the type duplication for bitfields will cause
BTF bloat. Duplicated types cannot be deduplicated
later if the bitfield size is different.
To fix this issue, this patch implemented a compatible
change for BTF struct type encoding:
. the bit 31 of struct_type->info, previously reserved,
now is used to indicate whether bitfield_size is
encoded in btf_member or not.
. if bit 31 of struct_type->info is set,
btf_member->offset will encode like:
bit 0 - 23: bit offset
bit 24 - 31: bitfield size
if bit 31 is not set, the old behavior is preserved:
bit 0 - 31: bit offset
So if the struct contains a bit field, the maximum bit offset
will be reduced to (2^24 - 1) instead of MAX_UINT. The maximum
bitfield size will be 256 which is enough for today as maximum
bitfield in compiler can be 128 where int128 type is supported.
This kernel patch intends to support the new BTF encoding:
$ pahole -JV t.o
[1] TYPEDEF ___int type_id=2
[2] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
[3] ENUM A size=4 vlen=3
A1 val=0
A2 val=1
A3 val=2
[4] STRUCT t kind_flag=1 size=24 vlen=3
a type_id=5 bitfield_size=0 bits_offset=0
b type_id=1 bitfield_size=4 bits_offset=160
c type_id=7 bitfield_size=4 bits_offset=164
[5] ARRAY (anon) type_id=2 index_type_id=2 nr_elems=5
[6] INT sizetype size=8 bit_offset=0 nr_bits=64 encoding=(none)
[7] VOLATILE (anon) type_id=3
Issue #2 and solution:
======================
Current forward type in BTF does not specify whether the original
type is struct or union. This will not work for type pretty print
and BTF-to-header-file conversion as struct/union must be specified.
$ cat tt.c
struct t;
union u;
int foo(struct t *t, union u *u) { return 0; }
$ gcc -c -g -O2 tt.c
$ pahole -JV tt.o
[1] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
[2] FWD t type_id=0
[3] PTR (anon) type_id=2
[4] FWD u type_id=0
[5] PTR (anon) type_id=4
To fix this issue, similar to issue #1, type->info bit 31
is used. If the bit is set, it is union type. Otherwise, it is
a struct type.
$ pahole -JV tt.o
[1] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
[2] FWD t kind_flag=0 type_id=0
[3] PTR (anon) kind_flag=0 type_id=2
[4] FWD u kind_flag=1 type_id=0
[5] PTR (anon) kind_flag=0 type_id=4
Pahole/LLVM change:
===================
The new kind_flag functionality has been implemented in pahole
and llvm:
https://github.com/yonghong-song/pahole/tree/bitfield
https://github.com/yonghong-song/llvm/tree/bitfield
Note that pahole hasn't implemented func/func_proto kind
and .BTF.ext. So to print function signature with bpftool,
the llvm compiler should be used.
Fixes: 69b693f0aefa ("bpf: btf: Introduce BPF Type Format (BTF)")
Acked-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
2018-12-16 13:13:51 +07:00
|
|
|
* bits 28-30: unused
|
|
|
|
* bit 31: kind_flag, currently used by
|
|
|
|
* struct, union and fwd
|
2018-04-19 05:55:57 +07:00
|
|
|
*/
|
|
|
|
__u32 info;
|
2019-04-10 04:20:08 +07:00
|
|
|
/* "size" is used by INT, ENUM, STRUCT, UNION and DATASEC.
|
2018-04-19 05:55:57 +07:00
|
|
|
* "size" tells the size of the type it is describing.
|
|
|
|
*
|
2018-11-20 06:29:08 +07:00
|
|
|
* "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT,
|
2019-04-10 04:20:08 +07:00
|
|
|
* FUNC, FUNC_PROTO and VAR.
|
2018-04-19 05:55:57 +07:00
|
|
|
* "type" is a type_id referring to another type.
|
|
|
|
*/
|
|
|
|
union {
|
|
|
|
__u32 size;
|
|
|
|
__u32 type;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2018-05-23 04:57:20 +07:00
|
|
|
#define BTF_INFO_KIND(info) (((info) >> 24) & 0x0f)
|
2018-04-19 05:55:57 +07:00
|
|
|
#define BTF_INFO_VLEN(info) ((info) & 0xffff)
|
bpf: btf: fix struct/union/fwd types with kind_flag
This patch fixed two issues with BTF. One is related to
struct/union bitfield encoding and the other is related to
forward type.
Issue #1 and solution:
======================
Current btf encoding of bitfield follows what pahole generates.
For each bitfield, pahole will duplicate the type chain and
put the bitfield size at the final int or enum type.
Since the BTF enum type cannot encode bit size,
pahole workarounds the issue by generating
an int type whenever the enum bit size is not 32.
For example,
-bash-4.4$ cat t.c
typedef int ___int;
enum A { A1, A2, A3 };
struct t {
int a[5];
___int b:4;
volatile enum A c:4;
} g;
-bash-4.4$ gcc -c -O2 -g t.c
The current kernel supports the following BTF encoding:
$ pahole -JV t.o
[1] TYPEDEF ___int type_id=2
[2] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
[3] ENUM A size=4 vlen=3
A1 val=0
A2 val=1
A3 val=2
[4] STRUCT t size=24 vlen=3
a type_id=5 bits_offset=0
b type_id=9 bits_offset=160
c type_id=11 bits_offset=164
[5] ARRAY (anon) type_id=2 index_type_id=2 nr_elems=5
[6] INT sizetype size=8 bit_offset=0 nr_bits=64 encoding=(none)
[7] VOLATILE (anon) type_id=3
[8] INT int size=1 bit_offset=0 nr_bits=4 encoding=(none)
[9] TYPEDEF ___int type_id=8
[10] INT (anon) size=1 bit_offset=0 nr_bits=4 encoding=SIGNED
[11] VOLATILE (anon) type_id=10
Two issues are in the above:
. by changing enum type to int, we lost the original
type information and this will not be ideal later
when we try to convert BTF to a header file.
. the type duplication for bitfields will cause
BTF bloat. Duplicated types cannot be deduplicated
later if the bitfield size is different.
To fix this issue, this patch implemented a compatible
change for BTF struct type encoding:
. the bit 31 of struct_type->info, previously reserved,
now is used to indicate whether bitfield_size is
encoded in btf_member or not.
. if bit 31 of struct_type->info is set,
btf_member->offset will encode like:
bit 0 - 23: bit offset
bit 24 - 31: bitfield size
if bit 31 is not set, the old behavior is preserved:
bit 0 - 31: bit offset
So if the struct contains a bit field, the maximum bit offset
will be reduced to (2^24 - 1) instead of MAX_UINT. The maximum
bitfield size will be 256 which is enough for today as maximum
bitfield in compiler can be 128 where int128 type is supported.
This kernel patch intends to support the new BTF encoding:
$ pahole -JV t.o
[1] TYPEDEF ___int type_id=2
[2] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
[3] ENUM A size=4 vlen=3
A1 val=0
A2 val=1
A3 val=2
[4] STRUCT t kind_flag=1 size=24 vlen=3
a type_id=5 bitfield_size=0 bits_offset=0
b type_id=1 bitfield_size=4 bits_offset=160
c type_id=7 bitfield_size=4 bits_offset=164
[5] ARRAY (anon) type_id=2 index_type_id=2 nr_elems=5
[6] INT sizetype size=8 bit_offset=0 nr_bits=64 encoding=(none)
[7] VOLATILE (anon) type_id=3
Issue #2 and solution:
======================
Current forward type in BTF does not specify whether the original
type is struct or union. This will not work for type pretty print
and BTF-to-header-file conversion as struct/union must be specified.
$ cat tt.c
struct t;
union u;
int foo(struct t *t, union u *u) { return 0; }
$ gcc -c -g -O2 tt.c
$ pahole -JV tt.o
[1] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
[2] FWD t type_id=0
[3] PTR (anon) type_id=2
[4] FWD u type_id=0
[5] PTR (anon) type_id=4
To fix this issue, similar to issue #1, type->info bit 31
is used. If the bit is set, it is union type. Otherwise, it is
a struct type.
$ pahole -JV tt.o
[1] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
[2] FWD t kind_flag=0 type_id=0
[3] PTR (anon) kind_flag=0 type_id=2
[4] FWD u kind_flag=1 type_id=0
[5] PTR (anon) kind_flag=0 type_id=4
Pahole/LLVM change:
===================
The new kind_flag functionality has been implemented in pahole
and llvm:
https://github.com/yonghong-song/pahole/tree/bitfield
https://github.com/yonghong-song/llvm/tree/bitfield
Note that pahole hasn't implemented func/func_proto kind
and .BTF.ext. So to print function signature with bpftool,
the llvm compiler should be used.
Fixes: 69b693f0aefa ("bpf: btf: Introduce BPF Type Format (BTF)")
Acked-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
2018-12-16 13:13:51 +07:00
|
|
|
#define BTF_INFO_KFLAG(info) ((info) >> 31)
|
2018-04-19 05:55:57 +07:00
|
|
|
|
|
|
|
#define BTF_KIND_UNKN 0 /* Unknown */
|
|
|
|
#define BTF_KIND_INT 1 /* Integer */
|
|
|
|
#define BTF_KIND_PTR 2 /* Pointer */
|
|
|
|
#define BTF_KIND_ARRAY 3 /* Array */
|
|
|
|
#define BTF_KIND_STRUCT 4 /* Struct */
|
|
|
|
#define BTF_KIND_UNION 5 /* Union */
|
|
|
|
#define BTF_KIND_ENUM 6 /* Enumeration */
|
|
|
|
#define BTF_KIND_FWD 7 /* Forward */
|
|
|
|
#define BTF_KIND_TYPEDEF 8 /* Typedef */
|
|
|
|
#define BTF_KIND_VOLATILE 9 /* Volatile */
|
|
|
|
#define BTF_KIND_CONST 10 /* Const */
|
|
|
|
#define BTF_KIND_RESTRICT 11 /* Restrict */
|
2018-11-20 06:29:08 +07:00
|
|
|
#define BTF_KIND_FUNC 12 /* Function */
|
|
|
|
#define BTF_KIND_FUNC_PROTO 13 /* Function Proto */
|
2019-04-10 04:20:08 +07:00
|
|
|
#define BTF_KIND_VAR 14 /* Variable */
|
|
|
|
#define BTF_KIND_DATASEC 15 /* Section */
|
|
|
|
#define BTF_KIND_MAX BTF_KIND_DATASEC
|
|
|
|
#define NR_BTF_KINDS (BTF_KIND_MAX + 1)
|
2018-04-19 05:55:57 +07:00
|
|
|
|
|
|
|
/* For some specific BTF_KIND, "struct btf_type" is immediately
|
|
|
|
* followed by extra data.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* BTF_KIND_INT is followed by a u32 and the following
|
|
|
|
* is the 32 bits arrangement:
|
|
|
|
*/
|
2018-05-23 04:57:20 +07:00
|
|
|
#define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24)
|
2019-05-13 16:45:48 +07:00
|
|
|
#define BTF_INT_OFFSET(VAL) (((VAL) & 0x00ff0000) >> 16)
|
2018-07-20 12:14:31 +07:00
|
|
|
#define BTF_INT_BITS(VAL) ((VAL) & 0x000000ff)
|
2018-04-19 05:55:57 +07:00
|
|
|
|
|
|
|
/* Attributes stored in the BTF_INT_ENCODING */
|
2018-05-23 04:57:20 +07:00
|
|
|
#define BTF_INT_SIGNED (1 << 0)
|
|
|
|
#define BTF_INT_CHAR (1 << 1)
|
|
|
|
#define BTF_INT_BOOL (1 << 2)
|
2018-04-19 05:55:57 +07:00
|
|
|
|
|
|
|
/* BTF_KIND_ENUM is followed by multiple "struct btf_enum".
|
|
|
|
* The exact number of btf_enum is stored in the vlen (of the
|
|
|
|
* info in "struct btf_type").
|
|
|
|
*/
|
|
|
|
struct btf_enum {
|
2018-04-21 23:48:23 +07:00
|
|
|
__u32 name_off;
|
2018-04-19 05:55:57 +07:00
|
|
|
__s32 val;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* BTF_KIND_ARRAY is followed by one "struct btf_array" */
|
|
|
|
struct btf_array {
|
|
|
|
__u32 type;
|
|
|
|
__u32 index_type;
|
|
|
|
__u32 nelems;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* BTF_KIND_STRUCT and BTF_KIND_UNION are followed
|
|
|
|
* by multiple "struct btf_member". The exact number
|
|
|
|
* of btf_member is stored in the vlen (of the info in
|
|
|
|
* "struct btf_type").
|
|
|
|
*/
|
|
|
|
struct btf_member {
|
2018-04-21 23:48:23 +07:00
|
|
|
__u32 name_off;
|
2018-04-19 05:55:57 +07:00
|
|
|
__u32 type;
|
bpf: btf: fix struct/union/fwd types with kind_flag
This patch fixed two issues with BTF. One is related to
struct/union bitfield encoding and the other is related to
forward type.
Issue #1 and solution:
======================
Current btf encoding of bitfield follows what pahole generates.
For each bitfield, pahole will duplicate the type chain and
put the bitfield size at the final int or enum type.
Since the BTF enum type cannot encode bit size,
pahole workarounds the issue by generating
an int type whenever the enum bit size is not 32.
For example,
-bash-4.4$ cat t.c
typedef int ___int;
enum A { A1, A2, A3 };
struct t {
int a[5];
___int b:4;
volatile enum A c:4;
} g;
-bash-4.4$ gcc -c -O2 -g t.c
The current kernel supports the following BTF encoding:
$ pahole -JV t.o
[1] TYPEDEF ___int type_id=2
[2] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
[3] ENUM A size=4 vlen=3
A1 val=0
A2 val=1
A3 val=2
[4] STRUCT t size=24 vlen=3
a type_id=5 bits_offset=0
b type_id=9 bits_offset=160
c type_id=11 bits_offset=164
[5] ARRAY (anon) type_id=2 index_type_id=2 nr_elems=5
[6] INT sizetype size=8 bit_offset=0 nr_bits=64 encoding=(none)
[7] VOLATILE (anon) type_id=3
[8] INT int size=1 bit_offset=0 nr_bits=4 encoding=(none)
[9] TYPEDEF ___int type_id=8
[10] INT (anon) size=1 bit_offset=0 nr_bits=4 encoding=SIGNED
[11] VOLATILE (anon) type_id=10
Two issues are in the above:
. by changing enum type to int, we lost the original
type information and this will not be ideal later
when we try to convert BTF to a header file.
. the type duplication for bitfields will cause
BTF bloat. Duplicated types cannot be deduplicated
later if the bitfield size is different.
To fix this issue, this patch implemented a compatible
change for BTF struct type encoding:
. the bit 31 of struct_type->info, previously reserved,
now is used to indicate whether bitfield_size is
encoded in btf_member or not.
. if bit 31 of struct_type->info is set,
btf_member->offset will encode like:
bit 0 - 23: bit offset
bit 24 - 31: bitfield size
if bit 31 is not set, the old behavior is preserved:
bit 0 - 31: bit offset
So if the struct contains a bit field, the maximum bit offset
will be reduced to (2^24 - 1) instead of MAX_UINT. The maximum
bitfield size will be 256 which is enough for today as maximum
bitfield in compiler can be 128 where int128 type is supported.
This kernel patch intends to support the new BTF encoding:
$ pahole -JV t.o
[1] TYPEDEF ___int type_id=2
[2] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
[3] ENUM A size=4 vlen=3
A1 val=0
A2 val=1
A3 val=2
[4] STRUCT t kind_flag=1 size=24 vlen=3
a type_id=5 bitfield_size=0 bits_offset=0
b type_id=1 bitfield_size=4 bits_offset=160
c type_id=7 bitfield_size=4 bits_offset=164
[5] ARRAY (anon) type_id=2 index_type_id=2 nr_elems=5
[6] INT sizetype size=8 bit_offset=0 nr_bits=64 encoding=(none)
[7] VOLATILE (anon) type_id=3
Issue #2 and solution:
======================
Current forward type in BTF does not specify whether the original
type is struct or union. This will not work for type pretty print
and BTF-to-header-file conversion as struct/union must be specified.
$ cat tt.c
struct t;
union u;
int foo(struct t *t, union u *u) { return 0; }
$ gcc -c -g -O2 tt.c
$ pahole -JV tt.o
[1] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
[2] FWD t type_id=0
[3] PTR (anon) type_id=2
[4] FWD u type_id=0
[5] PTR (anon) type_id=4
To fix this issue, similar to issue #1, type->info bit 31
is used. If the bit is set, it is union type. Otherwise, it is
a struct type.
$ pahole -JV tt.o
[1] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
[2] FWD t kind_flag=0 type_id=0
[3] PTR (anon) kind_flag=0 type_id=2
[4] FWD u kind_flag=1 type_id=0
[5] PTR (anon) kind_flag=0 type_id=4
Pahole/LLVM change:
===================
The new kind_flag functionality has been implemented in pahole
and llvm:
https://github.com/yonghong-song/pahole/tree/bitfield
https://github.com/yonghong-song/llvm/tree/bitfield
Note that pahole hasn't implemented func/func_proto kind
and .BTF.ext. So to print function signature with bpftool,
the llvm compiler should be used.
Fixes: 69b693f0aefa ("bpf: btf: Introduce BPF Type Format (BTF)")
Acked-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
2018-12-16 13:13:51 +07:00
|
|
|
/* If the type info kind_flag is set, the btf_member offset
|
|
|
|
* contains both member bitfield size and bit offset. The
|
|
|
|
* bitfield size is set for bitfield members. If the type
|
|
|
|
* info kind_flag is not set, the offset contains only bit
|
|
|
|
* offset.
|
|
|
|
*/
|
|
|
|
__u32 offset;
|
2018-04-19 05:55:57 +07:00
|
|
|
};
|
|
|
|
|
bpf: btf: fix struct/union/fwd types with kind_flag
This patch fixed two issues with BTF. One is related to
struct/union bitfield encoding and the other is related to
forward type.
Issue #1 and solution:
======================
Current btf encoding of bitfield follows what pahole generates.
For each bitfield, pahole will duplicate the type chain and
put the bitfield size at the final int or enum type.
Since the BTF enum type cannot encode bit size,
pahole workarounds the issue by generating
an int type whenever the enum bit size is not 32.
For example,
-bash-4.4$ cat t.c
typedef int ___int;
enum A { A1, A2, A3 };
struct t {
int a[5];
___int b:4;
volatile enum A c:4;
} g;
-bash-4.4$ gcc -c -O2 -g t.c
The current kernel supports the following BTF encoding:
$ pahole -JV t.o
[1] TYPEDEF ___int type_id=2
[2] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
[3] ENUM A size=4 vlen=3
A1 val=0
A2 val=1
A3 val=2
[4] STRUCT t size=24 vlen=3
a type_id=5 bits_offset=0
b type_id=9 bits_offset=160
c type_id=11 bits_offset=164
[5] ARRAY (anon) type_id=2 index_type_id=2 nr_elems=5
[6] INT sizetype size=8 bit_offset=0 nr_bits=64 encoding=(none)
[7] VOLATILE (anon) type_id=3
[8] INT int size=1 bit_offset=0 nr_bits=4 encoding=(none)
[9] TYPEDEF ___int type_id=8
[10] INT (anon) size=1 bit_offset=0 nr_bits=4 encoding=SIGNED
[11] VOLATILE (anon) type_id=10
Two issues are in the above:
. by changing enum type to int, we lost the original
type information and this will not be ideal later
when we try to convert BTF to a header file.
. the type duplication for bitfields will cause
BTF bloat. Duplicated types cannot be deduplicated
later if the bitfield size is different.
To fix this issue, this patch implemented a compatible
change for BTF struct type encoding:
. the bit 31 of struct_type->info, previously reserved,
now is used to indicate whether bitfield_size is
encoded in btf_member or not.
. if bit 31 of struct_type->info is set,
btf_member->offset will encode like:
bit 0 - 23: bit offset
bit 24 - 31: bitfield size
if bit 31 is not set, the old behavior is preserved:
bit 0 - 31: bit offset
So if the struct contains a bit field, the maximum bit offset
will be reduced to (2^24 - 1) instead of MAX_UINT. The maximum
bitfield size will be 256 which is enough for today as maximum
bitfield in compiler can be 128 where int128 type is supported.
This kernel patch intends to support the new BTF encoding:
$ pahole -JV t.o
[1] TYPEDEF ___int type_id=2
[2] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
[3] ENUM A size=4 vlen=3
A1 val=0
A2 val=1
A3 val=2
[4] STRUCT t kind_flag=1 size=24 vlen=3
a type_id=5 bitfield_size=0 bits_offset=0
b type_id=1 bitfield_size=4 bits_offset=160
c type_id=7 bitfield_size=4 bits_offset=164
[5] ARRAY (anon) type_id=2 index_type_id=2 nr_elems=5
[6] INT sizetype size=8 bit_offset=0 nr_bits=64 encoding=(none)
[7] VOLATILE (anon) type_id=3
Issue #2 and solution:
======================
Current forward type in BTF does not specify whether the original
type is struct or union. This will not work for type pretty print
and BTF-to-header-file conversion as struct/union must be specified.
$ cat tt.c
struct t;
union u;
int foo(struct t *t, union u *u) { return 0; }
$ gcc -c -g -O2 tt.c
$ pahole -JV tt.o
[1] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
[2] FWD t type_id=0
[3] PTR (anon) type_id=2
[4] FWD u type_id=0
[5] PTR (anon) type_id=4
To fix this issue, similar to issue #1, type->info bit 31
is used. If the bit is set, it is union type. Otherwise, it is
a struct type.
$ pahole -JV tt.o
[1] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
[2] FWD t kind_flag=0 type_id=0
[3] PTR (anon) kind_flag=0 type_id=2
[4] FWD u kind_flag=1 type_id=0
[5] PTR (anon) kind_flag=0 type_id=4
Pahole/LLVM change:
===================
The new kind_flag functionality has been implemented in pahole
and llvm:
https://github.com/yonghong-song/pahole/tree/bitfield
https://github.com/yonghong-song/llvm/tree/bitfield
Note that pahole hasn't implemented func/func_proto kind
and .BTF.ext. So to print function signature with bpftool,
the llvm compiler should be used.
Fixes: 69b693f0aefa ("bpf: btf: Introduce BPF Type Format (BTF)")
Acked-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
2018-12-16 13:13:51 +07:00
|
|
|
/* If the struct/union type info kind_flag is set, the
|
|
|
|
* following two macros are used to access bitfield_size
|
|
|
|
* and bit_offset from btf_member.offset.
|
|
|
|
*/
|
|
|
|
#define BTF_MEMBER_BITFIELD_SIZE(val) ((val) >> 24)
|
|
|
|
#define BTF_MEMBER_BIT_OFFSET(val) ((val) & 0xffffff)
|
|
|
|
|
2018-11-20 06:29:08 +07:00
|
|
|
/* BTF_KIND_FUNC_PROTO is followed by multiple "struct btf_param".
|
|
|
|
* The exact number of btf_param is stored in the vlen (of the
|
|
|
|
* info in "struct btf_type").
|
|
|
|
*/
|
|
|
|
struct btf_param {
|
|
|
|
__u32 name_off;
|
|
|
|
__u32 type;
|
|
|
|
};
|
|
|
|
|
2019-04-10 04:20:08 +07:00
|
|
|
enum {
|
|
|
|
BTF_VAR_STATIC = 0,
|
libbpf: Support libbpf-provided extern variables
Add support for extern variables, provided to BPF program by libbpf. Currently
the following extern variables are supported:
- LINUX_KERNEL_VERSION; version of a kernel in which BPF program is
executing, follows KERNEL_VERSION() macro convention, can be 4- and 8-byte
long;
- CONFIG_xxx values; a set of values of actual kernel config. Tristate,
boolean, strings, and integer values are supported.
Set of possible values is determined by declared type of extern variable.
Supported types of variables are:
- Tristate values. Are represented as `enum libbpf_tristate`. Accepted values
are **strictly** 'y', 'n', or 'm', which are represented as TRI_YES, TRI_NO,
or TRI_MODULE, respectively.
- Boolean values. Are represented as bool (_Bool) types. Accepted values are
'y' and 'n' only, turning into true/false values, respectively.
- Single-character values. Can be used both as a substritute for
bool/tristate, or as a small-range integer:
- 'y'/'n'/'m' are represented as is, as characters 'y', 'n', or 'm';
- integers in a range [-128, 127] or [0, 255] (depending on signedness of
char in target architecture) are recognized and represented with
respective values of char type.
- Strings. String values are declared as fixed-length char arrays. String of
up to that length will be accepted and put in first N bytes of char array,
with the rest of bytes zeroed out. If config string value is longer than
space alloted, it will be truncated and warning message emitted. Char array
is always zero terminated. String literals in config have to be enclosed in
double quotes, just like C-style string literals.
- Integers. 8-, 16-, 32-, and 64-bit integers are supported, both signed and
unsigned variants. Libbpf enforces parsed config value to be in the
supported range of corresponding integer type. Integers values in config can
be:
- decimal integers, with optional + and - signs;
- hexadecimal integers, prefixed with 0x or 0X;
- octal integers, starting with 0.
Config file itself is searched in /boot/config-$(uname -r) location with
fallback to /proc/config.gz, unless config path is specified explicitly
through bpf_object_open_opts' kernel_config_path option. Both gzipped and
plain text formats are supported. Libbpf adds explicit dependency on zlib
because of this, but this shouldn't be a problem, given libelf already depends
on zlib.
All detected extern variables, are put into a separate .extern internal map.
It, similarly to .rodata map, is marked as read-only from BPF program side, as
well as is frozen on load. This allows BPF verifier to track extern values as
constants and perform enhanced branch prediction and dead code elimination.
This can be relied upon for doing kernel version/feature detection and using
potentially unsupported field relocations or BPF helpers in a CO-RE-based BPF
program, while still having a single version of BPF program running on old and
new kernels. Selftests are validating this explicitly for unexisting BPF
helper.
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20191214014710.3449601-3-andriin@fb.com
2019-12-14 08:47:08 +07:00
|
|
|
BTF_VAR_GLOBAL_ALLOCATED = 1,
|
|
|
|
BTF_VAR_GLOBAL_EXTERN = 2,
|
2019-04-10 04:20:08 +07:00
|
|
|
};
|
|
|
|
|
2020-01-10 13:41:20 +07:00
|
|
|
enum btf_func_linkage {
|
|
|
|
BTF_FUNC_STATIC = 0,
|
|
|
|
BTF_FUNC_GLOBAL = 1,
|
|
|
|
BTF_FUNC_EXTERN = 2,
|
|
|
|
};
|
|
|
|
|
2019-04-10 04:20:08 +07:00
|
|
|
/* BTF_KIND_VAR is followed by a single "struct btf_var" to describe
|
|
|
|
* additional information related to the variable such as its linkage.
|
|
|
|
*/
|
|
|
|
struct btf_var {
|
|
|
|
__u32 linkage;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* BTF_KIND_DATASEC is followed by multiple "struct btf_var_secinfo"
|
|
|
|
* to describe all BTF_KIND_VAR types it contains along with it's
|
|
|
|
* in-section offset as well as size.
|
|
|
|
*/
|
|
|
|
struct btf_var_secinfo {
|
|
|
|
__u32 type;
|
|
|
|
__u32 offset;
|
|
|
|
__u32 size;
|
|
|
|
};
|
|
|
|
|
2018-04-19 05:55:57 +07:00
|
|
|
#endif /* _UAPI__LINUX_BTF_H__ */
|