Skip to content

Commit

Permalink
bpf: Define enum bpf_core_relo_kind as uapi.
Browse files Browse the repository at this point in the history
enum bpf_core_relo_kind is generated by llvm and processed by libbpf.
It's a de-facto uapi.
With CO-RE in the kernel the bpf_core_relo_kind values become uapi de-jure.
Also rename them with BPF_CORE_ prefix to distinguish from conflicting names in
bpf_core_read.h. The enums bpf_field_info_kind, bpf_type_id_kind,
bpf_type_info_kind, bpf_enum_value_kind are passing different values from bpf
program into llvm.

Signed-off-by: Alexei Starovoitov <[email protected]>
Signed-off-by: Andrii Nakryiko <[email protected]>
Acked-by: Andrii Nakryiko <[email protected]>
Link: https://lore.kernel.org/bpf/[email protected]
  • Loading branch information
Alexei Starovoitov authored and anakryiko committed Dec 2, 2021
1 parent 29db4be commit 46334a0
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 60 deletions.
19 changes: 19 additions & 0 deletions include/uapi/linux/bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -6374,4 +6374,23 @@ enum {
BTF_F_ZERO = (1ULL << 3),
};

/* bpf_core_relo_kind encodes which aspect of captured field/type/enum value
* has to be adjusted by relocations. It is emitted by llvm and passed to
* libbpf and later to the kernel.
*/
enum bpf_core_relo_kind {
BPF_CORE_FIELD_BYTE_OFFSET = 0, /* field byte offset */
BPF_CORE_FIELD_BYTE_SIZE = 1, /* field size in bytes */
BPF_CORE_FIELD_EXISTS = 2, /* field existence in target kernel */
BPF_CORE_FIELD_SIGNED = 3, /* field signedness (0 - unsigned, 1 - signed) */
BPF_CORE_FIELD_LSHIFT_U64 = 4, /* bitfield-specific left bitshift */
BPF_CORE_FIELD_RSHIFT_U64 = 5, /* bitfield-specific right bitshift */
BPF_CORE_TYPE_ID_LOCAL = 6, /* type ID in local BPF object */
BPF_CORE_TYPE_ID_TARGET = 7, /* type ID in target kernel */
BPF_CORE_TYPE_EXISTS = 8, /* type existence in target kernel */
BPF_CORE_TYPE_SIZE = 9, /* type size in bytes */
BPF_CORE_ENUMVAL_EXISTS = 10, /* enum value existence in target kernel */
BPF_CORE_ENUMVAL_VALUE = 11, /* enum value integer value */
};

#endif /* _UAPI__LINUX_BPF_H__ */
19 changes: 19 additions & 0 deletions tools/include/uapi/linux/bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -6374,4 +6374,23 @@ enum {
BTF_F_ZERO = (1ULL << 3),
};

/* bpf_core_relo_kind encodes which aspect of captured field/type/enum value
* has to be adjusted by relocations. It is emitted by llvm and passed to
* libbpf and later to the kernel.
*/
enum bpf_core_relo_kind {
BPF_CORE_FIELD_BYTE_OFFSET = 0, /* field byte offset */
BPF_CORE_FIELD_BYTE_SIZE = 1, /* field size in bytes */
BPF_CORE_FIELD_EXISTS = 2, /* field existence in target kernel */
BPF_CORE_FIELD_SIGNED = 3, /* field signedness (0 - unsigned, 1 - signed) */
BPF_CORE_FIELD_LSHIFT_U64 = 4, /* bitfield-specific left bitshift */
BPF_CORE_FIELD_RSHIFT_U64 = 5, /* bitfield-specific right bitshift */
BPF_CORE_TYPE_ID_LOCAL = 6, /* type ID in local BPF object */
BPF_CORE_TYPE_ID_TARGET = 7, /* type ID in target kernel */
BPF_CORE_TYPE_EXISTS = 8, /* type existence in target kernel */
BPF_CORE_TYPE_SIZE = 9, /* type size in bytes */
BPF_CORE_ENUMVAL_EXISTS = 10, /* enum value existence in target kernel */
BPF_CORE_ENUMVAL_VALUE = 11, /* enum value integer value */
};

#endif /* _UAPI__LINUX_BPF_H__ */
2 changes: 1 addition & 1 deletion tools/lib/bpf/libbpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -5523,7 +5523,7 @@ static int bpf_core_apply_relo(struct bpf_program *prog,
return -ENOTSUP;
}

if (relo->kind != BPF_TYPE_ID_LOCAL &&
if (relo->kind != BPF_CORE_TYPE_ID_LOCAL &&
!hashmap__find(cand_cache, type_key, (void **)&cands)) {
cands = bpf_core_find_cands(prog->obj, local_btf, local_id);
if (IS_ERR(cands)) {
Expand Down
84 changes: 42 additions & 42 deletions tools/lib/bpf/relo_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,31 +113,31 @@ static bool is_flex_arr(const struct btf *btf,
static const char *core_relo_kind_str(enum bpf_core_relo_kind kind)
{
switch (kind) {
case BPF_FIELD_BYTE_OFFSET: return "byte_off";
case BPF_FIELD_BYTE_SIZE: return "byte_sz";
case BPF_FIELD_EXISTS: return "field_exists";
case BPF_FIELD_SIGNED: return "signed";
case BPF_FIELD_LSHIFT_U64: return "lshift_u64";
case BPF_FIELD_RSHIFT_U64: return "rshift_u64";
case BPF_TYPE_ID_LOCAL: return "local_type_id";
case BPF_TYPE_ID_TARGET: return "target_type_id";
case BPF_TYPE_EXISTS: return "type_exists";
case BPF_TYPE_SIZE: return "type_size";
case BPF_ENUMVAL_EXISTS: return "enumval_exists";
case BPF_ENUMVAL_VALUE: return "enumval_value";
case BPF_CORE_FIELD_BYTE_OFFSET: return "byte_off";
case BPF_CORE_FIELD_BYTE_SIZE: return "byte_sz";
case BPF_CORE_FIELD_EXISTS: return "field_exists";
case BPF_CORE_FIELD_SIGNED: return "signed";
case BPF_CORE_FIELD_LSHIFT_U64: return "lshift_u64";
case BPF_CORE_FIELD_RSHIFT_U64: return "rshift_u64";
case BPF_CORE_TYPE_ID_LOCAL: return "local_type_id";
case BPF_CORE_TYPE_ID_TARGET: return "target_type_id";
case BPF_CORE_TYPE_EXISTS: return "type_exists";
case BPF_CORE_TYPE_SIZE: return "type_size";
case BPF_CORE_ENUMVAL_EXISTS: return "enumval_exists";
case BPF_CORE_ENUMVAL_VALUE: return "enumval_value";
default: return "unknown";
}
}

static bool core_relo_is_field_based(enum bpf_core_relo_kind kind)
{
switch (kind) {
case BPF_FIELD_BYTE_OFFSET:
case BPF_FIELD_BYTE_SIZE:
case BPF_FIELD_EXISTS:
case BPF_FIELD_SIGNED:
case BPF_FIELD_LSHIFT_U64:
case BPF_FIELD_RSHIFT_U64:
case BPF_CORE_FIELD_BYTE_OFFSET:
case BPF_CORE_FIELD_BYTE_SIZE:
case BPF_CORE_FIELD_EXISTS:
case BPF_CORE_FIELD_SIGNED:
case BPF_CORE_FIELD_LSHIFT_U64:
case BPF_CORE_FIELD_RSHIFT_U64:
return true;
default:
return false;
Expand All @@ -147,10 +147,10 @@ static bool core_relo_is_field_based(enum bpf_core_relo_kind kind)
static bool core_relo_is_type_based(enum bpf_core_relo_kind kind)
{
switch (kind) {
case BPF_TYPE_ID_LOCAL:
case BPF_TYPE_ID_TARGET:
case BPF_TYPE_EXISTS:
case BPF_TYPE_SIZE:
case BPF_CORE_TYPE_ID_LOCAL:
case BPF_CORE_TYPE_ID_TARGET:
case BPF_CORE_TYPE_EXISTS:
case BPF_CORE_TYPE_SIZE:
return true;
default:
return false;
Expand All @@ -160,8 +160,8 @@ static bool core_relo_is_type_based(enum bpf_core_relo_kind kind)
static bool core_relo_is_enumval_based(enum bpf_core_relo_kind kind)
{
switch (kind) {
case BPF_ENUMVAL_EXISTS:
case BPF_ENUMVAL_VALUE:
case BPF_CORE_ENUMVAL_EXISTS:
case BPF_CORE_ENUMVAL_VALUE:
return true;
default:
return false;
Expand Down Expand Up @@ -624,7 +624,7 @@ static int bpf_core_calc_field_relo(const char *prog_name,

*field_sz = 0;

if (relo->kind == BPF_FIELD_EXISTS) {
if (relo->kind == BPF_CORE_FIELD_EXISTS) {
*val = spec ? 1 : 0;
return 0;
}
Expand All @@ -637,15 +637,15 @@ static int bpf_core_calc_field_relo(const char *prog_name,

/* a[n] accessor needs special handling */
if (!acc->name) {
if (relo->kind == BPF_FIELD_BYTE_OFFSET) {
if (relo->kind == BPF_CORE_FIELD_BYTE_OFFSET) {
*val = spec->bit_offset / 8;
/* remember field size for load/store mem size */
sz = btf__resolve_size(spec->btf, acc->type_id);
if (sz < 0)
return -EINVAL;
*field_sz = sz;
*type_id = acc->type_id;
} else if (relo->kind == BPF_FIELD_BYTE_SIZE) {
} else if (relo->kind == BPF_CORE_FIELD_BYTE_SIZE) {
sz = btf__resolve_size(spec->btf, acc->type_id);
if (sz < 0)
return -EINVAL;
Expand Down Expand Up @@ -697,36 +697,36 @@ static int bpf_core_calc_field_relo(const char *prog_name,
*validate = !bitfield;

switch (relo->kind) {
case BPF_FIELD_BYTE_OFFSET:
case BPF_CORE_FIELD_BYTE_OFFSET:
*val = byte_off;
if (!bitfield) {
*field_sz = byte_sz;
*type_id = field_type_id;
}
break;
case BPF_FIELD_BYTE_SIZE:
case BPF_CORE_FIELD_BYTE_SIZE:
*val = byte_sz;
break;
case BPF_FIELD_SIGNED:
case BPF_CORE_FIELD_SIGNED:
/* enums will be assumed unsigned */
*val = btf_is_enum(mt) ||
(btf_int_encoding(mt) & BTF_INT_SIGNED);
if (validate)
*validate = true; /* signedness is never ambiguous */
break;
case BPF_FIELD_LSHIFT_U64:
case BPF_CORE_FIELD_LSHIFT_U64:
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
*val = 64 - (bit_off + bit_sz - byte_off * 8);
#else
*val = (8 - byte_sz) * 8 + (bit_off - byte_off * 8);
#endif
break;
case BPF_FIELD_RSHIFT_U64:
case BPF_CORE_FIELD_RSHIFT_U64:
*val = 64 - bit_sz;
if (validate)
*validate = true; /* right shift is never ambiguous */
break;
case BPF_FIELD_EXISTS:
case BPF_CORE_FIELD_EXISTS:
default:
return -EOPNOTSUPP;
}
Expand All @@ -747,20 +747,20 @@ static int bpf_core_calc_type_relo(const struct bpf_core_relo *relo,
}

switch (relo->kind) {
case BPF_TYPE_ID_TARGET:
case BPF_CORE_TYPE_ID_TARGET:
*val = spec->root_type_id;
break;
case BPF_TYPE_EXISTS:
case BPF_CORE_TYPE_EXISTS:
*val = 1;
break;
case BPF_TYPE_SIZE:
case BPF_CORE_TYPE_SIZE:
sz = btf__resolve_size(spec->btf, spec->root_type_id);
if (sz < 0)
return -EINVAL;
*val = sz;
break;
case BPF_TYPE_ID_LOCAL:
/* BPF_TYPE_ID_LOCAL is handled specially and shouldn't get here */
case BPF_CORE_TYPE_ID_LOCAL:
/* BPF_CORE_TYPE_ID_LOCAL is handled specially and shouldn't get here */
default:
return -EOPNOTSUPP;
}
Expand All @@ -776,10 +776,10 @@ static int bpf_core_calc_enumval_relo(const struct bpf_core_relo *relo,
const struct btf_enum *e;

switch (relo->kind) {
case BPF_ENUMVAL_EXISTS:
case BPF_CORE_ENUMVAL_EXISTS:
*val = spec ? 1 : 0;
break;
case BPF_ENUMVAL_VALUE:
case BPF_CORE_ENUMVAL_VALUE:
if (!spec)
return -EUCLEAN; /* request instruction poisoning */
t = btf_type_by_id(spec->btf, spec->spec[0].type_id);
Expand Down Expand Up @@ -1236,7 +1236,7 @@ int bpf_core_apply_relo_insn(const char *prog_name, struct bpf_insn *insn,
libbpf_print(LIBBPF_DEBUG, "\n");

/* TYPE_ID_LOCAL relo is special and doesn't need candidate search */
if (relo->kind == BPF_TYPE_ID_LOCAL) {
if (relo->kind == BPF_CORE_TYPE_ID_LOCAL) {
targ_res.validate = true;
targ_res.poison = false;
targ_res.orig_val = local_spec.root_type_id;
Expand Down Expand Up @@ -1302,7 +1302,7 @@ int bpf_core_apply_relo_insn(const char *prog_name, struct bpf_insn *insn,
}

/*
* For BPF_FIELD_EXISTS relo or when used BPF program has field
* For BPF_CORE_FIELD_EXISTS relo or when used BPF program has field
* existence checks or kernel version/config checks, it's expected
* that we might not find any candidates. In this case, if field
* wasn't found in any candidate, the list of candidates shouldn't
Expand Down
18 changes: 1 addition & 17 deletions tools/lib/bpf/relo_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,7 @@
#ifndef __RELO_CORE_H
#define __RELO_CORE_H

/* bpf_core_relo_kind encodes which aspect of captured field/type/enum value
* has to be adjusted by relocations.
*/
enum bpf_core_relo_kind {
BPF_FIELD_BYTE_OFFSET = 0, /* field byte offset */
BPF_FIELD_BYTE_SIZE = 1, /* field size in bytes */
BPF_FIELD_EXISTS = 2, /* field existence in target kernel */
BPF_FIELD_SIGNED = 3, /* field signedness (0 - unsigned, 1 - signed) */
BPF_FIELD_LSHIFT_U64 = 4, /* bitfield-specific left bitshift */
BPF_FIELD_RSHIFT_U64 = 5, /* bitfield-specific right bitshift */
BPF_TYPE_ID_LOCAL = 6, /* type ID in local BPF object */
BPF_TYPE_ID_TARGET = 7, /* type ID in target kernel */
BPF_TYPE_EXISTS = 8, /* type existence in target kernel */
BPF_TYPE_SIZE = 9, /* type size in bytes */
BPF_ENUMVAL_EXISTS = 10, /* enum value existence in target kernel */
BPF_ENUMVAL_VALUE = 11, /* enum value integer value */
};
#include <linux/bpf.h>

/* The minimum bpf_core_relo checked by the loader
*
Expand Down

0 comments on commit 46334a0

Please sign in to comment.