Commit 81bfdd08 authored by Andrii Nakryiko's avatar Andrii Nakryiko Committed by Alexei Starovoitov

libbpf: Put Kconfig externs into .kconfig section

Move Kconfig-provided externs into custom .kconfig section. Add __kconfig into
bpf_helpers.h for user convenience. Update selftests accordingly.
Suggested-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Signed-off-by: default avatarAndrii Nakryiko <andriin@fb.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20191219002837.3074619-2-andriin@fb.com
parent d6958706
...@@ -83,8 +83,8 @@ static const char *get_map_ident(const struct bpf_map *map) ...@@ -83,8 +83,8 @@ static const char *get_map_ident(const struct bpf_map *map)
return "rodata"; return "rodata";
else if (str_has_suffix(name, ".bss")) else if (str_has_suffix(name, ".bss"))
return "bss"; return "bss";
else if (str_has_suffix(name, ".extern")) else if (str_has_suffix(name, ".kconfig"))
return "externs"; /* extern is a C keyword */ return "kconfig";
else else
return NULL; return NULL;
} }
...@@ -112,8 +112,8 @@ static int codegen_datasec_def(struct bpf_object *obj, ...@@ -112,8 +112,8 @@ static int codegen_datasec_def(struct bpf_object *obj,
sec_ident = "bss"; sec_ident = "bss";
else if (strcmp(sec_name, ".rodata") == 0) else if (strcmp(sec_name, ".rodata") == 0)
sec_ident = "rodata"; sec_ident = "rodata";
else if (strcmp(sec_name, ".extern") == 0) else if (strcmp(sec_name, ".kconfig") == 0)
sec_ident = "externs"; /* extern is a C keyword */ sec_ident = "kconfig";
else else
return 0; return 0;
......
...@@ -53,4 +53,6 @@ enum libbpf_tristate { ...@@ -53,4 +53,6 @@ enum libbpf_tristate {
TRI_MODULE = 2, TRI_MODULE = 2,
}; };
#define __kconfig __attribute__((section(".kconfig")))
#endif #endif
...@@ -231,21 +231,21 @@ struct bpf_program { ...@@ -231,21 +231,21 @@ struct bpf_program {
#define DATA_SEC ".data" #define DATA_SEC ".data"
#define BSS_SEC ".bss" #define BSS_SEC ".bss"
#define RODATA_SEC ".rodata" #define RODATA_SEC ".rodata"
#define EXTERN_SEC ".extern" #define KCONFIG_SEC ".kconfig"
enum libbpf_map_type { enum libbpf_map_type {
LIBBPF_MAP_UNSPEC, LIBBPF_MAP_UNSPEC,
LIBBPF_MAP_DATA, LIBBPF_MAP_DATA,
LIBBPF_MAP_BSS, LIBBPF_MAP_BSS,
LIBBPF_MAP_RODATA, LIBBPF_MAP_RODATA,
LIBBPF_MAP_EXTERN, LIBBPF_MAP_KCONFIG,
}; };
static const char * const libbpf_type_to_btf_name[] = { static const char * const libbpf_type_to_btf_name[] = {
[LIBBPF_MAP_DATA] = DATA_SEC, [LIBBPF_MAP_DATA] = DATA_SEC,
[LIBBPF_MAP_BSS] = BSS_SEC, [LIBBPF_MAP_BSS] = BSS_SEC,
[LIBBPF_MAP_RODATA] = RODATA_SEC, [LIBBPF_MAP_RODATA] = RODATA_SEC,
[LIBBPF_MAP_EXTERN] = EXTERN_SEC, [LIBBPF_MAP_KCONFIG] = KCONFIG_SEC,
}; };
struct bpf_map { struct bpf_map {
...@@ -305,7 +305,7 @@ struct bpf_object { ...@@ -305,7 +305,7 @@ struct bpf_object {
char *kconfig_path; char *kconfig_path;
struct extern_desc *externs; struct extern_desc *externs;
int nr_extern; int nr_extern;
int extern_map_idx; int kconfig_map_idx;
bool loaded; bool loaded;
bool has_pseudo_calls; bool has_pseudo_calls;
...@@ -606,7 +606,7 @@ static struct bpf_object *bpf_object__new(const char *path, ...@@ -606,7 +606,7 @@ static struct bpf_object *bpf_object__new(const char *path,
obj->efile.data_shndx = -1; obj->efile.data_shndx = -1;
obj->efile.rodata_shndx = -1; obj->efile.rodata_shndx = -1;
obj->efile.bss_shndx = -1; obj->efile.bss_shndx = -1;
obj->extern_map_idx = -1; obj->kconfig_map_idx = -1;
obj->kern_version = get_kernel_version(); obj->kern_version = get_kernel_version();
obj->loaded = false; obj->loaded = false;
...@@ -902,11 +902,25 @@ static size_t bpf_map_mmap_sz(const struct bpf_map *map) ...@@ -902,11 +902,25 @@ static size_t bpf_map_mmap_sz(const struct bpf_map *map)
return map_sz; return map_sz;
} }
static char *internal_map_name(struct bpf_object *obj,
enum libbpf_map_type type)
{
char map_name[BPF_OBJ_NAME_LEN];
const char *sfx = libbpf_type_to_btf_name[type];
int sfx_len = max((size_t)7, strlen(sfx));
int pfx_len = min((size_t)BPF_OBJ_NAME_LEN - sfx_len - 1,
strlen(obj->name));
snprintf(map_name, sizeof(map_name), "%.*s%.*s", pfx_len, obj->name,
sfx_len, libbpf_type_to_btf_name[type]);
return strdup(map_name);
}
static int static int
bpf_object__init_internal_map(struct bpf_object *obj, enum libbpf_map_type type, bpf_object__init_internal_map(struct bpf_object *obj, enum libbpf_map_type type,
int sec_idx, void *data, size_t data_sz) int sec_idx, void *data, size_t data_sz)
{ {
char map_name[BPF_OBJ_NAME_LEN];
struct bpf_map_def *def; struct bpf_map_def *def;
struct bpf_map *map; struct bpf_map *map;
int err; int err;
...@@ -918,9 +932,7 @@ bpf_object__init_internal_map(struct bpf_object *obj, enum libbpf_map_type type, ...@@ -918,9 +932,7 @@ bpf_object__init_internal_map(struct bpf_object *obj, enum libbpf_map_type type,
map->libbpf_type = type; map->libbpf_type = type;
map->sec_idx = sec_idx; map->sec_idx = sec_idx;
map->sec_offset = 0; map->sec_offset = 0;
snprintf(map_name, sizeof(map_name), "%.8s%.7s", obj->name, map->name = internal_map_name(obj, type);
libbpf_type_to_btf_name[type]);
map->name = strdup(map_name);
if (!map->name) { if (!map->name) {
pr_warn("failed to alloc map name\n"); pr_warn("failed to alloc map name\n");
return -ENOMEM; return -ENOMEM;
...@@ -931,12 +943,12 @@ bpf_object__init_internal_map(struct bpf_object *obj, enum libbpf_map_type type, ...@@ -931,12 +943,12 @@ bpf_object__init_internal_map(struct bpf_object *obj, enum libbpf_map_type type,
def->key_size = sizeof(int); def->key_size = sizeof(int);
def->value_size = data_sz; def->value_size = data_sz;
def->max_entries = 1; def->max_entries = 1;
def->map_flags = type == LIBBPF_MAP_RODATA || type == LIBBPF_MAP_EXTERN def->map_flags = type == LIBBPF_MAP_RODATA || type == LIBBPF_MAP_KCONFIG
? BPF_F_RDONLY_PROG : 0; ? BPF_F_RDONLY_PROG : 0;
def->map_flags |= BPF_F_MMAPABLE; def->map_flags |= BPF_F_MMAPABLE;
pr_debug("map '%s' (global data): at sec_idx %d, offset %zu, flags %x.\n", pr_debug("map '%s' (global data): at sec_idx %d, offset %zu, flags %x.\n",
map_name, map->sec_idx, map->sec_offset, def->map_flags); map->name, map->sec_idx, map->sec_offset, def->map_flags);
map->mmaped = mmap(NULL, bpf_map_mmap_sz(map), PROT_READ | PROT_WRITE, map->mmaped = mmap(NULL, bpf_map_mmap_sz(map), PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0); MAP_SHARED | MAP_ANONYMOUS, -1, 0);
...@@ -1232,7 +1244,7 @@ static int bpf_object__read_kernel_config(struct bpf_object *obj, ...@@ -1232,7 +1244,7 @@ static int bpf_object__read_kernel_config(struct bpf_object *obj,
return err; return err;
} }
static int bpf_object__init_extern_map(struct bpf_object *obj) static int bpf_object__init_kconfig_map(struct bpf_object *obj)
{ {
struct extern_desc *last_ext; struct extern_desc *last_ext;
size_t map_sz; size_t map_sz;
...@@ -1244,13 +1256,13 @@ static int bpf_object__init_extern_map(struct bpf_object *obj) ...@@ -1244,13 +1256,13 @@ static int bpf_object__init_extern_map(struct bpf_object *obj)
last_ext = &obj->externs[obj->nr_extern - 1]; last_ext = &obj->externs[obj->nr_extern - 1];
map_sz = last_ext->data_off + last_ext->sz; map_sz = last_ext->data_off + last_ext->sz;
err = bpf_object__init_internal_map(obj, LIBBPF_MAP_EXTERN, err = bpf_object__init_internal_map(obj, LIBBPF_MAP_KCONFIG,
obj->efile.symbols_shndx, obj->efile.symbols_shndx,
NULL, map_sz); NULL, map_sz);
if (err) if (err)
return err; return err;
obj->extern_map_idx = obj->nr_maps - 1; obj->kconfig_map_idx = obj->nr_maps - 1;
return 0; return 0;
} }
...@@ -1742,7 +1754,7 @@ static int bpf_object__init_maps(struct bpf_object *obj, ...@@ -1742,7 +1754,7 @@ static int bpf_object__init_maps(struct bpf_object *obj,
err = bpf_object__init_user_maps(obj, strict); err = bpf_object__init_user_maps(obj, strict);
err = err ?: bpf_object__init_user_btf_maps(obj, strict, pin_root_path); err = err ?: bpf_object__init_user_btf_maps(obj, strict, pin_root_path);
err = err ?: bpf_object__init_global_data_maps(obj); err = err ?: bpf_object__init_global_data_maps(obj);
err = err ?: bpf_object__init_extern_map(obj); err = err ?: bpf_object__init_kconfig_map(obj);
if (err) if (err)
return err; return err;
...@@ -2269,9 +2281,9 @@ static int bpf_object__collect_externs(struct bpf_object *obj) ...@@ -2269,9 +2281,9 @@ static int bpf_object__collect_externs(struct bpf_object *obj)
i, ext->sym_idx, ext->data_off, ext->name); i, ext->sym_idx, ext->data_off, ext->name);
} }
btf_id = btf__find_by_name(obj->btf, EXTERN_SEC); btf_id = btf__find_by_name(obj->btf, KCONFIG_SEC);
if (btf_id <= 0) { if (btf_id <= 0) {
pr_warn("no BTF info found for '%s' datasec\n", EXTERN_SEC); pr_warn("no BTF info found for '%s' datasec\n", KCONFIG_SEC);
return -ESRCH; return -ESRCH;
} }
...@@ -2361,7 +2373,7 @@ bpf_object__section_to_libbpf_map_type(const struct bpf_object *obj, int shndx) ...@@ -2361,7 +2373,7 @@ bpf_object__section_to_libbpf_map_type(const struct bpf_object *obj, int shndx)
else if (shndx == obj->efile.rodata_shndx) else if (shndx == obj->efile.rodata_shndx)
return LIBBPF_MAP_RODATA; return LIBBPF_MAP_RODATA;
else if (shndx == obj->efile.symbols_shndx) else if (shndx == obj->efile.symbols_shndx)
return LIBBPF_MAP_EXTERN; return LIBBPF_MAP_KCONFIG;
else else
return LIBBPF_MAP_UNSPEC; return LIBBPF_MAP_UNSPEC;
} }
...@@ -2908,8 +2920,8 @@ bpf_object__populate_internal_map(struct bpf_object *obj, struct bpf_map *map) ...@@ -2908,8 +2920,8 @@ bpf_object__populate_internal_map(struct bpf_object *obj, struct bpf_map *map)
return err; return err;
} }
/* Freeze .rodata and .extern map as read-only from syscall side. */ /* Freeze .rodata and .kconfig map as read-only from syscall side. */
if (map_type == LIBBPF_MAP_RODATA || map_type == LIBBPF_MAP_EXTERN) { if (map_type == LIBBPF_MAP_RODATA || map_type == LIBBPF_MAP_KCONFIG) {
err = bpf_map_freeze(map->fd); err = bpf_map_freeze(map->fd);
if (err) { if (err) {
err = -errno; err = -errno;
...@@ -4264,7 +4276,7 @@ bpf_program__relocate(struct bpf_program *prog, struct bpf_object *obj) ...@@ -4264,7 +4276,7 @@ bpf_program__relocate(struct bpf_program *prog, struct bpf_object *obj)
break; break;
case RELO_EXTERN: case RELO_EXTERN:
insn[0].src_reg = BPF_PSEUDO_MAP_VALUE; insn[0].src_reg = BPF_PSEUDO_MAP_VALUE;
insn[0].imm = obj->maps[obj->extern_map_idx].fd; insn[0].imm = obj->maps[obj->kconfig_map_idx].fd;
insn[1].imm = relo->sym_off; insn[1].imm = relo->sym_off;
break; break;
case RELO_CALL: case RELO_CALL:
...@@ -4743,7 +4755,7 @@ static int bpf_object__resolve_externs(struct bpf_object *obj, ...@@ -4743,7 +4755,7 @@ static int bpf_object__resolve_externs(struct bpf_object *obj,
if (obj->nr_extern == 0) if (obj->nr_extern == 0)
return 0; return 0;
data = obj->maps[obj->extern_map_idx].mmaped; data = obj->maps[obj->kconfig_map_idx].mmaped;
for (i = 0; i < obj->nr_extern; i++) { for (i = 0; i < obj->nr_extern; i++) {
ext = &obj->externs[i]; ext = &obj->externs[i];
...@@ -7546,7 +7558,7 @@ int bpf_object__open_skeleton(struct bpf_object_skeleton *s, ...@@ -7546,7 +7558,7 @@ int bpf_object__open_skeleton(struct bpf_object_skeleton *s,
} }
/* externs shouldn't be pre-setup from user code */ /* externs shouldn't be pre-setup from user code */
if (mmaped && (*map)->libbpf_type != LIBBPF_MAP_EXTERN) if (mmaped && (*map)->libbpf_type != LIBBPF_MAP_KCONFIG)
*mmaped = (*map)->mmaped; *mmaped = (*map)->mmaped;
} }
......
...@@ -15,20 +15,18 @@ void test_skeleton(void) ...@@ -15,20 +15,18 @@ void test_skeleton(void)
int duration = 0, err; int duration = 0, err;
struct test_skeleton* skel; struct test_skeleton* skel;
struct test_skeleton__bss *bss; struct test_skeleton__bss *bss;
struct test_skeleton__externs *exts; struct test_skeleton__kconfig *kcfg;
skel = test_skeleton__open(); skel = test_skeleton__open();
if (CHECK(!skel, "skel_open", "failed to open skeleton\n")) if (CHECK(!skel, "skel_open", "failed to open skeleton\n"))
return; return;
printf("EXTERNS BEFORE: %p\n", skel->externs); if (CHECK(skel->kconfig, "skel_kconfig", "kconfig is mmaped()!\n"))
if (CHECK(skel->externs, "skel_externs", "externs are mmaped()!\n"))
goto cleanup; goto cleanup;
err = test_skeleton__load(skel); err = test_skeleton__load(skel);
if (CHECK(err, "skel_load", "failed to load skeleton: %d\n", err)) if (CHECK(err, "skel_load", "failed to load skeleton: %d\n", err))
goto cleanup; goto cleanup;
printf("EXTERNS AFTER: %p\n", skel->externs);
bss = skel->bss; bss = skel->bss;
bss->in1 = 1; bss->in1 = 1;
...@@ -37,7 +35,7 @@ void test_skeleton(void) ...@@ -37,7 +35,7 @@ void test_skeleton(void)
bss->in4 = 4; bss->in4 = 4;
bss->in5.a = 5; bss->in5.a = 5;
bss->in5.b = 6; bss->in5.b = 6;
exts = skel->externs; kcfg = skel->kconfig;
err = test_skeleton__attach(skel); err = test_skeleton__attach(skel);
if (CHECK(err, "skel_attach", "skeleton attach failed: %d\n", err)) if (CHECK(err, "skel_attach", "skeleton attach failed: %d\n", err))
...@@ -55,10 +53,10 @@ void test_skeleton(void) ...@@ -55,10 +53,10 @@ void test_skeleton(void)
CHECK(bss->handler_out5.b != 6, "res6", "got %lld != exp %d\n", CHECK(bss->handler_out5.b != 6, "res6", "got %lld != exp %d\n",
bss->handler_out5.b, 6); bss->handler_out5.b, 6);
CHECK(bss->bpf_syscall != exts->CONFIG_BPF_SYSCALL, "ext1", CHECK(bss->bpf_syscall != kcfg->CONFIG_BPF_SYSCALL, "ext1",
"got %d != exp %d\n", bss->bpf_syscall, exts->CONFIG_BPF_SYSCALL); "got %d != exp %d\n", bss->bpf_syscall, kcfg->CONFIG_BPF_SYSCALL);
CHECK(bss->kern_ver != exts->LINUX_KERNEL_VERSION, "ext2", CHECK(bss->kern_ver != kcfg->LINUX_KERNEL_VERSION, "ext2",
"got %d != exp %d\n", bss->kern_ver, exts->LINUX_KERNEL_VERSION); "got %d != exp %d\n", bss->kern_ver, kcfg->LINUX_KERNEL_VERSION);
cleanup: cleanup:
test_skeleton__destroy(skel); test_skeleton__destroy(skel);
......
...@@ -10,16 +10,16 @@ ...@@ -10,16 +10,16 @@
/* non-existing BPF helper, to test dead code elimination */ /* non-existing BPF helper, to test dead code elimination */
static int (*bpf_missing_helper)(const void *arg1, int arg2) = (void *) 999; static int (*bpf_missing_helper)(const void *arg1, int arg2) = (void *) 999;
extern int LINUX_KERNEL_VERSION; extern int LINUX_KERNEL_VERSION __kconfig;
extern bool CONFIG_BPF_SYSCALL; /* strong */ extern bool CONFIG_BPF_SYSCALL __kconfig; /* strong */
extern enum libbpf_tristate CONFIG_TRISTATE __weak; extern enum libbpf_tristate CONFIG_TRISTATE __kconfig __weak;
extern bool CONFIG_BOOL __weak; extern bool CONFIG_BOOL __kconfig __weak;
extern char CONFIG_CHAR __weak; extern char CONFIG_CHAR __kconfig __weak;
extern uint16_t CONFIG_USHORT __weak; extern uint16_t CONFIG_USHORT __kconfig __weak;
extern int CONFIG_INT __weak; extern int CONFIG_INT __kconfig __weak;
extern uint64_t CONFIG_ULONG __weak; extern uint64_t CONFIG_ULONG __kconfig __weak;
extern const char CONFIG_STR[8] __weak; extern const char CONFIG_STR[8] __kconfig __weak;
extern uint64_t CONFIG_MISSING __weak; extern uint64_t CONFIG_MISSING __kconfig __weak;
uint64_t kern_ver = -1; uint64_t kern_ver = -1;
uint64_t bpf_syscall = -1; uint64_t bpf_syscall = -1;
......
...@@ -21,8 +21,8 @@ char out3 = 0; ...@@ -21,8 +21,8 @@ char out3 = 0;
long long out4 = 0; long long out4 = 0;
int out1 = 0; int out1 = 0;
extern bool CONFIG_BPF_SYSCALL; extern bool CONFIG_BPF_SYSCALL __kconfig;
extern int LINUX_KERNEL_VERSION; extern int LINUX_KERNEL_VERSION __kconfig;
bool bpf_syscall = 0; bool bpf_syscall = 0;
int kern_ver = 0; int kern_ver = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment