linma / rpms / iproute

Forked from rpms/iproute 4 years ago
Clone

Blame SOURCES/0058-bpf-implement-bpf-to-bpf-calls-support.patch

7e752c
From 80dcb40f8442f79a043c520ae9eef067519ee7ca Mon Sep 17 00:00:00 2001
7e752c
From: Andrea Claudi <aclaudi@redhat.com>
7e752c
Date: Thu, 13 Jun 2019 14:37:56 +0200
7e752c
Subject: [PATCH] bpf: implement bpf to bpf calls support
7e752c
7e752c
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1716361
7e752c
Upstream Status: iproute2.git commit b5cb33aec65cb
7e752c
7e752c
commit b5cb33aec65cb77183abbdfa5b61ecc9877ec776
7e752c
Author: Daniel Borkmann <daniel@iogearbox.net>
7e752c
Date:   Wed Jul 18 01:31:21 2018 +0200
7e752c
7e752c
    bpf: implement bpf to bpf calls support
7e752c
7e752c
    Implement missing bpf to bpf calls support. The loader will
7e752c
    recognize .text section and handle relocation entries that
7e752c
    are emitted by LLVM.
7e752c
7e752c
    First step is processing of map related relocation entries
7e752c
    for .text section, and in a second step loader will copy .text
7e752c
    section into program section and adjust call instruction
7e752c
    offset accordingly.
7e752c
7e752c
    Example with test_xdp_noinline.o from kernel selftests:
7e752c
7e752c
     1) Every function as __attribute__ ((always_inline)), rest
7e752c
        left unchanged:
7e752c
7e752c
      # ip -force link set dev lo xdp obj test_xdp_noinline.o sec xdp-test
7e752c
      # ip a
7e752c
      1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 xdpgeneric/id:233 qdisc noqueue state UNKNOWN group default qlen 1000
7e752c
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
7e752c
        inet 127.0.0.1/8 scope host lo
7e752c
           valid_lft forever preferred_lft forever
7e752c
        inet6 ::1/128 scope host
7e752c
           valid_lft forever preferred_lft forever
7e752c
      [...]
7e752c
      # bpftool prog dump xlated id 233
7e752c
      [...]
7e752c
      1669: (2d) if r3 > r2 goto pc+4
7e752c
      1670: (79) r2 = *(u64 *)(r10 -136)
7e752c
      1671: (61) r2 = *(u32 *)(r2 +0)
7e752c
      1672: (63) *(u32 *)(r1 +0) = r2
7e752c
      1673: (b7) r0 = 1
7e752c
      1674: (95) exit        <-- 1674 insns total
7e752c
7e752c
     2) Every function as __attribute__ ((noinline)), rest
7e752c
        left unchanged:
7e752c
7e752c
      # ip -force link set dev lo xdp obj test_xdp_noinline.o sec xdp-test
7e752c
      # ip a
7e752c
      1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 xdpgeneric/id:236 qdisc noqueue state UNKNOWN group default qlen 1000
7e752c
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
7e752c
        inet 127.0.0.1/8 scope host lo
7e752c
           valid_lft forever preferred_lft forever
7e752c
        inet6 ::1/128 scope host
7e752c
           valid_lft forever preferred_lft forever
7e752c
      [...]
7e752c
      # bpftool prog dump xlated id 236
7e752c
      [...]
7e752c
      1000: (bf) r1 = r6
7e752c
      1001: (b7) r2 = 24
7e752c
      1002: (85) call pc+3   <-- pc-relative call insns
7e752c
      1003: (1f) r7 -= r0
7e752c
      1004: (bf) r0 = r7
7e752c
      1005: (95) exit
7e752c
      1006: (bf) r0 = r1
7e752c
      1007: (bf) r1 = r2
7e752c
      1008: (67) r1 <<= 32
7e752c
      1009: (77) r1 >>= 32
7e752c
      1010: (bf) r3 = r0
7e752c
      1011: (6f) r3 <<= r1
7e752c
      1012: (87) r2 = -r2
7e752c
      1013: (57) r2 &= 31
7e752c
      1014: (67) r0 <<= 32
7e752c
      1015: (77) r0 >>= 32
7e752c
      1016: (7f) r0 >>= r2
7e752c
      1017: (4f) r0 |= r3
7e752c
      1018: (95) exit        <-- 1018 insns total
7e752c
7e752c
    Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
7e752c
    Signed-off-by: David Ahern <dsahern@gmail.com>
7e752c
---
7e752c
 lib/bpf.c | 233 ++++++++++++++++++++++++++++++++++++------------------
7e752c
 1 file changed, 157 insertions(+), 76 deletions(-)
7e752c
7e752c
diff --git a/lib/bpf.c b/lib/bpf.c
7e752c
index ead8b5a7219f0..1b87490555050 100644
7e752c
--- a/lib/bpf.c
7e752c
+++ b/lib/bpf.c
7e752c
@@ -1109,7 +1109,8 @@ int bpf_prog_load(enum bpf_prog_type type, const struct bpf_insn *insns,
7e752c
 #ifdef HAVE_ELF
7e752c
 struct bpf_elf_prog {
7e752c
 	enum bpf_prog_type	type;
7e752c
-	const struct bpf_insn	*insns;
7e752c
+	struct bpf_insn		*insns;
7e752c
+	unsigned int		insns_num;
7e752c
 	size_t			size;
7e752c
 	const char		*license;
7e752c
 };
7e752c
@@ -1135,11 +1136,13 @@ struct bpf_elf_ctx {
7e752c
 	int			map_fds[ELF_MAX_MAPS];
7e752c
 	struct bpf_elf_map	maps[ELF_MAX_MAPS];
7e752c
 	struct bpf_map_ext	maps_ext[ELF_MAX_MAPS];
7e752c
+	struct bpf_elf_prog	prog_text;
7e752c
 	int			sym_num;
7e752c
 	int			map_num;
7e752c
 	int			map_len;
7e752c
 	bool			*sec_done;
7e752c
 	int			sec_maps;
7e752c
+	int			sec_text;
7e752c
 	char			license[ELF_MAX_LICENSE_LEN];
7e752c
 	enum bpf_prog_type	type;
7e752c
 	__u32			ifindex;
7e752c
@@ -1904,12 +1907,25 @@ static int bpf_fetch_strtab(struct bpf_elf_ctx *ctx, int section,
7e752c
 	return 0;
7e752c
 }
7e752c
 
7e752c
+static int bpf_fetch_text(struct bpf_elf_ctx *ctx, int section,
7e752c
+			  struct bpf_elf_sec_data *data)
7e752c
+{
7e752c
+	ctx->sec_text = section;
7e752c
+	ctx->sec_done[section] = true;
7e752c
+	return 0;
7e752c
+}
7e752c
+
7e752c
 static bool bpf_has_map_data(const struct bpf_elf_ctx *ctx)
7e752c
 {
7e752c
 	return ctx->sym_tab && ctx->str_tab && ctx->sec_maps;
7e752c
 }
7e752c
 
7e752c
-static int bpf_fetch_ancillary(struct bpf_elf_ctx *ctx)
7e752c
+static bool bpf_has_call_data(const struct bpf_elf_ctx *ctx)
7e752c
+{
7e752c
+	return ctx->sec_text;
7e752c
+}
7e752c
+
7e752c
+static int bpf_fetch_ancillary(struct bpf_elf_ctx *ctx, bool check_text_sec)
7e752c
 {
7e752c
 	struct bpf_elf_sec_data data;
7e752c
 	int i, ret = -1;
7e752c
@@ -1925,6 +1941,11 @@ static int bpf_fetch_ancillary(struct bpf_elf_ctx *ctx)
7e752c
 		else if (data.sec_hdr.sh_type == SHT_PROGBITS &&
7e752c
 			 !strcmp(data.sec_name, ELF_SECTION_LICENSE))
7e752c
 			ret = bpf_fetch_license(ctx, i, &data);
7e752c
+		else if (data.sec_hdr.sh_type == SHT_PROGBITS &&
7e752c
+			 (data.sec_hdr.sh_flags & SHF_EXECINSTR) &&
7e752c
+			 !strcmp(data.sec_name, ".text") &&
7e752c
+			 check_text_sec)
7e752c
+			ret = bpf_fetch_text(ctx, i, &data);
7e752c
 		else if (data.sec_hdr.sh_type == SHT_SYMTAB &&
7e752c
 			 !strcmp(data.sec_name, ".symtab"))
7e752c
 			ret = bpf_fetch_symtab(ctx, i, &data);
7e752c
@@ -1969,17 +1990,18 @@ static int bpf_fetch_prog(struct bpf_elf_ctx *ctx, const char *section,
7e752c
 		ret = bpf_fill_section_data(ctx, i, &data);
7e752c
 		if (ret < 0 ||
7e752c
 		    !(data.sec_hdr.sh_type == SHT_PROGBITS &&
7e752c
-		      data.sec_hdr.sh_flags & SHF_EXECINSTR &&
7e752c
+		      (data.sec_hdr.sh_flags & SHF_EXECINSTR) &&
7e752c
 		      !strcmp(data.sec_name, section)))
7e752c
 			continue;
7e752c
 
7e752c
 		*sseen = true;
7e752c
 
7e752c
 		memset(&prog, 0, sizeof(prog));
7e752c
-		prog.type    = ctx->type;
7e752c
-		prog.insns   = data.sec_data->d_buf;
7e752c
-		prog.size    = data.sec_data->d_size;
7e752c
-		prog.license = ctx->license;
7e752c
+		prog.type      = ctx->type;
7e752c
+		prog.license   = ctx->license;
7e752c
+		prog.size      = data.sec_data->d_size;
7e752c
+		prog.insns_num = prog.size / sizeof(struct bpf_insn);
7e752c
+		prog.insns     = data.sec_data->d_buf;
7e752c
 
7e752c
 		fd = bpf_prog_attach(section, &prog, ctx);
7e752c
 		if (fd < 0)
7e752c
@@ -1992,84 +2014,120 @@ static int bpf_fetch_prog(struct bpf_elf_ctx *ctx, const char *section,
7e752c
 	return fd;
7e752c
 }
7e752c
 
7e752c
-struct bpf_tail_call_props {
7e752c
-	unsigned int total;
7e752c
-	unsigned int jited;
7e752c
+struct bpf_relo_props {
7e752c
+	struct bpf_tail_call {
7e752c
+		unsigned int total;
7e752c
+		unsigned int jited;
7e752c
+	} tc;
7e752c
+	int main_num;
7e752c
 };
7e752c
 
7e752c
+static int bpf_apply_relo_map(struct bpf_elf_ctx *ctx, struct bpf_elf_prog *prog,
7e752c
+			      GElf_Rel *relo, GElf_Sym *sym,
7e752c
+			      struct bpf_relo_props *props)
7e752c
+{
7e752c
+	unsigned int insn_off = relo->r_offset / sizeof(struct bpf_insn);
7e752c
+	unsigned int map_idx = sym->st_value / ctx->map_len;
7e752c
+
7e752c
+	if (insn_off >= prog->insns_num)
7e752c
+		return -EINVAL;
7e752c
+	if (prog->insns[insn_off].code != (BPF_LD | BPF_IMM | BPF_DW)) {
7e752c
+		fprintf(stderr, "ELF contains relo data for non ld64 instruction at offset %u! Compiler bug?!\n",
7e752c
+			insn_off);
7e752c
+		return -EINVAL;
7e752c
+	}
7e752c
+
7e752c
+	if (map_idx >= ARRAY_SIZE(ctx->map_fds))
7e752c
+		return -EINVAL;
7e752c
+	if (!ctx->map_fds[map_idx])
7e752c
+		return -EINVAL;
7e752c
+	if (ctx->maps[map_idx].type == BPF_MAP_TYPE_PROG_ARRAY) {
7e752c
+		props->tc.total++;
7e752c
+		if (ctx->maps_ext[map_idx].owner.jited ||
7e752c
+		    (ctx->maps_ext[map_idx].owner.type == 0 &&
7e752c
+		     ctx->cfg.jit_enabled))
7e752c
+			props->tc.jited++;
7e752c
+	}
7e752c
+
7e752c
+	prog->insns[insn_off].src_reg = BPF_PSEUDO_MAP_FD;
7e752c
+	prog->insns[insn_off].imm = ctx->map_fds[map_idx];
7e752c
+	return 0;
7e752c
+}
7e752c
+
7e752c
+static int bpf_apply_relo_call(struct bpf_elf_ctx *ctx, struct bpf_elf_prog *prog,
7e752c
+			       GElf_Rel *relo, GElf_Sym *sym,
7e752c
+			       struct bpf_relo_props *props)
7e752c
+{
7e752c
+	unsigned int insn_off = relo->r_offset / sizeof(struct bpf_insn);
7e752c
+	struct bpf_elf_prog *prog_text = &ctx->prog_text;
7e752c
+
7e752c
+	if (insn_off >= prog->insns_num)
7e752c
+		return -EINVAL;
7e752c
+	if (prog->insns[insn_off].code != (BPF_JMP | BPF_CALL) &&
7e752c
+	    prog->insns[insn_off].src_reg != BPF_PSEUDO_CALL) {
7e752c
+		fprintf(stderr, "ELF contains relo data for non call instruction at offset %u! Compiler bug?!\n",
7e752c
+			insn_off);
7e752c
+		return -EINVAL;
7e752c
+	}
7e752c
+
7e752c
+	if (!props->main_num) {
7e752c
+		struct bpf_insn *insns = realloc(prog->insns,
7e752c
+						 prog->size + prog_text->size);
7e752c
+		if (!insns)
7e752c
+			return -ENOMEM;
7e752c
+
7e752c
+		memcpy(insns + prog->insns_num, prog_text->insns,
7e752c
+		       prog_text->size);
7e752c
+		props->main_num = prog->insns_num;
7e752c
+		prog->insns = insns;
7e752c
+		prog->insns_num += prog_text->insns_num;
7e752c
+		prog->size += prog_text->size;
7e752c
+	}
7e752c
+
7e752c
+	prog->insns[insn_off].imm += props->main_num - insn_off;
7e752c
+	return 0;
7e752c
+}
7e752c
+
7e752c
 static int bpf_apply_relo_data(struct bpf_elf_ctx *ctx,
7e752c
 			       struct bpf_elf_sec_data *data_relo,
7e752c
-			       struct bpf_elf_sec_data *data_insn,
7e752c
-			       struct bpf_tail_call_props *props)
7e752c
+			       struct bpf_elf_prog *prog,
7e752c
+			       struct bpf_relo_props *props)
7e752c
 {
7e752c
-	Elf_Data *idata = data_insn->sec_data;
7e752c
 	GElf_Shdr *rhdr = &data_relo->sec_hdr;
7e752c
 	int relo_ent, relo_num = rhdr->sh_size / rhdr->sh_entsize;
7e752c
-	struct bpf_insn *insns = idata->d_buf;
7e752c
-	unsigned int num_insns = idata->d_size / sizeof(*insns);
7e752c
 
7e752c
 	for (relo_ent = 0; relo_ent < relo_num; relo_ent++) {
7e752c
-		unsigned int ioff, rmap;
7e752c
 		GElf_Rel relo;
7e752c
 		GElf_Sym sym;
7e752c
+		int ret = -EIO;
7e752c
 
7e752c
 		if (gelf_getrel(data_relo->sec_data, relo_ent, &relo) != &relo)
7e752c
 			return -EIO;
7e752c
-
7e752c
-		ioff = relo.r_offset / sizeof(struct bpf_insn);
7e752c
-		if (ioff >= num_insns ||
7e752c
-		    insns[ioff].code != (BPF_LD | BPF_IMM | BPF_DW)) {
7e752c
-			fprintf(stderr, "ELF contains relo data for non ld64 instruction at offset %u! Compiler bug?!\n",
7e752c
-				ioff);
7e752c
-			fprintf(stderr, " - Current section: %s\n", data_relo->sec_name);
7e752c
-			if (ioff < num_insns &&
7e752c
-			    insns[ioff].code == (BPF_JMP | BPF_CALL))
7e752c
-				fprintf(stderr, " - Try to annotate functions with always_inline attribute!\n");
7e752c
-			return -EINVAL;
7e752c
-		}
7e752c
-
7e752c
 		if (gelf_getsym(ctx->sym_tab, GELF_R_SYM(relo.r_info), &sym) != &sym)
7e752c
 			return -EIO;
7e752c
-		if (sym.st_shndx != ctx->sec_maps) {
7e752c
-			fprintf(stderr, "ELF contains non-map related relo data in entry %u pointing to section %u! Compiler bug?!\n",
7e752c
-				relo_ent, sym.st_shndx);
7e752c
-			return -EIO;
7e752c
-		}
7e752c
 
7e752c
-		rmap = sym.st_value / ctx->map_len;
7e752c
-		if (rmap >= ARRAY_SIZE(ctx->map_fds))
7e752c
-			return -EINVAL;
7e752c
-		if (!ctx->map_fds[rmap])
7e752c
-			return -EINVAL;
7e752c
-		if (ctx->maps[rmap].type == BPF_MAP_TYPE_PROG_ARRAY) {
7e752c
-			props->total++;
7e752c
-			if (ctx->maps_ext[rmap].owner.jited ||
7e752c
-			    (ctx->maps_ext[rmap].owner.type == 0 &&
7e752c
-			     ctx->cfg.jit_enabled))
7e752c
-				props->jited++;
7e752c
-		}
7e752c
-
7e752c
-		if (ctx->verbose)
7e752c
-			fprintf(stderr, "Map \'%s\' (%d) injected into prog section \'%s\' at offset %u!\n",
7e752c
-				bpf_str_tab_name(ctx, &sym), ctx->map_fds[rmap],
7e752c
-				data_insn->sec_name, ioff);
7e752c
-
7e752c
-		insns[ioff].src_reg = BPF_PSEUDO_MAP_FD;
7e752c
-		insns[ioff].imm     = ctx->map_fds[rmap];
7e752c
+		if (sym.st_shndx == ctx->sec_maps)
7e752c
+			ret = bpf_apply_relo_map(ctx, prog, &relo, &sym, props);
7e752c
+		else if (sym.st_shndx == ctx->sec_text)
7e752c
+			ret = bpf_apply_relo_call(ctx, prog, &relo, &sym, props);
7e752c
+		else
7e752c
+			fprintf(stderr, "ELF contains non-{map,call} related relo data in entry %u pointing to section %u! Compiler bug?!\n",
7e752c
+				relo_ent, sym.st_shndx);
7e752c
+		if (ret < 0)
7e752c
+			return ret;
7e752c
 	}
7e752c
 
7e752c
 	return 0;
7e752c
 }
7e752c
 
7e752c
 static int bpf_fetch_prog_relo(struct bpf_elf_ctx *ctx, const char *section,
7e752c
-			       bool *lderr, bool *sseen)
7e752c
+			       bool *lderr, bool *sseen, struct bpf_elf_prog *prog)
7e752c
 {
7e752c
 	struct bpf_elf_sec_data data_relo, data_insn;
7e752c
-	struct bpf_elf_prog prog;
7e752c
 	int ret, idx, i, fd = -1;
7e752c
 
7e752c
 	for (i = 1; i < ctx->elf_hdr.e_shnum; i++) {
7e752c
-		struct bpf_tail_call_props props = {};
7e752c
+		struct bpf_relo_props props = {};
7e752c
 
7e752c
 		ret = bpf_fill_section_data(ctx, i, &data_relo);
7e752c
 		if (ret < 0 || data_relo.sec_hdr.sh_type != SHT_REL)
7e752c
@@ -2080,40 +2138,54 @@ static int bpf_fetch_prog_relo(struct bpf_elf_ctx *ctx, const char *section,
7e752c
 		ret = bpf_fill_section_data(ctx, idx, &data_insn);
7e752c
 		if (ret < 0 ||
7e752c
 		    !(data_insn.sec_hdr.sh_type == SHT_PROGBITS &&
7e752c
-		      data_insn.sec_hdr.sh_flags & SHF_EXECINSTR &&
7e752c
+		      (data_insn.sec_hdr.sh_flags & SHF_EXECINSTR) &&
7e752c
 		      !strcmp(data_insn.sec_name, section)))
7e752c
 			continue;
7e752c
+		if (sseen)
7e752c
+			*sseen = true;
7e752c
+
7e752c
+		memset(prog, 0, sizeof(*prog));
7e752c
+		prog->type = ctx->type;
7e752c
+		prog->license = ctx->license;
7e752c
+		prog->size = data_insn.sec_data->d_size;
7e752c
+		prog->insns_num = prog->size / sizeof(struct bpf_insn);
7e752c
+		prog->insns = malloc(prog->size);
7e752c
+		if (!prog->insns) {
7e752c
+			*lderr = true;
7e752c
+			return -ENOMEM;
7e752c
+		}
7e752c
 
7e752c
-		*sseen = true;
7e752c
+		memcpy(prog->insns, data_insn.sec_data->d_buf, prog->size);
7e752c
 
7e752c
-		ret = bpf_apply_relo_data(ctx, &data_relo, &data_insn, &props;;
7e752c
+		ret = bpf_apply_relo_data(ctx, &data_relo, prog, &props;;
7e752c
 		if (ret < 0) {
7e752c
 			*lderr = true;
7e752c
+			if (ctx->sec_text != idx)
7e752c
+				free(prog->insns);
7e752c
 			return ret;
7e752c
 		}
7e752c
+		if (ctx->sec_text == idx) {
7e752c
+			fd = 0;
7e752c
+			goto out;
7e752c
+		}
7e752c
 
7e752c
-		memset(&prog, 0, sizeof(prog));
7e752c
-		prog.type    = ctx->type;
7e752c
-		prog.insns   = data_insn.sec_data->d_buf;
7e752c
-		prog.size    = data_insn.sec_data->d_size;
7e752c
-		prog.license = ctx->license;
7e752c
-
7e752c
-		fd = bpf_prog_attach(section, &prog, ctx);
7e752c
+		fd = bpf_prog_attach(section, prog, ctx);
7e752c
+		free(prog->insns);
7e752c
 		if (fd < 0) {
7e752c
 			*lderr = true;
7e752c
-			if (props.total) {
7e752c
+			if (props.tc.total) {
7e752c
 				if (ctx->cfg.jit_enabled &&
7e752c
-				    props.total != props.jited)
7e752c
+				    props.tc.total != props.tc.jited)
7e752c
 					fprintf(stderr, "JIT enabled, but only %u/%u tail call maps in the program have JITed owner!\n",
7e752c
-						props.jited, props.total);
7e752c
+						props.tc.jited, props.tc.total);
7e752c
 				if (!ctx->cfg.jit_enabled &&
7e752c
-				    props.jited)
7e752c
+				    props.tc.jited)
7e752c
 					fprintf(stderr, "JIT disabled, but %u/%u tail call maps in the program have JITed owner!\n",
7e752c
-						props.jited, props.total);
7e752c
+						props.tc.jited, props.tc.total);
7e752c
 			}
7e752c
 			return fd;
7e752c
 		}
7e752c
-
7e752c
+out:
7e752c
 		ctx->sec_done[i]   = true;
7e752c
 		ctx->sec_done[idx] = true;
7e752c
 		break;
7e752c
@@ -2125,10 +2197,18 @@ static int bpf_fetch_prog_relo(struct bpf_elf_ctx *ctx, const char *section,
7e752c
 static int bpf_fetch_prog_sec(struct bpf_elf_ctx *ctx, const char *section)
7e752c
 {
7e752c
 	bool lderr = false, sseen = false;
7e752c
+	struct bpf_elf_prog prog;
7e752c
 	int ret = -1;
7e752c
 
7e752c
-	if (bpf_has_map_data(ctx))
7e752c
-		ret = bpf_fetch_prog_relo(ctx, section, &lderr, &sseen);
7e752c
+	if (bpf_has_call_data(ctx)) {
7e752c
+		ret = bpf_fetch_prog_relo(ctx, ".text", &lderr, NULL,
7e752c
+					  &ctx->prog_text);
7e752c
+		if (ret < 0)
7e752c
+			return ret;
7e752c
+	}
7e752c
+
7e752c
+	if (bpf_has_map_data(ctx) || bpf_has_call_data(ctx))
7e752c
+		ret = bpf_fetch_prog_relo(ctx, section, &lderr, &sseen, &prog;;
7e752c
 	if (ret < 0 && !lderr)
7e752c
 		ret = bpf_fetch_prog(ctx, section, &sseen);
7e752c
 	if (ret < 0 && !sseen)
7e752c
@@ -2525,6 +2605,7 @@ static void bpf_elf_ctx_destroy(struct bpf_elf_ctx *ctx, bool failure)
7e752c
 
7e752c
 	bpf_hash_destroy(ctx);
7e752c
 
7e752c
+	free(ctx->prog_text.insns);
7e752c
 	free(ctx->sec_done);
7e752c
 	free(ctx->log);
7e752c
 
7e752c
@@ -2546,7 +2627,7 @@ static int bpf_obj_open(const char *pathname, enum bpf_prog_type type,
7e752c
 		return ret;
7e752c
 	}
7e752c
 
7e752c
-	ret = bpf_fetch_ancillary(ctx);
7e752c
+	ret = bpf_fetch_ancillary(ctx, strcmp(section, ".text"));
7e752c
 	if (ret < 0) {
7e752c
 		fprintf(stderr, "Error fetching ELF ancillary data!\n");
7e752c
 		goto out;
7e752c
-- 
7e752c
2.20.1
7e752c