Skip to content

Commit aade400

Browse files
committed
[tmp] libbpf: support new LLVM llvm/llvm-project#149715
Signed-off-by: Anton Protopopov <[email protected]>
1 parent e78cfcc commit aade400

File tree

2 files changed

+50
-34
lines changed

2 files changed

+50
-34
lines changed

tools/lib/bpf/libbpf.c

Lines changed: 44 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ enum reloc_type {
372372
RELO_EXTERN_CALL,
373373
RELO_SUBPROG_ADDR,
374374
RELO_CORE,
375+
RELO_INSN_ARRAY,
375376
};
376377

377378
struct reloc_desc {
@@ -383,6 +384,7 @@ struct reloc_desc {
383384
int map_idx;
384385
int sym_off;
385386
int ext_idx;
387+
int sym_size;
386388
};
387389
};
388390
};
@@ -664,6 +666,7 @@ struct elf_state {
664666
Elf_Data *symbols;
665667
Elf_Data *arena_data;
666668
Elf_Data *jt_sizes_data;
669+
Elf_Data *jumptables_data;
667670
size_t shstrndx; /* section index for section name strings */
668671
size_t strtabidx;
669672
struct elf_sec_desc *secs;
@@ -675,6 +678,7 @@ struct elf_state {
675678
bool has_st_ops;
676679
int arena_data_shndx;
677680
int jt_sizes_data_shndx;
681+
int jumptables_data_shndx;
678682
};
679683

680684
struct usdt_manager;
@@ -4064,6 +4068,11 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
40644068
} else if (strcmp(name, ARENA_SEC) == 0) {
40654069
obj->efile.arena_data = data;
40664070
obj->efile.arena_data_shndx = idx;
4071+
} else if (strcmp(name, ".jumptables") == 0) {
4072+
// XXX, do it properly, otherwise ->d_buf is eventually corrupted
4073+
obj->efile.jumptables_data = calloc(1, sizeof(*data));
4074+
memcpy(obj->efile.jumptables_data, data, sizeof(*data));
4075+
obj->efile.jumptables_data_shndx = idx;
40674076
} else {
40684077
pr_info("elf: skipping unrecognized data section(%d) %s\n",
40694078
idx, name);
@@ -4712,6 +4721,16 @@ static int bpf_program__record_reloc(struct bpf_program *prog,
47124721
return 0;
47134722
}
47144723

4724+
/* jump table data relocation */
4725+
if (shdr_idx == obj->efile.jumptables_data_shndx) {
4726+
reloc_desc->type = RELO_INSN_ARRAY;
4727+
reloc_desc->insn_idx = insn_idx;
4728+
reloc_desc->map_idx = -1;
4729+
reloc_desc->sym_off = sym->st_value; // XXX ?
4730+
reloc_desc->sym_size = sym->st_size;
4731+
return 0;
4732+
}
4733+
47154734
/* generic map reference relocation */
47164735
if (type == LIBBPF_MAP_UNSPEC) {
47174736
if (!bpf_object__shndx_is_maps(obj, shdr_idx)) {
@@ -6204,12 +6223,7 @@ static void poison_kfunc_call(struct bpf_program *prog, int relo_idx,
62046223
insn->imm = POISON_CALL_KFUNC_BASE + ext_idx;
62056224
}
62066225

6207-
static bool map_fd_is_rodata(struct bpf_object *obj, int map_fd)
6208-
{
6209-
return map_fd == obj->rodata_map_fd;
6210-
}
6211-
6212-
static int create_jt_map(const struct jt *jt, int adjust_off)
6226+
static int create_jt_map(struct bpf_object *obj, int off, int size, int adjust_off)
62136227
{
62146228
static union bpf_attr attr = {
62156229
.map_type = BPF_MAP_TYPE_INSN_ARRAY,
@@ -6221,15 +6235,20 @@ static int create_jt_map(const struct jt *jt, int adjust_off)
62216235
int map_fd;
62226236
int err;
62236237
__u32 i;
6238+
__u32 *jt;
62246239

6225-
attr.max_entries = jt->jump_target_cnt;
6240+
attr.max_entries = size / 4;
62266241

62276242
map_fd = syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
62286243
if (map_fd < 0)
62296244
return map_fd;
62306245

6231-
for (i = 0; i < jt->jump_target_cnt; i++) {
6232-
val.xlated_off = jt->jump_target[i] + adjust_off;
6246+
jt = (__u32 *)(obj->efile.jumptables_data->d_buf + off);
6247+
if (!jt)
6248+
return -EINVAL;
6249+
6250+
for (i = 0; i < attr.max_entries; i++) {
6251+
val.xlated_off = jt[2*i]/8 + adjust_off;
62336252
err = bpf_map_update_elem(map_fd, &i, &val, 0);
62346253
if (err) {
62356254
close(map_fd);
@@ -6257,6 +6276,7 @@ static int subprog_insn_off(struct bpf_program *prog, int insn_idx)
62576276
return -prog->sec_insn_off;
62586277
}
62596278

6279+
62606280
/* Relocate data references within program code:
62616281
* - map references;
62626282
* - global variable references;
@@ -6294,31 +6314,8 @@ bpf_object__relocate_data(struct bpf_object *obj, struct bpf_program *prog)
62946314
insn[0].src_reg = BPF_PSEUDO_MAP_IDX_VALUE;
62956315
insn[0].imm = relo->map_idx;
62966316
} else if (map->autocreate) {
6297-
const struct jt *jt;
6298-
int ajdust_insn_off;
6299-
int map_fd = map->fd;
6300-
6301-
/*
6302-
* Set imm to proper map file descriptor. In normal case,
6303-
* it is just map->fd. However, in case of a jump table,
6304-
* a new map file descriptor should be created
6305-
*/
6306-
jt = bpf_object__find_jt(obj, insn[1].imm / 8);
6307-
if (map_fd_is_rodata(obj, map_fd) && !IS_ERR(jt)) {
6308-
ajdust_insn_off = subprog_insn_off(prog, relo->insn_idx);
6309-
map_fd = create_jt_map(jt, ajdust_insn_off);
6310-
if (map_fd < 0) {
6311-
pr_warn("prog '%s': relo #%d: failed to create a jt map for .rodata offset %u\n",
6312-
prog->name, i, insn[1].imm / 8);
6313-
return map_fd;
6314-
}
6315-
6316-
/* a new map is created, so offset should be 0 */
6317-
insn[1].imm = 0;
6318-
}
6319-
63206317
insn[0].src_reg = BPF_PSEUDO_MAP_VALUE;
6321-
insn[0].imm = map_fd;
6318+
insn[0].imm = map->fd;
63226319
} else {
63236320
poison_map_ldimm64(prog, i, relo->insn_idx, insn,
63246321
relo->map_idx, map);
@@ -6371,6 +6368,20 @@ bpf_object__relocate_data(struct bpf_object *obj, struct bpf_program *prog)
63716368
case RELO_CORE:
63726369
/* will be handled by bpf_program_record_relos() */
63736370
break;
6371+
case RELO_INSN_ARRAY: {
6372+
int map_fd;
6373+
6374+
map_fd = create_jt_map(obj, relo->sym_off, relo->sym_size, subprog_insn_off(prog, relo->insn_idx));
6375+
if (map_fd < 0) {
6376+
pr_warn("prog '%s': relo #%d: failed to create a jt map for .rodata offset %u\n",
6377+
prog->name, i, relo->sym_off);
6378+
return map_fd;
6379+
}
6380+
insn[0].src_reg = BPF_PSEUDO_MAP_VALUE;
6381+
insn->imm = map_fd;
6382+
insn->off = 0;
6383+
}
6384+
break;
63746385
default:
63756386
pr_warn("prog '%s': relo #%d: bad relo type %d\n",
63766387
prog->name, i, relo->type);

tools/lib/bpf/linker.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
#define BTF_EXTERN_SEC ".extern"
3131
#define RODATA_REL_SEC ".rel.rodata"
32+
#define JUMPTABLES_REL_SEC ".rel.jumptables"
3233
#define LLVM_JT_SIZES_REL_SEC ".rel.llvm_jump_table_sizes"
3334

3435
struct src_sec {
@@ -2084,6 +2085,9 @@ static int linker_append_elf_sym(struct bpf_linker *linker, struct src_obj *obj,
20842085
obj->sym_map[src_sym_idx] = dst_sec->sec_sym_idx;
20852086
return 0;
20862087
}
2088+
2089+
if (!strcmp(src_sec->sec_name, ".jumptables"))
2090+
goto add_sym;
20872091
}
20882092

20892093
if (sym_bind == STB_LOCAL)
@@ -2331,7 +2335,8 @@ static int linker_append_elf_relos(struct bpf_linker *linker, struct src_obj *ob
23312335
else
23322336
insn->imm += sec->dst_off;
23332337
} else if (strcmp(src_sec->sec_name, LLVM_JT_SIZES_REL_SEC) &&
2334-
strcmp(src_sec->sec_name, RODATA_REL_SEC)) {
2338+
strcmp(src_sec->sec_name, RODATA_REL_SEC) &&
2339+
strcmp(src_sec->sec_name, JUMPTABLES_REL_SEC)) {
23352340
pr_warn("relocation against STT_SECTION in section %s is not supported!\n",
23362341
src_sec->sec_name);
23372342
return -EINVAL;

0 commit comments

Comments
 (0)