From: Daniel Borkmann <daniel@iogearbox.net>
Subject: bpf: data section support poc
Patch-mainline: No, status unknown, seems to be implemented in libbpf instead
References: none

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
---
 lib/bpf.c | 40 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 38 insertions(+), 2 deletions(-)

--- a/lib/bpf.c
+++ b/lib/bpf.c
@@ -1147,6 +1147,7 @@ struct bpf_elf_ctx {
 	Elf_Data		*sym_tab;
 	Elf_Data		*str_tab;
 	Elf_Data		*btf_data;
+	Elf_Data		*glo_data;
 	char			obj_uid[64];
 	int			obj_fd;
 	int			btf_fd;
@@ -1162,6 +1163,7 @@ struct bpf_elf_ctx {
 	int			sec_maps;
 	int			sec_text;
 	int			sec_btf;
+	int			sec_data;
 	char			license[ELF_MAX_LICENSE_LEN];
 	enum bpf_prog_type	type;
 	__u32			ifindex;
@@ -2057,6 +2059,15 @@ static int bpf_fetch_text(struct bpf_elf_ctx *ctx, int section,
 	return 0;
 }
 
+static int bpf_fetch_data(struct bpf_elf_ctx *ctx, int section,
+			  struct bpf_elf_sec_data *data)
+{
+	ctx->sec_data = section;
+	ctx->glo_data = data->sec_data;
+	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",
@@ -2270,6 +2281,11 @@ static bool bpf_has_call_data(const struct bpf_elf_ctx *ctx)
 	return ctx->sec_text;
 }
 
+static bool bpf_has_glob_data(const struct bpf_elf_ctx *ctx)
+{
+	return ctx->sec_data;
+}
+
 static int bpf_fetch_ancillary(struct bpf_elf_ctx *ctx, bool check_text_sec)
 {
 	struct bpf_elf_sec_data data;
@@ -2291,6 +2307,9 @@ static int bpf_fetch_ancillary(struct bpf_elf_ctx *ctx, bool check_text_sec)
 			 !strcmp(data.sec_name, ".text") &&
 			 check_text_sec)
 			ret = bpf_fetch_text(ctx, i, &data);
+		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_SYMTAB &&
 			 !strcmp(data.sec_name, ".symtab"))
 			ret = bpf_fetch_symtab(ctx, i, &data);
@@ -2404,6 +2423,21 @@ static int bpf_apply_relo_map(struct bpf_elf_ctx *ctx, struct bpf_elf_prog *prog
 	return 0;
 }
 
+static int bpf_apply_relo_glob(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);
+	int *data;
+
+	if (insn_off >= prog->insns_num)
+		return -EINVAL;
+
+	data = ctx->glo_data->d_buf + sym->st_value;
+	prog->insns[insn_off].imm = *data;
+	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)
@@ -2458,10 +2492,12 @@ static int bpf_apply_relo_data(struct bpf_elf_ctx *ctx,
 
 		if (sym.st_shndx == ctx->sec_maps)
 			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_text)
 			ret = bpf_apply_relo_call(ctx, prog, &relo, &sym, props);
 		else
-			fprintf(stderr, "ELF contains non-{map,call} related relo data in entry %u pointing to section %u! Compiler bug?!\n",
+			fprintf(stderr, "ELF contains non-{map,data,call} related relo data in entry %u pointing to section %u! Compiler bug?!\n",
 				relo_ent, sym.st_shndx);
 		if (ret < 0)
 			return ret;
@@ -2557,7 +2593,7 @@ 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))
+	if (bpf_has_map_data(ctx) || bpf_has_call_data(ctx) || bpf_has_glob_data(ctx))
 		ret = bpf_fetch_prog_relo(ctx, section, &lderr, &sseen, &prog);
 	if (ret < 0 && !lderr)
 		ret = bpf_fetch_prog(ctx, section, &sseen);
