diff options
author | David Faust <david.faust@oracle.com> | 2022-10-24 13:59:39 -0700 |
---|---|---|
committer | David Faust <david.faust@oracle.com> | 2022-10-26 13:18:48 -0700 |
commit | 068baae1864e2a8036beec3082d384a204e24201 (patch) | |
tree | 680abc541c63bb61cc0d1c31622da8cc6f19c7db /gcc/doc | |
parent | d2249cd9adf5ae638577139177a50f7e62d8abd9 (diff) | |
download | gcc-068baae1864e2a8036beec3082d384a204e24201.zip gcc-068baae1864e2a8036beec3082d384a204e24201.tar.gz gcc-068baae1864e2a8036beec3082d384a204e24201.tar.bz2 |
bpf: add preserve_field_info builtin
Add BPF __builtin_preserve_field_info. This builtin is used to extract
information to facilitate struct and union relocations performed by the
BPF loader, especially for bitfields.
The builtin has the following signature:
unsigned int __builtin_preserve_field_info (EXPR, unsigned int KIND);
Where EXPR is an expression accessing a field of a struct or union.
Depending on KIND, different information is returned to the program. The
supported values for KIND are as follows:
enum {
FIELD_BYTE_OFFSET = 0,
FIELD_BYTE_SIZE,
FIELD_EXISTENCE,
FIELD_SIGNEDNESS,
FIELD_LSHIFT_U64,
FIELD_RSHIFT_U64
};
If -mco-re is in effect (explicitly or implicitly specified), a CO-RE
relocation is added for the access in EXPR recording the relevant
information according to KIND.
gcc/
* config/bpf/bpf.cc: Support __builtin_preserve_field_info.
(enum bpf_builtins): Add new builtin.
(bpf_init_builtins): Likewise.
(bpf_core_field_info): New function.
(bpf_expand_builtin): Accomodate new builtin. Refactor adding new
relocation to...
(maybe_make_core_relo): ... here. New function.
(bpf_resolve_overloaded_builtin): Accomodate new builtin.
(bpf_core_newdecl): Likewise.
(bpf_core_walk): Likewise.
(bpf_core_is_maybe_aggregate_access): Improve logic.
(struct core_walk_data): New.
* config/bpf/coreout.cc (bpf_core_reloc_add): Allow adding different
relocation kinds.
* config/bpf/coreout.h: Analogous change.
* doc/extend.texi: Document BPF __builtin_preserve_field_info.
gcc/testsuite/
* gcc.target/bpf/core-builtin-fieldinfo-errors-1.c: New test.
* gcc.target/bpf/core-builtin-fieldinfo-errors-2.c: New test.
* gcc.target/bpf/core-builtin-fieldinfo-existence-1.c: New test.
* gcc.target/bpf/core-builtin-fieldinfo-lshift-1-be.c: New test.
* gcc.target/bpf/core-builtin-fieldinfo-lshift-1-le.c: New test.
* gcc.target/bpf/core-builtin-fieldinfo-lshift-2.c: New test.
* gcc.target/bpf/core-builtin-fieldinfo-offset-1.c: New test.
* gcc.target/bpf/core-builtin-fieldinfo-rshift-1.c: New test.
* gcc.target/bpf/core-builtin-fieldinfo-rshift-2.c: New test.
* gcc.target/bpf/core-builtin-fieldinfo-sign-1.c: New test.
* gcc.target/bpf/core-builtin-fieldinfo-sign-2.c: New test.
* gcc.target/bpf/core-builtin-fieldinfo-size-1.c: New test.
Diffstat (limited to 'gcc/doc')
-rw-r--r-- | gcc/doc/extend.texi | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index ba90bfa..77ea545 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -15755,6 +15755,83 @@ Load 32-bits from the @code{struct sk_buff} packet data pointed by the register BPF Compile Once-Run Everywhere (CO-RE) support. Instruct GCC to generate CO-RE relocation records for any accesses to aggregate data structures (struct, union, array types) in @var{expr}. This builtin is otherwise transparent, the return value is whatever @var{expr} evaluates to. It is also overloaded: @var{expr} may be of any type (not necessarily a pointer), the return type is the same. Has no effect if @code{-mco-re} is not in effect (either specified or implied). @end deftypefn +@deftypefn {Built-in Function} unsigned int __builtin_preserve_field_info (@var{expr}, unsigned int @var{kind}) +BPF Compile Once-Run Everywhere (CO-RE) support. This builtin is used to +extract information to aid in struct/union relocations. @var{expr} is +an access to a field of a struct or union. Depending on @var{kind}, different +information is returned to the program. A CO-RE relocation for the access in +@var{expr} with kind @var{kind} is recorded if @code{-mco-re} is in effect. + +The following values are supported for @var{kind}: +@table @var +@item FIELD_BYTE_OFFSET = 0 +The returned value is the offset, in bytes, of the field from the +beginning of the containing structure. For bitfields, the byte offset +of the containing word. + +@item FIELD_BYTE_SIZE = 1 +The returned value is the size, in bytes, of the field. For bitfields, +the size in bytes of the containing word. + +@item FIELD_EXISTENCE = 2 +The returned value is 1 if the field exists, 0 otherwise. Always 1 at +compile time. + +@item FIELD_SIGNEDNESS = 3 +The returned value is 1 if the field is signed, 0 otherwise. + +@item FIELD_LSHIFT_U64 = 4 +@itemx FIELD_RSHIFT_U64 = 5 +The returned value is the number of bits of left- or right-shifting +respectively needed in order to recover the original value of the field, +after it has been loaded by a read of FIELD_BYTE_SIZE bytes into an +unsigned 64-bit value. Primarily useful for reading bitfield values +from structures which may change between kernel versions. + +@end table + +Note that the return value is a constant which is known at +compile-time. If the field has a variable offset then +FIELD_BYTE_OFFSET, FIELD_LSHIFT_U64 and FIELD_RSHIFT_U64 are not +supported. Similarly, if the field has a variable size then +FIELD_BYTE_SIZE, FIELD_LSHIFT_U64 and FIELD_RSHIFT_U64 are not +supported. + +For example, __builtin_preserve_field_info can be used to reliably +extract bitfield values from a structure which may change between +kernel versions: + +@example +struct S +@{ + short a; + int x:7; + int y:5; +@}; + +int +read_y (struct S *arg) +@{ + unsigned long long val; + unsigned int offset = __builtin_preserve_field_info (arg->y, FIELD_BYTE_OFFSET); + unsigned int size = __builtin_presrve_field_info (arg->y, FIELD_BYTE_SIZE); + + /* Read size bytes from arg + offset into val. */ + bpf_probe_read (&val, size, arg + offset); + + val <<= __builtin_preserve_field_info (arg->y, FIELD_LSHIFT_U64); + + if (__builtin_preserve_field_info (arg->y, FIELD_SIGNEDNESS)) + val = ((long long) val >> __builtin_preserve_field_info (arg->y, FIELD_RSHIFT_U64)); + else + val >>= __builtin_preserve_field_info (arg->y, FIELD_RSHIFT_U64); + + return val; +@} + +@end example +@end deftypefn + @node FR-V Built-in Functions @subsection FR-V Built-in Functions |