From: sdf@google.com
To: Andrii Nakryiko <andrii@kernel.org>
Cc: bpf@vger.kernel.org, ast@kernel.org, daniel@iogearbox.net,
kernel-team@fb.com
Subject: Re: [PATCH bpf-next 1/3] libbpf: clean up and refactor BTF fixup step
Date: Tue, 18 Oct 2022 11:47:44 -0700 [thread overview]
Message-ID: <Y0700LilBVP2D39B@google.com> (raw)
In-Reply-To: <20221018035646.1294873-2-andrii@kernel.org>
On 10/17, Andrii Nakryiko wrote:
> Refactor libbpf's BTF fixup step during BPF object open phase. The only
> functional change is that we now ignore BTF_VAR_GLOBAL_EXTERN variables
> during fix up, not just BTF_VAR_STATIC ones, which shouldn't cause any
> change in behavior as there shouldn't be any extern variable in data
> sections for valid BPF object anyways.
> Otherwise it's just collapsing two functions that have no reason to be
> separate, and switching find_elf_var_offset() helper to return entire
> symbol pointer, not just its offset. This will be used by next patch to
> get ELF symbol visibility.
> While refactoring, also "normalize" debug messages inside
> btf_fixup_datasec() to follow general libbpf style and print out data
> section name consistently, where it's available.
> Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Stanislav Fomichev <sdf@google.com>
Left a couple of questions below.
> ---
> tools/lib/bpf/libbpf.c | 95 ++++++++++++++++++------------------------
> 1 file changed, 41 insertions(+), 54 deletions(-)
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index 8c3f236c86e4..a25eb8fe7bf2 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -1461,15 +1461,12 @@ static int find_elf_sec_sz(const struct
> bpf_object *obj, const char *name, __u32
> return -ENOENT;
> }
> -static int find_elf_var_offset(const struct bpf_object *obj, const char
> *name, __u32 *off)
> +static Elf64_Sym *find_elf_var_sym(const struct bpf_object *obj, const
> char *name)
> {
> Elf_Data *symbols = obj->efile.symbols;
> const char *sname;
> size_t si;
> - if (!name || !off)
> - return -EINVAL;
> -
> for (si = 0; si < symbols->d_size / sizeof(Elf64_Sym); si++) {
> Elf64_Sym *sym = elf_sym_by_idx(obj, si);
> @@ -1483,15 +1480,13 @@ static int find_elf_var_offset(const struct
> bpf_object *obj, const char *name, _
> sname = elf_sym_str(obj, sym->st_name);
> if (!sname) {
> pr_warn("failed to get sym name string for var %s\n", name);
> - return -EIO;
> - }
> - if (strcmp(name, sname) == 0) {
> - *off = sym->st_value;
> - return 0;
> + return ERR_PTR(-EIO);
> }
> + if (strcmp(name, sname) == 0)
> + return sym;
> }
> - return -ENOENT;
> + return ERR_PTR(-ENOENT);
> }
> static struct bpf_map *bpf_object__add_map(struct bpf_object *obj)
> @@ -2850,57 +2845,62 @@ static int compare_vsi_off(const void *_a, const
> void *_b)
> static int btf_fixup_datasec(struct bpf_object *obj, struct btf *btf,
> struct btf_type *t)
> {
> - __u32 size = 0, off = 0, i, vars = btf_vlen(t);
> - const char *name = btf__name_by_offset(btf, t->name_off);
> - const struct btf_type *t_var;
> + __u32 size = 0, i, vars = btf_vlen(t);
> + const char *sec_name = btf__name_by_offset(btf, t->name_off);
> struct btf_var_secinfo *vsi;
> - const struct btf_var *var;
> - int ret;
> + int err;
> - if (!name) {
> + if (!sec_name) {
> pr_debug("No name found in string section for DATASEC kind.\n");
> return -ENOENT;
> }
> - /* .extern datasec size and var offsets were set correctly during
> - * extern collection step, so just skip straight to sorting variables
> + /* extern-backing datasecs (.ksyms, .kconfig) have their size and
> + * variable offsets set at the previous step, so we skip any fixups
> + * for such sections
> */
> if (t->size)
> goto sort_vars;
> - ret = find_elf_sec_sz(obj, name, &size);
> - if (ret || !size) {
> - pr_debug("Invalid size for section %s: %u bytes\n", name, size);
> + err = find_elf_sec_sz(obj, sec_name, &size);
> + if (err || !size) {
> + pr_debug("sec '%s': invalid size %u bytes\n", sec_name, size);
nit: do we want to log err instead here? it seems like the size will be
zero on error anyway, so probably not worth logging it?
> return -ENOENT;
> }
> t->size = size;
> for (i = 0, vsi = btf_var_secinfos(t); i < vars; i++, vsi++) {
> + const struct btf_type *t_var;
> + struct btf_var *var;
> + const char *var_name;
> + Elf64_Sym *sym;
> +
> t_var = btf__type_by_id(btf, vsi->type);
> if (!t_var || !btf_is_var(t_var)) {
> - pr_debug("Non-VAR type seen in section %s\n", name);
> + pr_debug("sec '%s': unexpected non-VAR type found\n", sec_name);
> return -EINVAL;
> }
> var = btf_var(t_var);
> - if (var->linkage == BTF_VAR_STATIC)
> + if (var->linkage == BTF_VAR_STATIC || var->linkage ==
> BTF_VAR_GLOBAL_EXTERN)
> continue;
> - name = btf__name_by_offset(btf, t_var->name_off);
> - if (!name) {
> - pr_debug("No name found in string section for VAR kind\n");
> + var_name = btf__name_by_offset(btf, t_var->name_off);
> + if (!var_name) {
> + pr_debug("sec '%s': failed to find name of DATASEC's member #%d\n",
> + sec_name, i);
> return -ENOENT;
> }
> - ret = find_elf_var_offset(obj, name, &off);
> - if (ret) {
> - pr_debug("No offset found in symbol table for VAR %s\n",
> - name);
> + sym = find_elf_var_sym(obj, var_name);
> + if (IS_ERR(sym)) {
> + pr_debug("sec '%s': failed to find ELF symbol for VAR '%s'\n",
> + sec_name, var_name);
> return -ENOENT;
> }
> - vsi->offset = off;
> + vsi->offset = sym->st_value;
> }
> sort_vars:
> @@ -2908,13 +2908,16 @@ static int btf_fixup_datasec(struct bpf_object
> *obj, struct btf *btf,
> return 0;
> }
> -static int btf_finalize_data(struct bpf_object *obj, struct btf *btf)
> +static int bpf_object_fixup_btf(struct bpf_object *obj)
> {
> - int err = 0;
> - __u32 i, n = btf__type_cnt(btf);
> + int i, n, err = 0;
> + if (!obj->btf)
> + return 0;
> +
> + n = btf__type_cnt(obj->btf);
qq: why do s/__u32/int/ here? btf__type_cnt seems to be returning u32?
> for (i = 1; i < n; i++) {
> - struct btf_type *t = btf_type_by_id(btf, i);
> + struct btf_type *t = btf_type_by_id(obj->btf, i);
> /* Loader needs to fix up some of the things compiler
> * couldn't get its hands on while emitting BTF. This
> @@ -2922,28 +2925,12 @@ static int btf_finalize_data(struct bpf_object
> *obj, struct btf *btf)
> * the info from the ELF itself for this purpose.
> */
> if (btf_is_datasec(t)) {
> - err = btf_fixup_datasec(obj, btf, t);
> + err = btf_fixup_datasec(obj, obj->btf, t);
> if (err)
> - break;
> + return err;
> }
> }
> - return libbpf_err(err);
> -}
> -
> -static int bpf_object__finalize_btf(struct bpf_object *obj)
> -{
> - int err;
> -
> - if (!obj->btf)
> - return 0;
> -
> - err = btf_finalize_data(obj, obj->btf);
> - if (err) {
> - pr_warn("Error finalizing %s: %d.\n", BTF_ELF_SEC, err);
> - return err;
> - }
> -
> return 0;
> }
> @@ -7233,7 +7220,7 @@ static struct bpf_object *bpf_object_open(const
> char *path, const void *obj_buf,
> err = err ? : bpf_object__check_endianness(obj);
> err = err ? : bpf_object__elf_collect(obj);
> err = err ? : bpf_object__collect_externs(obj);
> - err = err ? : bpf_object__finalize_btf(obj);
> + err = err ? : bpf_object_fixup_btf(obj);
> err = err ? : bpf_object__init_maps(obj, opts);
> err = err ? : bpf_object_init_progs(obj, opts);
> err = err ? : bpf_object__collect_relos(obj);
> --
> 2.30.2
next prev parent reply other threads:[~2022-10-18 18:47 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-18 3:56 [PATCH bpf-next 0/3] libbpf: support non-mmap()'able data sections Andrii Nakryiko
2022-10-18 3:56 ` [PATCH bpf-next 1/3] libbpf: clean up and refactor BTF fixup step Andrii Nakryiko
2022-10-18 18:47 ` sdf [this message]
2022-10-18 23:18 ` Andrii Nakryiko
2022-10-19 0:15 ` Stanislav Fomichev
2022-10-18 3:56 ` [PATCH bpf-next 2/3] libbpf: only add BPF_F_MMAPABLE flag for data maps with global vars Andrii Nakryiko
2022-10-18 18:52 ` sdf
2022-10-18 23:20 ` Andrii Nakryiko
2022-10-18 3:56 ` [PATCH bpf-next 3/3] libbpf: add non-mmapable data section selftest Andrii Nakryiko
2022-10-18 18:55 ` sdf
2022-10-18 20:56 ` Dave Marchevsky
2022-10-18 21:02 ` Dave Marchevsky
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=Y0700LilBVP2D39B@google.com \
--to=sdf@google.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=kernel-team@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox