From: Jiri Olsa <olsajiri@gmail.com>
To: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Cc: Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Andrii Nakryiko <andrii@kernel.org>,
bpf@vger.kernel.org, Martin KaFai Lau <kafai@fb.com>,
Song Liu <songliubraving@fb.com>, Yonghong Song <yhs@fb.com>,
John Fastabend <john.fastabend@gmail.com>,
KP Singh <kpsingh@chromium.org>,
Stanislav Fomichev <sdf@google.com>, Hao Luo <haoluo@google.com>
Subject: Re: [PATCHv2 bpf-next 06/24] libbpf: Add elf symbol iterator
Date: Fri, 23 Jun 2023 10:19:11 +0200 [thread overview]
Message-ID: <ZJVVf2Ml/gvUSF+I@krava> (raw)
In-Reply-To: <CAEf4BzbVJ4y2-y8WFicA_iSkVUoieWWHbv_f1mLwoY3fSPeTRw@mail.gmail.com>
On Thu, Jun 22, 2023 at 05:31:58PM -0700, Andrii Nakryiko wrote:
> On Tue, Jun 20, 2023 at 1:36 AM Jiri Olsa <jolsa@kernel.org> wrote:
> >
> > Adding elf symbol iterator object (and some functions) that follow
> > open-coded iterator pattern and some functions to ease up iterating
> > elf object symbols.
> >
> > The idea is to iterate single symbol section with:
> >
> > struct elf_symbol_iter iter;
> > struct elf_symbol *sym;
> >
> > if (elf_symbol_iter_new(&iter, elf, binary_path, SHT_DYNSYM))
> > goto error;
> >
> > while ((sym = elf_symbol_iter_next(&iter))) {
> > ...
> > }
> >
> > I considered opening the elf inside the iterator and iterate all symbol
> > sections, but then it gets more complicated wrt user checks for when
> > the next section is processed.
> >
> > Plus side is the we don't need 'exit' function, because caller/user is
> > in charge of that.
> >
> > The returned iterated symbol object from elf_symbol_iter_next function
> > is placed inside the struct elf_symbol_iter, so no extra allocation or
> > argument is needed.
> >
> > Suggested-by: Andrii Nakryiko <andrii@kernel.org>
> > Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> > ---
> > tools/lib/bpf/libbpf.c | 179 ++++++++++++++++++++++++++---------------
> > 1 file changed, 114 insertions(+), 65 deletions(-)
> >
>
> This is great. Left a few nits below. I'm thinkin maybe we should add
> a separate elf.c file for all these ELF-related helpers and start
> offloading code from libbpf.c, which got pretty big already. WDYT?
yes, I thought doing the move after this is merged might be better,
because it's quite big already
>
>
> > diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> > index af52188daa80..cdac368c7ce1 100644
> > --- a/tools/lib/bpf/libbpf.c
> > +++ b/tools/lib/bpf/libbpf.c
> > @@ -10824,6 +10824,109 @@ static Elf_Scn *elf_find_next_scn_by_type(Elf *elf, int sh_type, Elf_Scn *scn)
> > return NULL;
> > }
> >
> > +struct elf_symbol {
> > + const char *name;
> > + unsigned long offset;
> > + int bind;
> > +};
> > +
> > +struct elf_symbol_iter {
>
> naming nits: elf_sym and elf_sym_iter? keep it short, keep it cool :)
ok
>
> > + Elf *elf;
> > + Elf_Data *symbols;
>
> syms :-P
ook ;-)
>
> > + size_t nr_syms;
> > + size_t strtabidx;
> > + size_t idx;
>
> next_sym_idx?
ok
>
> > + struct elf_symbol sym;
> > +};
> > +
> > +static int elf_symbol_iter_new(struct elf_symbol_iter *iter,
> > + Elf *elf, const char *binary_path,
> > + int sh_type)
> > +{
> > + Elf_Scn *scn = NULL;
> > + GElf_Ehdr ehdr;
> > + GElf_Shdr sh;
> > +
> > + memset(iter, 0, sizeof(*iter));
> > +
> > + if (!gelf_getehdr(elf, &ehdr)) {
> > + pr_warn("elf: failed to get ehdr from %s: %s\n", binary_path, elf_errmsg(-1));
> > + return -LIBBPF_ERRNO__FORMAT;
> > + }
> > +
> > + scn = elf_find_next_scn_by_type(elf, sh_type, NULL);
> > + if (!scn) {
> > + pr_debug("elf: failed to find symbol table ELF sections in '%s'\n",
> > + binary_path);
> > + return -EINVAL;
> > + }
> > +
> > + if (!gelf_getshdr(scn, &sh))
> > + return -EINVAL;
> > +
> > + iter->strtabidx = sh.sh_link;
> > + iter->symbols = elf_getdata(scn, 0);
> > + if (!iter->symbols) {
> > + pr_warn("elf: failed to get symbols for symtab section in '%s': %s\n",
> > + binary_path, elf_errmsg(-1));
> > + return -LIBBPF_ERRNO__FORMAT;
> > + }
> > + iter->nr_syms = iter->symbols->d_size / sh.sh_entsize;
> > + iter->elf = elf;
> > + return 0;
> > +}
> > +
> > +static struct elf_symbol *elf_symbol_iter_next(struct elf_symbol_iter *iter)
> > +{
> > + struct elf_symbol *ret = &iter->sym;
> > + unsigned long offset = 0;
> > + const char *name = NULL;
> > + GElf_Shdr sym_sh;
> > + Elf_Scn *sym_scn;
> > + GElf_Sym sym;
> > + size_t idx;
> > +
> > + for (idx = iter->idx; idx < iter->nr_syms; idx++) {
> > + if (!gelf_getsym(iter->symbols, idx, &sym))
> > + continue;
> > + if (GELF_ST_TYPE(sym.st_info) != STT_FUNC)
> > + continue;
>
> it would be more generic if this symbol type filter was a parameter to
> iterator, instead of hard-coding it?
ok
>
> > + name = elf_strptr(iter->elf, iter->strtabidx, sym.st_name);
> > + if (!name)
> > + continue;
> > +
> > + /* Transform symbol's virtual address (absolute for
> > + * binaries and relative for shared libs) into file
> > + * offset, which is what kernel is expecting for
> > + * uprobe/uretprobe attachment.
> > + * See Documentation/trace/uprobetracer.rst for more
> > + * details.
> > + * This is done by looking up symbol's containing
> > + * section's header and using iter's virtual address
> > + * (sh_addr) and corresponding file offset (sh_offset)
> > + * to transform sym.st_value (virtual address) into
> > + * desired final file offset.
> > + */
> > + sym_scn = elf_getscn(iter->elf, sym.st_shndx);
> > + if (!sym_scn)
> > + continue;
> > + if (!gelf_getshdr(sym_scn, &sym_sh))
> > + continue;
> > +
> > + offset = sym.st_value - sym_sh.sh_addr + sym_sh.sh_offset;
>
> I think this part is not really generic "let's iterate ELF symbols",
> maybe let users of iterator do this? We can have a helper to do
> translation if we need to do it in few different places.
yes this will be called in all the places we use the iterator,
I'll add the helper for it
>
> > + break;
> > + }
> > +
> > + /* we reached the last symbol */
> > + if (idx == iter->nr_syms)
> > + return NULL;
> > + iter->idx = idx + 1;
> > + ret->name = name;
> > + ret->bind = GELF_ST_BIND(sym.st_info);
> > + ret->offset = offset;
>
> Why not just return entire GElf_Sym information and let user process
> it as desired. So basically for each symbol you'll give back its name,
> GElf_Sym info, and I'd return symbol index as well. That will keep
> this very generic for future uses.
ok, so you have other users of this iterator in mind already?
>
> > + return ret;
>
> I'd structure this a bit different. If we got out of loop, just return
> NULL. Then inside the for loop, when we found the symbol, fill out ret
> and return from inside the for loop. I think it's more
> straightforward.
ok, will change
thanks,
jirka
>
> > +}
> > +
> > /* Find offset of function name in the provided ELF object. "binary_path" is
> > * the path to the ELF binary represented by "elf", and only used for error
> > * reporting matters. "name" matches symbol name or name@@LIB for library
>
> [...]
next prev parent reply other threads:[~2023-06-23 8:19 UTC|newest]
Thread overview: 61+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-20 8:35 [PATCHv2 bpf-next 00/24] bpf: Add multi uprobe link Jiri Olsa
2023-06-20 8:35 ` [PATCHv2 bpf-next 01/24] " Jiri Olsa
2023-06-20 17:11 ` Alexei Starovoitov
2023-06-21 8:32 ` Jiri Olsa
2023-06-23 0:18 ` Andrii Nakryiko
2023-06-23 8:19 ` Jiri Olsa
2023-06-23 16:24 ` Andrii Nakryiko
2023-06-23 16:39 ` Alexei Starovoitov
2023-06-23 17:11 ` Andrii Nakryiko
2023-06-23 17:20 ` Alexei Starovoitov
2023-06-25 1:19 ` Jiri Olsa
2023-06-25 1:18 ` Jiri Olsa
2023-06-26 18:27 ` Andrii Nakryiko
2023-06-26 19:23 ` Jiri Olsa
2023-06-20 8:35 ` [PATCHv2 bpf-next 02/24] bpf: Add cookies support for uprobe_multi link Jiri Olsa
2023-06-23 0:18 ` Andrii Nakryiko
2023-06-23 8:01 ` Jiri Olsa
2023-06-20 8:35 ` [PATCHv2 bpf-next 03/24] bpf: Add pid filter " Jiri Olsa
2023-06-20 12:40 ` Oleg Nesterov
2023-06-20 8:35 ` [PATCHv2 bpf-next 04/24] bpf: Add bpf_get_func_ip helper support for uprobe link Jiri Olsa
2023-06-20 8:35 ` [PATCHv2 bpf-next 05/24] libbpf: Add uprobe_multi attach type and link names Jiri Olsa
2023-06-20 8:35 ` [PATCHv2 bpf-next 06/24] libbpf: Add elf symbol iterator Jiri Olsa
2023-06-23 0:31 ` Andrii Nakryiko
2023-06-23 8:19 ` Jiri Olsa [this message]
2023-06-23 16:27 ` Andrii Nakryiko
2023-06-23 16:29 ` Andrii Nakryiko
2023-06-20 8:35 ` [PATCHv2 bpf-next 07/24] libbpf: Add open_elf/close_elf functions Jiri Olsa
2023-06-23 0:33 ` Andrii Nakryiko
2023-06-23 8:21 ` Jiri Olsa
2023-06-20 8:35 ` [PATCHv2 bpf-next 08/24] libbpf: Add elf_find_multi_func_offset function Jiri Olsa
2023-06-23 20:39 ` Andrii Nakryiko
2023-06-25 1:19 ` Jiri Olsa
2023-06-20 8:35 ` [PATCHv2 bpf-next 09/24] libbpf: Add elf_find_pattern_func_offset function Jiri Olsa
2023-06-23 20:39 ` Andrii Nakryiko
2023-06-25 1:19 ` Jiri Olsa
2023-06-20 8:35 ` [PATCHv2 bpf-next 10/24] libbpf: Add bpf_link_create support for multi uprobes Jiri Olsa
2023-06-23 20:40 ` Andrii Nakryiko
2023-06-20 8:35 ` [PATCHv2 bpf-next 11/24] libbpf: Add bpf_program__attach_uprobe_multi_opts function Jiri Olsa
2023-06-23 20:40 ` Andrii Nakryiko
2023-06-25 1:19 ` Jiri Olsa
2023-06-20 8:35 ` [PATCHv2 bpf-next 12/24] libbpf: Add support for u[ret]probe.multi[.s] program sections Jiri Olsa
2023-06-23 20:40 ` Andrii Nakryiko
2023-06-25 1:20 ` Jiri Olsa
2023-06-20 8:35 ` [PATCHv2 bpf-next 13/24] libbpf: Add uprobe multi link detection Jiri Olsa
2023-06-23 20:40 ` Andrii Nakryiko
2023-06-25 1:18 ` Jiri Olsa
2023-06-26 18:21 ` Andrii Nakryiko
2023-06-26 19:22 ` Jiri Olsa
2023-06-20 8:35 ` [PATCHv2 bpf-next 14/24] libbpf: Add uprobe multi link support to bpf_program__attach_usdt Jiri Olsa
2023-06-23 20:40 ` Andrii Nakryiko
2023-06-25 1:18 ` Jiri Olsa
2023-06-20 8:35 ` [PATCHv2 bpf-next 15/24] selftests/bpf: Add uprobe_multi skel test Jiri Olsa
2023-06-20 8:35 ` [PATCHv2 bpf-next 16/24] selftests/bpf: Add uprobe_multi api test Jiri Olsa
2023-06-20 8:35 ` [PATCHv2 bpf-next 17/24] selftests/bpf: Add uprobe_multi link test Jiri Olsa
2023-06-20 8:35 ` [PATCHv2 bpf-next 18/24] selftests/bpf: Add uprobe_multi test program Jiri Olsa
2023-06-20 8:35 ` [PATCHv2 bpf-next 19/24] selftests/bpf: Add uprobe_multi bench test Jiri Olsa
2023-06-20 8:35 ` [PATCHv2 bpf-next 20/24] selftests/bpf: Add usdt_multi test program Jiri Olsa
2023-06-20 8:35 ` [PATCHv2 bpf-next 21/24] selftests/bpf: Add usdt_multi bench test Jiri Olsa
2023-06-20 8:35 ` [PATCHv2 bpf-next 22/24] selftests/bpf: Add uprobe_multi cookie test Jiri Olsa
2023-06-20 8:35 ` [PATCHv2 bpf-next 23/24] selftests/bpf: Add uprobe_multi pid filter tests Jiri Olsa
2023-06-20 8:35 ` [PATCHv2 bpf-next 24/24] selftests/bpf: Add extra link to uprobe_multi tests Jiri Olsa
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=ZJVVf2Ml/gvUSF+I@krava \
--to=olsajiri@gmail.com \
--cc=andrii.nakryiko@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=haoluo@google.com \
--cc=john.fastabend@gmail.com \
--cc=kafai@fb.com \
--cc=kpsingh@chromium.org \
--cc=sdf@google.com \
--cc=songliubraving@fb.com \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox