From: Jiri Olsa <olsajiri@gmail.com>
To: Hengqi Chen <hengqi.chen@gmail.com>
Cc: bpf@vger.kernel.org, ast@kernel.org, daniel@iogearbox.net,
andrii@kernel.org
Subject: Re: [PATCH bpf-next 2/2] libbpf: Support symbol versioning for uprobe
Date: Mon, 4 Sep 2023 16:10:59 +0200 [thread overview]
Message-ID: <ZPXlcwnSuq16+gcc@krava> (raw)
In-Reply-To: <20230904022444.1695820-3-hengqi.chen@gmail.com>
On Mon, Sep 04, 2023 at 02:24:44AM +0000, Hengqi Chen wrote:
> Currently, we allow users to specify symbol name for uprobe in a qualified
> form, i.e. func@@LIB or func@@LIB_VERSION. For dynamic symbols, their version
> info is actually stored in .gnu.version and .gnu.version_d sections of the ELF
> objects. So dynamic symbols and the qualified name won't match. Add support for
> symbol versioning ([0]) so that we can handle the above case.
>
> [0]: https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA.junk/symversion.html
>
> Signed-off-by: Hengqi Chen <hengqi.chen@gmail.com>
> ---
> tools/lib/bpf/elf.c | 98 +++++++++++++++++++++++++++++++++++++++++----
> 1 file changed, 90 insertions(+), 8 deletions(-)
>
> diff --git a/tools/lib/bpf/elf.c b/tools/lib/bpf/elf.c
> index 5c9e588b17da..ed3d9880eaa4 100644
> --- a/tools/lib/bpf/elf.c
> +++ b/tools/lib/bpf/elf.c
> @@ -9,6 +9,7 @@
> #include "str_error.h"
>
> #define STRERR_BUFSIZE 128
> +#define HIDDEN_BIT 16
hum, the docs says it's bit 15 ?
SNIP
> @@ -138,12 +155,57 @@ static struct elf_sym *elf_sym_iter_next(struct elf_sym_iter *iter)
>
> iter->next_sym_idx = idx + 1;
> ret->name = name;
> + ret->ver = 0;
> + ret->hidden = false;
> +
> + if (iter->versyms) {
> + if (!gelf_getversym(iter->versyms, idx, &versym))
> + continue;
> + ret->ver = versym & ~(1 << HIDDEN_BIT);
> + ret->hidden = versym & (1 << HIDDEN_BIT);
> + }
> return ret;
> }
>
> return NULL;
> }
>
> +static const char *elf_get_vername(Elf *elf, int ver)
> +{
> + GElf_Verdaux verdaux;
> + GElf_Verdef verdef;
> + Elf_Data *verdefs;
> + size_t strtabidx;
> + GElf_Shdr sh;
> + Elf_Scn *scn;
> + int offset;
> +
> + scn = elf_find_next_scn_by_type(elf, SHT_GNU_verdef, NULL);
> + if (!scn)
> + return NULL;
> + if (!gelf_getshdr(scn, &sh))
> + return NULL;
> + strtabidx = sh.sh_link;
> + verdefs = elf_getdata(scn, 0);
should we read verdefs same as you did for versyms in elf_sym_iter_new,
so you don't need to read that every time?
> +
> + offset = 0;
> + while (gelf_getverdef(verdefs, offset, &verdef)) {
> + if (verdef.vd_ndx != ver) {
> + if (!verdef.vd_next)
> + break;
> +
> + offset += verdef.vd_next;
> + continue;
> + }
> +
> + if (!gelf_getverdaux(verdefs, offset + verdef.vd_aux, &verdaux))
> + break;
> +
> + return elf_strptr(elf, strtabidx, verdaux.vda_name);
> +
> + }
> + return NULL;
> +}
>
> /* Transform symbol's virtual address (absolute for binaries and relative
> * for shared libs) into file offset, which is what kernel is expecting
> @@ -191,6 +253,9 @@ long elf_find_func_offset(Elf *elf, const char *binary_path, const char *name)
> for (i = 0; i < ARRAY_SIZE(sh_types); i++) {
> struct elf_sym_iter iter;
> struct elf_sym *sym;
> + size_t sname_len;
> + char sname[256];
is this enough? not sure if there's symbol max size,
maybe we could also use asprintf below
> + const char *ver;
> int last_bind = -1;
> int cur_bind;
>
> @@ -201,14 +266,31 @@ long elf_find_func_offset(Elf *elf, const char *binary_path, const char *name)
> goto out;
>
> while ((sym = elf_sym_iter_next(&iter))) {
> - /* User can specify func, func@@LIB or func@@LIB_VERSION. */
> - if (strncmp(sym->name, name, name_len) != 0)
> - continue;
> - /* ...but we don't want a search for "foo" to match 'foo2" also, so any
> - * additional characters in sname should be of the form "@@LIB".
> - */
> - if (!is_name_qualified && sym->name[name_len] != '\0' && sym->name[name_len] != '@')
> - continue;
> + if (sh_types[i] == SHT_DYNSYM && is_name_qualified) {
> + if (sym->hidden)
> + continue;
> +
> + sname_len = strlen(sym->name);
> + if (strncmp(sym->name, name, sname_len) != 0)
> + continue;
> +
> + ver = elf_get_vername(elf, sym->ver);
> + if (!ver)
> + continue;
> +
> + snprintf(sname, sizeof(sname), "%s@@%s", sym->name, ver);
> + if (strncmp(sname, name, name_len) != 0)
> + continue;
> + } else {
> + /* User can specify func, func@@LIB or func@@LIB_VERSION. */
> + if (strncmp(sym->name, name, name_len) != 0)
> + continue;
> + /* ...but we don't want a search for "foo" to match 'foo2" also, so any
> + * additional characters in sname should be of the form "@@LIB".
> + */
> + if (!is_name_qualified && sym->name[name_len] != '\0' && sym->name[name_len] != '@')
> + continue;
hum, I never checked the versioned symbols, but it looks like we
don't get symbols in 'symbol@version' form, so I wonder how that
worked before
would be great to have a selftest for that
also I had to add change below to test that through prog's section,
I think we need allow '@' in there
thanks,
jirka
---
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 96ff1aa4bf6a..a30f3c48f891 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -11512,8 +11512,11 @@ static int attach_uprobe(const struct bpf_program *prog, long cookie, struct bpf
*link = NULL;
- n = sscanf(prog->sec_name, "%m[^/]/%m[^:]:%m[a-zA-Z0-9_.]+%li",
+ n = sscanf(prog->sec_name, "%m[^/]/%m[^:]:%m[a-zA-Z0-9_.@]+%li",
&probe_type, &binary_path, &func_name, &offset);
next prev parent reply other threads:[~2023-09-04 14:11 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-09-04 2:24 [PATCH bpf-next 0/2] libbpf: Support symbol versioning for uprobe Hengqi Chen
2023-09-04 2:24 ` [PATCH bpf-next 1/2] libbpf: Resolve ambiguous matches at the same offset " Hengqi Chen
2023-09-04 2:24 ` [PATCH bpf-next 2/2] libbpf: Support symbol versioning " Hengqi Chen
2023-09-04 14:10 ` Jiri Olsa [this message]
2023-09-04 15:40 ` Hengqi Chen
2023-09-04 8:38 ` [PATCH bpf-next 0/2] " Alan Maguire
2023-09-04 15:30 ` Hengqi Chen
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=ZPXlcwnSuq16+gcc@krava \
--to=olsajiri@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=hengqi.chen@gmail.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.