From: Alexei Starovoitov <alexei.starovoitov@gmail.com>
To: davem@davemloft.net
Cc: daniel@iogearbox.net, andrii@kernel.org, netdev@vger.kernel.org,
bpf@vger.kernel.org, kernel-team@fb.com
Subject: [PATCH bpf-next 12/15] libbpf: Change the order of data and text relocations.
Date: Fri, 16 Apr 2021 20:32:21 -0700 [thread overview]
Message-ID: <20210417033224.8063-13-alexei.starovoitov@gmail.com> (raw)
In-Reply-To: <20210417033224.8063-1-alexei.starovoitov@gmail.com>
From: Alexei Starovoitov <ast@kernel.org>
In order to be able to generate loader program in the later
patches change the order of data and text relocations.
Also improve the test to include data relos.
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
---
tools/lib/bpf/libbpf.c | 82 ++++++++++++++-----
.../selftests/bpf/progs/test_subprogs.c | 13 +++
2 files changed, 76 insertions(+), 19 deletions(-)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 17cfc5b66111..083e441d9c5e 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -6379,11 +6379,15 @@ bpf_object__relocate_data(struct bpf_object *obj, struct bpf_program *prog)
insn[0].imm = ext->ksym.kernel_btf_id;
break;
case RELO_SUBPROG_ADDR:
- insn[0].src_reg = BPF_PSEUDO_FUNC;
- /* will be handled as a follow up pass */
+ if (insn[0].src_reg != BPF_PSEUDO_FUNC) {
+ pr_warn("prog '%s': relo #%d: bad insn\n",
+ prog->name, i);
+ return -EINVAL;
+ }
+ /* handled already */
break;
case RELO_CALL:
- /* will be handled as a follow up pass */
+ /* handled already */
break;
default:
pr_warn("prog '%s': relo #%d: bad relo type %d\n",
@@ -6552,6 +6556,31 @@ static struct reloc_desc *find_prog_insn_relo(const struct bpf_program *prog, si
sizeof(*prog->reloc_desc), cmp_relo_by_insn_idx);
}
+static int append_subprog_relos(struct bpf_program *main_prog, struct bpf_program *subprog)
+{
+ int new_cnt = main_prog->nr_reloc + subprog->nr_reloc;
+ struct reloc_desc *relos;
+ size_t off = subprog->sub_insn_off;
+ int i;
+
+ if (main_prog == subprog)
+ return 0;
+ relos = libbpf_reallocarray(main_prog->reloc_desc, new_cnt, sizeof(*relos));
+ if (!relos)
+ return -ENOMEM;
+ memcpy(relos + main_prog->nr_reloc, subprog->reloc_desc,
+ sizeof(*relos) * subprog->nr_reloc);
+
+ for (i = main_prog->nr_reloc; i < new_cnt; i++)
+ relos[i].insn_idx += off;
+ /* After insn_idx adjustment the 'relos' array is still sorted
+ * by insn_idx and doesn't break bsearch.
+ */
+ main_prog->reloc_desc = relos;
+ main_prog->nr_reloc = new_cnt;
+ return 0;
+}
+
static int
bpf_object__reloc_code(struct bpf_object *obj, struct bpf_program *main_prog,
struct bpf_program *prog)
@@ -6560,12 +6589,21 @@ bpf_object__reloc_code(struct bpf_object *obj, struct bpf_program *main_prog,
struct bpf_program *subprog;
struct bpf_insn *insns, *insn;
struct reloc_desc *relo;
- int err;
+ int err, i;
err = reloc_prog_func_and_line_info(obj, main_prog, prog);
if (err)
return err;
+ for (i = 0; i < prog->nr_reloc; i++) {
+ relo = &prog->reloc_desc[i];
+ insn = &main_prog->insns[prog->sub_insn_off + relo->insn_idx];
+
+ if (relo->type == RELO_SUBPROG_ADDR)
+ /* mark the insn, so it becomes insn_is_pseudo_func() */
+ insn[0].src_reg = BPF_PSEUDO_FUNC;
+ }
+
for (insn_idx = 0; insn_idx < prog->sec_insn_cnt; insn_idx++) {
insn = &main_prog->insns[prog->sub_insn_off + insn_idx];
if (!insn_is_subprog_call(insn) && !insn_is_pseudo_func(insn))
@@ -6573,6 +6611,8 @@ bpf_object__reloc_code(struct bpf_object *obj, struct bpf_program *main_prog,
relo = find_prog_insn_relo(prog, insn_idx);
if (relo && relo->type != RELO_CALL && relo->type != RELO_SUBPROG_ADDR) {
+ if (relo->type == RELO_EXTERN_FUNC)
+ continue;
pr_warn("prog '%s': unexpected relo for insn #%zu, type %d\n",
prog->name, insn_idx, relo->type);
return -LIBBPF_ERRNO__RELOC;
@@ -6646,6 +6686,10 @@ bpf_object__reloc_code(struct bpf_object *obj, struct bpf_program *main_prog,
pr_debug("prog '%s': added %zu insns from sub-prog '%s'\n",
main_prog->name, subprog->insns_cnt, subprog->name);
+ /* The subprog insns are now appended. Append its relos too. */
+ err = append_subprog_relos(main_prog, subprog);
+ if (err)
+ return err;
err = bpf_object__reloc_code(obj, main_prog, subprog);
if (err)
return err;
@@ -6790,23 +6834,11 @@ bpf_object__relocate(struct bpf_object *obj, const char *targ_btf_path)
return err;
}
}
- /* relocate data references first for all programs and sub-programs,
- * as they don't change relative to code locations, so subsequent
- * subprogram processing won't need to re-calculate any of them
- */
- for (i = 0; i < obj->nr_programs; i++) {
- prog = &obj->programs[i];
- err = bpf_object__relocate_data(obj, prog);
- if (err) {
- pr_warn("prog '%s': failed to relocate data references: %d\n",
- prog->name, err);
- return err;
- }
- }
- /* now relocate subprogram calls and append used subprograms to main
+ /* relocate subprogram calls and append used subprograms to main
* programs; each copy of subprogram code needs to be relocated
* differently for each main program, because its code location might
- * have changed
+ * have changed.
+ * Append subprog relos to main programs.
*/
for (i = 0; i < obj->nr_programs; i++) {
prog = &obj->programs[i];
@@ -6823,6 +6855,18 @@ bpf_object__relocate(struct bpf_object *obj, const char *targ_btf_path)
return err;
}
}
+ /* Process data relos for main programs */
+ for (i = 0; i < obj->nr_programs; i++) {
+ prog = &obj->programs[i];
+ if (prog_is_subprog(obj, prog))
+ continue;
+ err = bpf_object__relocate_data(obj, prog);
+ if (err) {
+ pr_warn("prog '%s': failed to relocate data references: %d\n",
+ prog->name, err);
+ return err;
+ }
+ }
/* free up relocation descriptors */
for (i = 0; i < obj->nr_programs; i++) {
prog = &obj->programs[i];
diff --git a/tools/testing/selftests/bpf/progs/test_subprogs.c b/tools/testing/selftests/bpf/progs/test_subprogs.c
index d3c5673c0218..b7c37ca09544 100644
--- a/tools/testing/selftests/bpf/progs/test_subprogs.c
+++ b/tools/testing/selftests/bpf/progs/test_subprogs.c
@@ -4,8 +4,18 @@
const char LICENSE[] SEC("license") = "GPL";
+struct {
+ __uint(type, BPF_MAP_TYPE_ARRAY);
+ __uint(max_entries, 1);
+ __type(key, __u32);
+ __type(value, __u64);
+} array SEC(".maps");
+
__noinline int sub1(int x)
{
+ int key = 0;
+
+ bpf_map_lookup_elem(&array, &key);
return x + 1;
}
@@ -23,6 +33,9 @@ static __noinline int sub3(int z)
static __noinline int sub4(int w)
{
+ int key = 0;
+
+ bpf_map_lookup_elem(&array, &key);
return w + sub3(5) + sub1(6);
}
--
2.30.2
next prev parent reply other threads:[~2021-04-17 3:33 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-04-17 3:32 [PATCH bpf-next 00/15] bpf: syscall program, FD array, loader program, light skeleton Alexei Starovoitov
2021-04-17 3:32 ` [PATCH bpf-next 01/15] bpf: Introduce bpf_sys_bpf() helper and program type Alexei Starovoitov
2021-04-17 3:32 ` [PATCH bpf-next 02/15] bpf: Introduce bpfptr_t user/kernel pointer Alexei Starovoitov
2021-04-17 3:32 ` [PATCH bpf-next 03/15] bpf: Prepare bpf syscall to be used from kernel and user space Alexei Starovoitov
2021-04-17 3:32 ` [PATCH bpf-next 04/15] libbpf: Support for syscall program type Alexei Starovoitov
2021-04-17 3:32 ` [PATCH bpf-next 05/15] selftests/bpf: Test " Alexei Starovoitov
2021-04-17 3:32 ` [PATCH bpf-next 06/15] bpf: Make btf_load command to be bpfptr_t compatible Alexei Starovoitov
2021-04-17 3:32 ` [PATCH bpf-next 07/15] selftests/bpf: Test for btf_load command Alexei Starovoitov
2021-04-17 3:32 ` [PATCH bpf-next 08/15] bpf: Introduce fd_idx Alexei Starovoitov
2021-04-17 3:32 ` [PATCH bpf-next 09/15] libbpf: Support for fd_idx Alexei Starovoitov
2021-04-17 3:32 ` [PATCH bpf-next 10/15] bpf: Add bpf_btf_find_by_name_kind() helper Alexei Starovoitov
2021-04-17 3:32 ` [PATCH bpf-next 11/15] bpf: Add bpf_sys_close() helper Alexei Starovoitov
2021-04-17 3:42 ` Al Viro
2021-04-17 3:46 ` Alexei Starovoitov
2021-04-17 4:04 ` Al Viro
2021-04-17 5:01 ` Alexei Starovoitov
2021-04-17 14:36 ` Alexei Starovoitov
2021-04-17 16:48 ` Al Viro
2021-04-17 17:09 ` Alexei Starovoitov
2021-04-17 3:32 ` Alexei Starovoitov [this message]
2021-04-17 3:32 ` [PATCH bpf-next 13/15] libbpf: Generate loader program out of BPF ELF file Alexei Starovoitov
2021-04-21 1:34 ` Yonghong Song
2021-04-21 4:46 ` Alexei Starovoitov
2021-04-21 5:30 ` Yonghong Song
2021-04-21 6:06 ` Alexei Starovoitov
2021-04-21 14:05 ` Yonghong Song
2021-04-21 17:46 ` Andrii Nakryiko
2021-04-21 17:50 ` Alexei Starovoitov
2021-04-17 3:32 ` [PATCH bpf-next 14/15] bpftool: Use syscall/loader program in "prog load" and "gen skeleton" command Alexei Starovoitov
2021-04-17 3:32 ` [PATCH bpf-next 15/15] selftests/bpf: Convert few tests to light skeleton Alexei Starovoitov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210417033224.8063-13-alexei.starovoitov@gmail.com \
--to=alexei.starovoitov@gmail.com \
--cc=andrii@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=kernel-team@fb.com \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox