On Wed, Mar 30, 2022 at 8:27 AM Alan Maguire <alan.maguire@xxxxxxxxxx> wrote: > > kprobe attach is name-based, using lookups of kallsyms to translate > a function name to an address. Currently uprobe attach is done > via an offset value as described in [1]. Extend uprobe opts > for attach to include a function name which can then be converted > into a uprobe-friendly offset. The calcualation is done in > several steps: > > 1. First, determine the symbol address using libelf; this gives us > the offset as reported by objdump > 2. If the function is a shared library function - and the binary > provided is a shared library - no further work is required; > the address found is the required address > 3. Finally, if the function is local, subtract the base address > associated with the object, retrieved from ELF program headers. > > The resultant value is then added to the func_offset value passed > in to specify the uprobe attach address. So specifying a func_offset > of 0 along with a function name "printf" will attach to printf entry. > > The modes of operation supported are then > > 1. to attach to a local function in a binary; function "foo1" in > "/usr/bin/foo" > 2. to attach to a shared library function in a shared library - > function "malloc" in libc. > > [1] https://www.kernel.org/doc/html/latest/trace/uprobetracer.html > > Signed-off-by: Alan Maguire <alan.maguire@xxxxxxxxxx> > --- > tools/lib/bpf/libbpf.c | 203 +++++++++++++++++++++++++++++++++++++++++++++++++ > tools/lib/bpf/libbpf.h | 10 ++- > 2 files changed, 212 insertions(+), 1 deletion(-) > [...] > @@ -10569,6 +10758,7 @@ static int resolve_full_path(const char *file, char *result, size_t result_sz) > size_t ref_ctr_off; > int pfd, err; > bool retprobe, legacy; > + const char *func_name; > > if (!OPTS_VALID(opts, bpf_uprobe_opts)) > return libbpf_err_ptr(-EINVAL); > @@ -10586,6 +10776,19 @@ static int resolve_full_path(const char *file, char *result, size_t result_sz) > } > binary_path = full_binary_path; > } > + func_name = OPTS_GET(opts, func_name, NULL); > + if (func_name) { > + long sym_off; > + > + if (!binary_path) { > + pr_warn("name-based attach requires binary_path\n"); same about prog '%s': prefix > + return libbpf_err_ptr(-EINVAL); > + } > + sym_off = elf_find_func_offset(binary_path, func_name); > + if (sym_off < 0) > + return libbpf_err_ptr(sym_off); > + func_offset += sym_off; > + } > > legacy = determine_uprobe_perf_type() < 0; > if (!legacy) { > diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h > index 05dde85..28cd206 100644 > --- a/tools/lib/bpf/libbpf.h > +++ b/tools/lib/bpf/libbpf.h > @@ -459,9 +459,17 @@ struct bpf_uprobe_opts { > __u64 bpf_cookie; > /* uprobe is return probe, invoked at function return time */ > bool retprobe; > + /* Function name to attach to. Could be an unqualified ("abc") or library-qualified > + * "abc@LIBXYZ" name. To specify function entry, func_name should be set while > + * func_offset argument to bpf_prog__attach_uprobe_opts() should be 0. To trace an > + * offset within a function, specify func_name and use func_offset argument to specify > + * offset within the function. Shared library functions must specify the shared library > + * binary_path. > + */ > + const char *func_name; > size_t :0; > }; > -#define bpf_uprobe_opts__last_field retprobe > +#define bpf_uprobe_opts__last_field func_name > > /** > * @brief **bpf_program__attach_uprobe()** attaches a BPF program > -- > 1.8.3.1 >