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


Reply via email to