From: Joe Stringer Subject: bpf: bss section poc Patch-mainline: No, status unknown, seems to be implemented in libbpf instead References: none The .bss section denotes uninitialized data, which is for instance what clang will generate if a static variable is set to zero by default. Teach the bpf library about .bss so that such variables can be properly initialized. Signed-off-by: Joe Stringer --- lib/bpf.c | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) --- a/lib/bpf.c +++ b/lib/bpf.c @@ -1164,6 +1164,7 @@ struct bpf_elf_ctx { int sec_text; int sec_btf; int sec_data; + int sec_bss; char license[ELF_MAX_LICENSE_LEN]; enum bpf_prog_type type; __u32 ifindex; @@ -2068,6 +2069,14 @@ static int bpf_fetch_data(struct bpf_elf_ctx *ctx, int section, return 0; } +static int bpf_fetch_bss(struct bpf_elf_ctx *ctx, int section, + struct bpf_elf_sec_data *data) +{ + ctx->sec_bss = section; + ctx->sec_done[section] = true; + return 0; +} + static void bpf_btf_report(int fd, struct bpf_elf_ctx *ctx) { fprintf(stderr, "\nBTF debug data section \'.BTF\' %s%s (%d)!\n", @@ -2286,6 +2295,11 @@ static bool bpf_has_glob_data(const struct bpf_elf_ctx *ctx) return ctx->sec_data; } +static bool bpf_has_bss_data(const struct bpf_elf_ctx *ctx) +{ + return ctx->sec_bss; +} + static int bpf_fetch_ancillary(struct bpf_elf_ctx *ctx, bool check_text_sec) { struct bpf_elf_sec_data data; @@ -2310,6 +2324,9 @@ static int bpf_fetch_ancillary(struct bpf_elf_ctx *ctx, bool check_text_sec) else if (data.sec_hdr.sh_type == SHT_PROGBITS && !strcmp(data.sec_name, ".data")) ret = bpf_fetch_data(ctx, i, &data); + else if (data.sec_hdr.sh_type == SHT_NOBITS && + !strcmp(data.sec_name, ".bss")) + ret = bpf_fetch_bss(ctx, i, &data); else if (data.sec_hdr.sh_type == SHT_SYMTAB && !strcmp(data.sec_name, ".symtab")) ret = bpf_fetch_symtab(ctx, i, &data); @@ -2438,6 +2455,19 @@ static int bpf_apply_relo_glob(struct bpf_elf_ctx *ctx, struct bpf_elf_prog *pro return 0; } +static int bpf_apply_relo_bss(struct bpf_elf_ctx *ctx, struct bpf_elf_prog *prog, + GElf_Rel *relo, GElf_Sym *sym, + struct bpf_relo_props *props) +{ + unsigned int insn_off = relo->r_offset / sizeof(struct bpf_insn); + + if (insn_off >= prog->insns_num) + return -EINVAL; + + prog->insns[insn_off].imm = 0; + return 0; +} + static int bpf_apply_relo_call(struct bpf_elf_ctx *ctx, struct bpf_elf_prog *prog, GElf_Rel *relo, GElf_Sym *sym, struct bpf_relo_props *props) @@ -2494,10 +2524,12 @@ static int bpf_apply_relo_data(struct bpf_elf_ctx *ctx, ret = bpf_apply_relo_map(ctx, prog, &relo, &sym, props); else if (sym.st_shndx == ctx->sec_data) ret = bpf_apply_relo_glob(ctx, prog, &relo, &sym, props); + else if (sym.st_shndx == ctx->sec_bss) + ret = bpf_apply_relo_bss(ctx, prog, &relo, &sym, props); else if (sym.st_shndx == ctx->sec_text) ret = bpf_apply_relo_call(ctx, prog, &relo, &sym, props); else - fprintf(stderr, "ELF contains non-{map,data,call} related relo data in entry %u pointing to section %u! Compiler bug?!\n", + fprintf(stderr, "ELF contains non-{bss,call,data,map} related relo data in entry %u pointing to section %u! Compiler bug?!\n", relo_ent, sym.st_shndx); if (ret < 0) return ret; @@ -2593,7 +2625,8 @@ static int bpf_fetch_prog_sec(struct bpf_elf_ctx *ctx, const char *section) return ret; } - if (bpf_has_map_data(ctx) || bpf_has_call_data(ctx) || bpf_has_glob_data(ctx)) + if (bpf_has_map_data(ctx) || bpf_has_call_data(ctx) || + bpf_has_glob_data(ctx) || bpf_has_bss_data(ctx)) ret = bpf_fetch_prog_relo(ctx, section, &lderr, &sseen, &prog); if (ret < 0 && !lderr) ret = bpf_fetch_prog(ctx, section, &sseen);