Commit 46334a0c authored by Alexei Starovoitov's avatar Alexei Starovoitov Committed by Andrii Nakryiko
Browse files

bpf: Define enum bpf_core_relo_kind as uapi.



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: default avatarAlexei Starovoitov <ast@kernel.org>
Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Acked-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20211201181040.23337-5-alexei.starovoitov@gmail.com
parent 29db4bea
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
@@ -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__ */
+1 −1
Original line number Diff line number Diff line
@@ -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)) {
+42 −42
Original line number Diff line number Diff line
@@ -113,18 +113,18 @@ 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";
	}
}
@@ -132,12 +132,12 @@ static const char *core_relo_kind_str(enum bpf_core_relo_kind kind)
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;
@@ -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;
@@ -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;
@@ -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;
	}
@@ -637,7 +637,7 @@ 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);
@@ -645,7 +645,7 @@ static int bpf_core_calc_field_relo(const char *prog_name,
				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;
@@ -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;
	}
@@ -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;
	}
@@ -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);
@@ -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;
@@ -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
+1 −17
Original line number Diff line number Diff line
@@ -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
 *