@@ -10230,6 +10230,12 @@ static const char *tracefs_available_filter_functions(void)
TRACEFS"/available_filter_functions";
}
+static const char *tracefs_available_filter_functions_addrs(void)
+{
+ return use_debugfs() ? DEBUGFS"/available_filter_functions_addrs" :
+ TRACEFS"/available_filter_functions_addrs";
+}
+
static void gen_kprobe_legacy_event_name(char *buf, size_t buf_sz,
const char *kfunc_name, size_t offset)
{
@@ -10653,6 +10659,53 @@ static int libbpf_available_kallsyms_parse(struct kprobe_multi_resolve *res)
return err;
}
+static bool has_available_filter_functions_addrs(void)
+{
+ return access(tracefs_available_filter_functions_addrs(), R_OK) != -1;
+}
+
+static int libbpf_available_kprobes_parse(struct kprobe_multi_resolve *res)
+{
+ char sym_name[256];
+ FILE *f;
+ int ret, err = 0;
+ unsigned long long sym_addr;
+ const char *available_path = tracefs_available_filter_functions_addrs();
+
+ f = fopen(available_path, "r");
+ if (!f) {
+ err = -errno;
+ pr_warn("failed to open %s.\n", available_path);
+ return err;
+ }
+
+ while (true) {
+ ret = fscanf(f, "%llx %s%*[^\n]\n", &sym_addr, sym_name);
+ if (ret == EOF && feof(f))
+ break;
+
+ if (ret != 2) {
+ pr_warn("failed to read available kprobe entry: %d\n",
+ ret);
+ err = -EINVAL;
+ break;
+ }
+
+ if (!glob_match(sym_name, res->pattern))
+ continue;
+
+ err = libbpf_ensure_mem((void **) &res->addrs, &res->cap,
+ sizeof(unsigned long), res->cnt + 1);
+ if (err)
+ break;
+
+ res->addrs[res->cnt++] = (unsigned long) sym_addr;
+ }
+
+ fclose(f);
+ return err;
+}
+
struct bpf_link *
bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
const char *pattern,
@@ -10689,7 +10742,10 @@ bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
return libbpf_err_ptr(-EINVAL);
if (pattern) {
- err = libbpf_available_kallsyms_parse(&res);
+ if (has_available_filter_functions_addrs())
+ err = libbpf_available_kprobes_parse(&res);
+ else
+ err = libbpf_available_kallsyms_parse(&res);
if (err)
goto error;
if (!res.cnt) {