Skip to content

Commit

Permalink
libbpf: Permit 64bit relocation value
Browse files Browse the repository at this point in the history
Currently, the libbpf limits the relocation value to be 32bit
since all current relocations have such a limit. But with
BTF_KIND_ENUM64 support, the enum value could be 64bit.
So let us permit 64bit relocation value in libbpf.

Acked-by: Andrii Nakryiko <[email protected]>
Signed-off-by: Yonghong Song <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Alexei Starovoitov <[email protected]>
  • Loading branch information
yonghong-song authored and Alexei Starovoitov committed Jun 7, 2022
1 parent 6089fb3 commit 7762816
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 24 deletions.
49 changes: 27 additions & 22 deletions tools/lib/bpf/relo_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ static int bpf_core_spec_match(struct bpf_core_spec *local_spec,
static int bpf_core_calc_field_relo(const char *prog_name,
const struct bpf_core_relo *relo,
const struct bpf_core_spec *spec,
__u32 *val, __u32 *field_sz, __u32 *type_id,
__u64 *val, __u32 *field_sz, __u32 *type_id,
bool *validate)
{
const struct bpf_core_accessor *acc;
Expand Down Expand Up @@ -708,7 +708,7 @@ static int bpf_core_calc_field_relo(const char *prog_name,

static int bpf_core_calc_type_relo(const struct bpf_core_relo *relo,
const struct bpf_core_spec *spec,
__u32 *val, bool *validate)
__u64 *val, bool *validate)
{
__s64 sz;

Expand Down Expand Up @@ -751,7 +751,7 @@ static int bpf_core_calc_type_relo(const struct bpf_core_relo *relo,

static int bpf_core_calc_enumval_relo(const struct bpf_core_relo *relo,
const struct bpf_core_spec *spec,
__u32 *val)
__u64 *val)
{
const struct btf_type *t;
const struct btf_enum *e;
Expand Down Expand Up @@ -929,7 +929,7 @@ int bpf_core_patch_insn(const char *prog_name, struct bpf_insn *insn,
int insn_idx, const struct bpf_core_relo *relo,
int relo_idx, const struct bpf_core_relo_res *res)
{
__u32 orig_val, new_val;
__u64 orig_val, new_val;
__u8 class;

class = BPF_CLASS(insn->code);
Expand All @@ -954,28 +954,30 @@ int bpf_core_patch_insn(const char *prog_name, struct bpf_insn *insn,
if (BPF_SRC(insn->code) != BPF_K)
return -EINVAL;
if (res->validate && insn->imm != orig_val) {
pr_warn("prog '%s': relo #%d: unexpected insn #%d (ALU/ALU64) value: got %u, exp %u -> %u\n",
pr_warn("prog '%s': relo #%d: unexpected insn #%d (ALU/ALU64) value: got %u, exp %llu -> %llu\n",
prog_name, relo_idx,
insn_idx, insn->imm, orig_val, new_val);
insn_idx, insn->imm, (unsigned long long)orig_val,
(unsigned long long)new_val);
return -EINVAL;
}
orig_val = insn->imm;
insn->imm = new_val;
pr_debug("prog '%s': relo #%d: patched insn #%d (ALU/ALU64) imm %u -> %u\n",
pr_debug("prog '%s': relo #%d: patched insn #%d (ALU/ALU64) imm %llu -> %llu\n",
prog_name, relo_idx, insn_idx,
orig_val, new_val);
(unsigned long long)orig_val, (unsigned long long)new_val);
break;
case BPF_LDX:
case BPF_ST:
case BPF_STX:
if (res->validate && insn->off != orig_val) {
pr_warn("prog '%s': relo #%d: unexpected insn #%d (LDX/ST/STX) value: got %u, exp %u -> %u\n",
prog_name, relo_idx, insn_idx, insn->off, orig_val, new_val);
pr_warn("prog '%s': relo #%d: unexpected insn #%d (LDX/ST/STX) value: got %u, exp %llu -> %llu\n",
prog_name, relo_idx, insn_idx, insn->off, (unsigned long long)orig_val,
(unsigned long long)new_val);
return -EINVAL;
}
if (new_val > SHRT_MAX) {
pr_warn("prog '%s': relo #%d: insn #%d (LDX/ST/STX) value too big: %u\n",
prog_name, relo_idx, insn_idx, new_val);
pr_warn("prog '%s': relo #%d: insn #%d (LDX/ST/STX) value too big: %llu\n",
prog_name, relo_idx, insn_idx, (unsigned long long)new_val);
return -ERANGE;
}
if (res->fail_memsz_adjust) {
Expand All @@ -987,8 +989,9 @@ int bpf_core_patch_insn(const char *prog_name, struct bpf_insn *insn,

orig_val = insn->off;
insn->off = new_val;
pr_debug("prog '%s': relo #%d: patched insn #%d (LDX/ST/STX) off %u -> %u\n",
prog_name, relo_idx, insn_idx, orig_val, new_val);
pr_debug("prog '%s': relo #%d: patched insn #%d (LDX/ST/STX) off %llu -> %llu\n",
prog_name, relo_idx, insn_idx, (unsigned long long)orig_val,
(unsigned long long)new_val);

if (res->new_sz != res->orig_sz) {
int insn_bytes_sz, insn_bpf_sz;
Expand Down Expand Up @@ -1026,18 +1029,18 @@ int bpf_core_patch_insn(const char *prog_name, struct bpf_insn *insn,

imm = insn[0].imm + ((__u64)insn[1].imm << 32);
if (res->validate && imm != orig_val) {
pr_warn("prog '%s': relo #%d: unexpected insn #%d (LDIMM64) value: got %llu, exp %u -> %u\n",
pr_warn("prog '%s': relo #%d: unexpected insn #%d (LDIMM64) value: got %llu, exp %llu -> %llu\n",
prog_name, relo_idx,
insn_idx, (unsigned long long)imm,
orig_val, new_val);
(unsigned long long)orig_val, (unsigned long long)new_val);
return -EINVAL;
}

insn[0].imm = new_val;
insn[1].imm = 0; /* currently only 32-bit values are supported */
pr_debug("prog '%s': relo #%d: patched insn #%d (LDIMM64) imm64 %llu -> %u\n",
insn[1].imm = new_val >> 32;
pr_debug("prog '%s': relo #%d: patched insn #%d (LDIMM64) imm64 %llu -> %llu\n",
prog_name, relo_idx, insn_idx,
(unsigned long long)imm, new_val);
(unsigned long long)imm, (unsigned long long)new_val);
break;
}
default:
Expand Down Expand Up @@ -1261,10 +1264,12 @@ int bpf_core_calc_relo_insn(const char *prog_name,
* decision and value, otherwise it's dangerous to
* proceed due to ambiguity
*/
pr_warn("prog '%s': relo #%d: relocation decision ambiguity: %s %u != %s %u\n",
pr_warn("prog '%s': relo #%d: relocation decision ambiguity: %s %llu != %s %llu\n",
prog_name, relo_idx,
cand_res.poison ? "failure" : "success", cand_res.new_val,
targ_res->poison ? "failure" : "success", targ_res->new_val);
cand_res.poison ? "failure" : "success",
(unsigned long long)cand_res.new_val,
targ_res->poison ? "failure" : "success",
(unsigned long long)targ_res->new_val);
return -EINVAL;
}

Expand Down
4 changes: 2 additions & 2 deletions tools/lib/bpf/relo_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ struct bpf_core_spec {

struct bpf_core_relo_res {
/* expected value in the instruction, unless validate == false */
__u32 orig_val;
__u64 orig_val;
/* new value that needs to be patched up to */
__u32 new_val;
__u64 new_val;
/* relocation unsuccessful, poison instruction, but don't fail load */
bool poison;
/* some relocations can't be validated against orig_val */
Expand Down

0 comments on commit 7762816

Please sign in to comment.