Skip to content

Commit

Permalink
bpftool: Improve skeleton generation for data maps without DATASEC type
Browse files Browse the repository at this point in the history
It can happen that some data sections (e.g., .rodata.cst16, containing
compiler populated string constants) won't have a corresponding BTF
DATASEC type. Now that libbpf supports .rodata.* and .data.* sections,
situation like that will cause invalid BPF skeleton to be generated that
won't compile successfully, as some parts of skeleton would assume
memory-mapped struct definitions for each special data section.

Fix this by generating empty struct definitions for such data sections.

Signed-off-by: Andrii Nakryiko <[email protected]>
Signed-off-by: Alexei Starovoitov <[email protected]>
Acked-by: Song Liu <[email protected]>
Link: https://lore.kernel.org/bpf/[email protected]
  • Loading branch information
anakryiko authored and Alexei Starovoitov committed Oct 22, 2021
1 parent 8654b4d commit ef9356d
Showing 1 changed file with 45 additions and 6 deletions.
51 changes: 45 additions & 6 deletions tools/bpf/bpftool/gen.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,22 +213,61 @@ static int codegen_datasecs(struct bpf_object *obj, const char *obj_name)
struct btf *btf = bpf_object__btf(obj);
int n = btf__get_nr_types(btf);
struct btf_dump *d;
struct bpf_map *map;
const struct btf_type *sec;
char sec_ident[256], map_ident[256];
int i, err = 0;

d = btf_dump__new(btf, NULL, NULL, codegen_btf_dump_printf);
if (IS_ERR(d))
return PTR_ERR(d);

for (i = 1; i <= n; i++) {
const struct btf_type *t = btf__type_by_id(btf, i);
bpf_object__for_each_map(map, obj) {
/* only generate definitions for memory-mapped internal maps */
if (!bpf_map__is_internal(map))
continue;
if (!(bpf_map__def(map)->map_flags & BPF_F_MMAPABLE))
continue;

if (!btf_is_datasec(t))
if (!get_map_ident(map, map_ident, sizeof(map_ident)))
continue;

err = codegen_datasec_def(obj, btf, d, t, obj_name);
if (err)
goto out;
sec = NULL;
for (i = 1; i <= n; i++) {
const struct btf_type *t = btf__type_by_id(btf, i);
const char *name;

if (!btf_is_datasec(t))
continue;

name = btf__str_by_offset(btf, t->name_off);
if (!get_datasec_ident(name, sec_ident, sizeof(sec_ident)))
continue;

if (strcmp(sec_ident, map_ident) == 0) {
sec = t;
break;
}
}

/* In some cases (e.g., sections like .rodata.cst16 containing
* compiler allocated string constants only) there will be
* special internal maps with no corresponding DATASEC BTF
* type. In such case, generate empty structs for each such
* map. It will still be memory-mapped and its contents
* accessible from user-space through BPF skeleton.
*/
if (!sec) {
printf(" struct %s__%s {\n", obj_name, map_ident);
printf(" } *%s;\n", map_ident);
} else {
err = codegen_datasec_def(obj, btf, d, sec, obj_name);
if (err)
goto out;
}
}


out:
btf_dump__free(d);
return err;
Expand Down

0 comments on commit ef9356d

Please sign in to comment.