Implement dual-path optimization in attach_kprobe_session(): - Fast path: Use syms[] array for exact function names (no kallsyms parsing) - Slow path: Use pattern matching with kallsyms only for wildcards
This avoids expensive kallsyms file parsing (~150ms) when function names are specified exactly, improving attachment time 50x (~3-5ms). Error code normalization: The fast path returns ESRCH from kernel's ftrace_lookup_symbols(), while slow path returns ENOENT from userspace kallsyms parsing. Convert ESRCH to ENOENT in fast path to maintain API consistency - both paths now return identical error codes for "symbol not found". Signed-off-by: Andrey Grodzovsky <[email protected]> --- tools/lib/bpf/libbpf.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 0be7017800fe..87a71eab4308 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -12192,7 +12192,7 @@ static int attach_kprobe_session(const struct bpf_program *prog, long cookie, { LIBBPF_OPTS(bpf_kprobe_multi_opts, opts, .session = true); const char *spec; - char *pattern; + char *func_name; int n; *link = NULL; @@ -12202,14 +12202,36 @@ static int attach_kprobe_session(const struct bpf_program *prog, long cookie, return 0; spec = prog->sec_name + sizeof("kprobe.session/") - 1; - n = sscanf(spec, "%m[a-zA-Z0-9_.*?]", &pattern); + n = sscanf(spec, "%m[a-zA-Z0-9_.*?]", &func_name); if (n < 1) { - pr_warn("kprobe session pattern is invalid: %s\n", spec); + pr_warn("kprobe session function name is invalid: %s\n", spec); return -EINVAL; } - *link = bpf_program__attach_kprobe_multi_opts(prog, pattern, &opts); - free(pattern); + /* Check if pattern contains wildcards */ + if (strpbrk(func_name, "*?")) { + /* Wildcard pattern - use pattern matching path with kallsyms parsing */ + *link = bpf_program__attach_kprobe_multi_opts(prog, func_name, &opts); + } else { + /* Exact function name - use syms array path (fast, no kallsyms parsing) */ + const char *syms[1]; + + syms[0] = func_name; + opts.syms = syms; + opts.cnt = 1; + *link = bpf_program__attach_kprobe_multi_opts(prog, NULL, &opts); + if (!*link && errno == ESRCH) { + /* + * Normalize error code for API consistency: fast path returns ESRCH + * from kernel's ftrace_lookup_symbols(), while slow path returns ENOENT + * from userspace kallsyms parsing. Convert ESRCH to ENOENT so both paths + * return the same error for "symbol not found". + */ + errno = ENOENT; + } + } + + free(func_name); return *link ? 0 : -errno; } -- 2.34.1
