All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrii Nakryiko <andrii.nakryiko@gmail.com>
To: Yonghong Song <yhs@fb.com>
Cc: Andrii Nakryiko <andrii@kernel.org>, bpf <bpf@vger.kernel.org>,
	Networking <netdev@vger.kernel.org>,
	Alexei Starovoitov <ast@fb.com>,
	Daniel Borkmann <daniel@iogearbox.net>,
	Kernel Team <kernel-team@fb.com>
Subject: Re: [PATCH v2 bpf-next 15/17] selftests/bpf: add function linking selftest
Date: Fri, 23 Apr 2021 10:55:09 -0700	[thread overview]
Message-ID: <CAEf4BzbP+trfjW-_AwcLsmS=79jqXWoRbQJnSH2xkE=MOxN2Gg@mail.gmail.com> (raw)
In-Reply-To: <b49042fc-0af8-11f4-4316-39b0d6f0e6e4@fb.com>

On Fri, Apr 23, 2021 at 10:35 AM Yonghong Song <yhs@fb.com> wrote:
>
>
>
> On 4/23/21 10:18 AM, Andrii Nakryiko wrote:
> > On Thu, Apr 22, 2021 at 5:50 PM Yonghong Song <yhs@fb.com> wrote:
> >>
> >>
> >>
> >> On 4/16/21 1:24 PM, Andrii Nakryiko wrote:
> >>> Add selftest validating various aspects of statically linking functions:
> >>>     - no conflicts and correct resolution for name-conflicting static funcs;
> >>>     - correct resolution of extern functions;
> >>>     - correct handling of weak functions, both resolution itself and libbpf's
> >>>       handling of unused weak function that "lost" (it leaves gaps in code with
> >>>       no ELF symbols);
> >>>     - correct handling of hidden visibility to turn global function into
> >>>       "static" for the purpose of BPF verification.
> >>>
> >>> Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
> >>
> >> Ack with a small nit below.
> >>
> >> Acked-by: Yonghong Song <yhs@fb.com>
> >>
> >>> ---
> >>>    tools/testing/selftests/bpf/Makefile          |  3 +-
> >>>    .../selftests/bpf/prog_tests/linked_funcs.c   | 42 +++++++++++
> >>>    .../selftests/bpf/progs/linked_funcs1.c       | 73 +++++++++++++++++++
> >>>    .../selftests/bpf/progs/linked_funcs2.c       | 73 +++++++++++++++++++
> >>>    4 files changed, 190 insertions(+), 1 deletion(-)
> >>>    create mode 100644 tools/testing/selftests/bpf/prog_tests/linked_funcs.c
> >>>    create mode 100644 tools/testing/selftests/bpf/progs/linked_funcs1.c
> >>>    create mode 100644 tools/testing/selftests/bpf/progs/linked_funcs2.c
> >>>
> >>> diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
> >>> index 666b462c1218..427ccfec1a6a 100644
> >>> --- a/tools/testing/selftests/bpf/Makefile
> >>> +++ b/tools/testing/selftests/bpf/Makefile
> >>> @@ -308,9 +308,10 @@ endef
> >>>
> >>>    SKEL_BLACKLIST := btf__% test_pinning_invalid.c test_sk_assign.c
> >>>
> >>> -LINKED_SKELS := test_static_linked.skel.h
> >>> +LINKED_SKELS := test_static_linked.skel.h linked_funcs.skel.h
> >>>
> >>>    test_static_linked.skel.h-deps := test_static_linked1.o test_static_linked2.o
> >>> +linked_funcs.skel.h-deps := linked_funcs1.o linked_funcs2.o
> >>>
> >>>    LINKED_BPF_SRCS := $(patsubst %.o,%.c,$(foreach skel,$(LINKED_SKELS),$($(skel)-deps)))
> >>>
> >>> diff --git a/tools/testing/selftests/bpf/prog_tests/linked_funcs.c b/tools/testing/selftests/bpf/prog_tests/linked_funcs.c
> >>> new file mode 100644
> >>> index 000000000000..03bf8ef131ce
> >>> --- /dev/null
> >>> +++ b/tools/testing/selftests/bpf/prog_tests/linked_funcs.c
> >>> @@ -0,0 +1,42 @@
> >>> +// SPDX-License-Identifier: GPL-2.0
> >>> +/* Copyright (c) 2021 Facebook */
> >>> +
> >>> +#include <test_progs.h>
> >>> +#include <sys/syscall.h>
> >>> +#include "linked_funcs.skel.h"
> >>> +
> >>> +void test_linked_funcs(void)
> >>> +{
> >>> +     int err;
> >>> +     struct linked_funcs *skel;
> >>> +
> >>> +     skel = linked_funcs__open();
> >>> +     if (!ASSERT_OK_PTR(skel, "skel_open"))
> >>> +             return;
> >>> +
> >>> +     skel->rodata->my_tid = syscall(SYS_gettid);
> >>> +     skel->rodata->syscall_id = SYS_getpgid;
> >>> +
> >>> +     err = linked_funcs__load(skel);
> >>> +     if (!ASSERT_OK(err, "skel_load"))
> >>> +             goto cleanup;
> >>> +
> >>> +     err = linked_funcs__attach(skel);
> >>> +     if (!ASSERT_OK(err, "skel_attach"))
> >>> +             goto cleanup;
> >>> +
> >>> +     /* trigger */
> >>> +     syscall(SYS_getpgid);
> >>> +
> >>> +     ASSERT_EQ(skel->bss->output_val1, 2000 + 2000, "output_val1");
> >>> +     ASSERT_EQ(skel->bss->output_ctx1, SYS_getpgid, "output_ctx1");
> >>> +     ASSERT_EQ(skel->bss->output_weak1, 42, "output_weak1");
> >>> +
> >>> +     ASSERT_EQ(skel->bss->output_val2, 2 * 1000 + 2 * (2 * 1000), "output_val2");
> >>> +     ASSERT_EQ(skel->bss->output_ctx2, SYS_getpgid, "output_ctx2");
> >>> +     /* output_weak2 should never be updated */
> >>> +     ASSERT_EQ(skel->bss->output_weak2, 0, "output_weak2");
> >>> +
> >>> +cleanup:
> >>> +     linked_funcs__destroy(skel);
> >>> +}
> >>> diff --git a/tools/testing/selftests/bpf/progs/linked_funcs1.c b/tools/testing/selftests/bpf/progs/linked_funcs1.c
> >>> new file mode 100644
> >>> index 000000000000..cc621d4e4d82
> >>> --- /dev/null
> >>> +++ b/tools/testing/selftests/bpf/progs/linked_funcs1.c
> >>> @@ -0,0 +1,73 @@
> >>> +// SPDX-License-Identifier: GPL-2.0
> >>> +/* Copyright (c) 2021 Facebook */
> >>> +
> >>> +#include "vmlinux.h"
> >>> +#include <bpf/bpf_helpers.h>
> >>> +#include <bpf/bpf_tracing.h>
> >>> +
> >>> +/* weak and shared between two files */
> >>> +const volatile int my_tid __weak = 0;
> >>> +const volatile long syscall_id __weak = 0;
> >>
> >> Since the new compiler (llvm13) is recommended for this patch set.
> >> We can simplify the above two definition with
> >>     int my_tid __weak;
> >>     long syscall_id __weak;
> >> The same for the other file.
> >
> > This is not about old vs new compilers. I wanted to use .rodata
> > variables, but I'll switch to .bss, no problem.
>
> I see. You can actually hone one "const volatile ing my_tid __weak = 0"
> and another "long syscall_id __weak". This way, you will be able to
> test both .rodata and .bss section.

I wonder if you meant to have one my_tid __weak in .bss and another
my_tid __weak in .rodata. Or just my_tid in .bss and syscall_id in
.rodata?

If the former (mixing ELF sections across definitions of the same
symbol), then it's disallowed right now. libbpf will error out on
mismatched sections. I tested this with normal compilation, it does
work and the final section is the section of the winner.

But I think that's quite confusing, actually, so I'm going to leave it
disallowed for now. E.g., if one file expects a read-write variable
and another expects that same variable to be read-only, and the winner
ends up being read-only one, then the file expecting read-write will
essentially have incorrect code (and will be rejected by BPF verifier,
if anything attempts to write). So I think it's better to reject it at
the linking time.

But I'll do one (my_tid) as .bss, and another (syscall_id) as .rodata.

>
> >
> >>
> >> But I am also okay with the current form
> >> to *satisfy* llvm10 some people may still use.
> >>
> >>> +
> >>> +int output_val1 = 0;
> >>> +int output_ctx1 = 0;
> >>> +int output_weak1 = 0;
> >>> +
> >>> +/* same "subprog" name in all files, but it's ok because they all are static */
> >>> +static __noinline int subprog(int x)
> >>> +{
> >>> +     /* but different formula */
> >>> +     return x * 1;
> >>> +}
> >>> +
> >>> +/* Global functions can't be void */
> >>> +int set_output_val1(int x)
> >>> +{
> >>> +     output_val1 = x + subprog(x);
> >>> +     return x;
> >>> +}
> >>> +
> >>> +/* This function can't be verified as global, as it assumes raw_tp/sys_enter
> >>> + * context and accesses syscall id (second argument). So we mark it as
> >>> + * __hidden, so that libbpf will mark it as static in the final object file,
> >>> + * right before verifying it in the kernel.
> >>> + *
> >>> + * But we don't mark it as __hidden here, rather at extern site. __hidden is
> >>> + * "contaminating" visibility, so it will get propagated from either extern or
> >>> + * actual definition (including from the losing __weak definition).
> >>> + */
> >>> +void set_output_ctx1(__u64 *ctx)
> >>> +{
> >>> +     output_ctx1 = ctx[1]; /* long id, same as in BPF_PROG below */
> >>> +}
> >>> +
> >>> +/* this weak instance should win because it's the first one */
> >>> +__weak int set_output_weak(int x)
> >>> +{
> >>> +     output_weak1 = x;
> >>> +     return x;
> >>> +}
> >>> +
> >>> +extern int set_output_val2(int x);
> >>> +
> >>> +/* here we'll force set_output_ctx2() to be __hidden in the final obj file */
> >>> +__hidden extern void set_output_ctx2(__u64 *ctx);
> >>> +
> >> [...]

  reply	other threads:[~2021-04-23 17:55 UTC|newest]

Thread overview: 67+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-16 20:23 [PATCH v2 bpf-next 00/17] BPF static linker: support externs Andrii Nakryiko
2021-04-16 20:23 ` [PATCH v2 bpf-next 01/17] bpftool: support dumping BTF VAR's "extern" linkage Andrii Nakryiko
2021-04-22  3:02   ` Yonghong Song
2021-04-16 20:23 ` [PATCH v2 bpf-next 02/17] bpftool: dump more info about DATASEC members Andrii Nakryiko
2021-04-22  3:09   ` Yonghong Song
2021-04-16 20:23 ` [PATCH v2 bpf-next 03/17] libbpf: suppress compiler warning when using SEC() macro with externs Andrii Nakryiko
2021-04-22  3:47   ` Yonghong Song
2021-04-22  3:59     ` Andrii Nakryiko
2021-04-16 20:23 ` [PATCH v2 bpf-next 04/17] libbpf: mark BPF subprogs with hidden visibility as static for BPF verifier Andrii Nakryiko
2021-04-22  5:43   ` Yonghong Song
2021-04-22 18:09     ` Andrii Nakryiko
2021-04-22 23:00       ` Yonghong Song
2021-04-22 23:28         ` Andrii Nakryiko
2021-04-16 20:23 ` [PATCH v2 bpf-next 05/17] libbpf: allow gaps in BPF program sections to support overriden weak functions Andrii Nakryiko
2021-04-22  6:25   ` Yonghong Song
2021-04-22 18:10     ` Andrii Nakryiko
2021-04-16 20:23 ` [PATCH v2 bpf-next 06/17] libbpf: refactor BTF map definition parsing Andrii Nakryiko
2021-04-22 15:33   ` Yonghong Song
2021-04-22 18:40     ` Andrii Nakryiko
2021-04-16 20:23 ` [PATCH v2 bpf-next 07/17] libbpf: factor out symtab and relos sanity checks Andrii Nakryiko
2021-04-22 16:06   ` Yonghong Song
2021-04-22 18:16     ` Andrii Nakryiko
2021-04-16 20:23 ` [PATCH v2 bpf-next 08/17] libbpf: make few internal helpers available outside of libbpf.c Andrii Nakryiko
2021-04-22 16:19   ` Yonghong Song
2021-04-22 18:18     ` Andrii Nakryiko
2021-04-16 20:23 ` [PATCH v2 bpf-next 09/17] libbpf: extend sanity checking ELF symbols with externs validation Andrii Nakryiko
2021-04-22 16:35   ` Yonghong Song
2021-04-22 18:20     ` Andrii Nakryiko
2021-04-22 23:13       ` Yonghong Song
2021-04-16 20:23 ` [PATCH v2 bpf-next 10/17] libbpf: tighten BTF type ID rewriting with error checking Andrii Nakryiko
2021-04-22 16:50   ` Yonghong Song
2021-04-22 18:24     ` Andrii Nakryiko
2021-04-23  2:54       ` Alexei Starovoitov
2021-04-23  4:25         ` Andrii Nakryiko
2021-04-23  5:11           ` Alexei Starovoitov
2021-04-23 16:09             ` Andrii Nakryiko
2021-04-23 16:18               ` Alexei Starovoitov
2021-04-23 16:30                 ` Andrii Nakryiko
2021-04-23 16:34                   ` Alexei Starovoitov
2021-04-23 17:02                     ` Andrii Nakryiko
2021-04-16 20:23 ` [PATCH v2 bpf-next 11/17] libbpf: add linker extern resolution support for functions and global variables Andrii Nakryiko
2021-04-22 21:27   ` Yonghong Song
2021-04-22 22:12     ` Andrii Nakryiko
2021-04-22 23:57       ` Yonghong Song
2021-04-23  2:36         ` Yonghong Song
2021-04-23  4:28           ` Andrii Nakryiko
2021-04-23  4:27         ` Andrii Nakryiko
2021-04-16 20:23 ` [PATCH v2 bpf-next 12/17] libbpf: support extern resolution for BTF-defined maps in .maps section Andrii Nakryiko
2021-04-22 22:56   ` Yonghong Song
2021-04-22 23:32     ` Andrii Nakryiko
2021-04-16 20:24 ` [PATCH v2 bpf-next 13/17] selftests/bpf: use -O0 instead of -Og in selftests builds Andrii Nakryiko
2021-04-23  0:05   ` Yonghong Song
2021-04-16 20:24 ` [PATCH v2 bpf-next 14/17] selftests/bpf: omit skeleton generation for multi-linked BPF object files Andrii Nakryiko
2021-04-23  0:13   ` Yonghong Song
2021-04-16 20:24 ` [PATCH v2 bpf-next 15/17] selftests/bpf: add function linking selftest Andrii Nakryiko
2021-04-23  0:50   ` Yonghong Song
2021-04-23  2:34     ` Alexei Starovoitov
2021-04-23  4:29       ` Andrii Nakryiko
2021-04-23 17:18     ` Andrii Nakryiko
2021-04-23 17:35       ` Yonghong Song
2021-04-23 17:55         ` Andrii Nakryiko [this message]
2021-04-23 17:58           ` Yonghong Song
2021-04-23 17:59             ` Andrii Nakryiko
2021-04-16 20:24 ` [PATCH v2 bpf-next 16/17] selftests/bpf: add global variables " Andrii Nakryiko
2021-04-23  1:01   ` Yonghong Song
2021-04-16 20:24 ` [PATCH v2 bpf-next 17/17] sleftests/bpf: add map " Andrii Nakryiko
2021-04-23  1:20   ` Yonghong Song

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='CAEf4BzbP+trfjW-_AwcLsmS=79jqXWoRbQJnSH2xkE=MOxN2Gg@mail.gmail.com' \
    --to=andrii.nakryiko@gmail.com \
    --cc=andrii@kernel.org \
    --cc=ast@fb.com \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=kernel-team@fb.com \
    --cc=netdev@vger.kernel.org \
    --cc=yhs@fb.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.