@@ -10422,8 +10422,8 @@ struct kprobe_multi_resolve {
};
static int
-resolve_kprobe_multi_cb(unsigned long long sym_addr, char sym_type,
- const char *sym_name, void *ctx)
+kallsyms_resolve_kprobe_multi_cb(unsigned long long sym_addr, char sym_type,
+ const char *sym_name, void *ctx)
{
struct kprobe_multi_resolve *res = ctx;
int err;
@@ -10440,6 +10440,99 @@ resolve_kprobe_multi_cb(unsigned long long sym_addr, char sym_type,
return 0;
}
+static int
+resolve_function_addrs(const char *name, unsigned long long *sym_addr)
+{
+ char sym_name[500];
+ int ret, err = 0;
+ FILE *f;
+
+ f = fopen("/proc/kallsyms", "r");
+ if (!f) {
+ err = -errno;
+ pr_warn("failed to open /proc/kallsyms: %d\n", err);
+ return err;
+ }
+
+ while (true) {
+ ret = fscanf(f, "%llx %*c %499s%*[^\n]\n",
+ sym_addr, sym_name);
+ if (ret == EOF && feof(f)) {
+ pr_warn("not found syms in /proc/kallsyms\n");
+ err = -ENOENT;
+ break;
+ }
+ if (ret != 2) {
+ pr_warn("failed to read kallsyms entry: %d\n", ret);
+ err = -EINVAL;
+ break;
+ }
+
+ if (strcmp(name, sym_name) == 0)
+ return 0;
+ }
+
+ return err;
+}
+
+static int resolve_kprobe_multi_cb(const char *sym_name, void *ctx)
+{
+ unsigned long long sym_addr;
+ struct kprobe_multi_resolve *res = ctx;
+ int err;
+
+ if (!glob_match(sym_name, res->pattern))
+ return 0;
+
+ err = resolve_function_addrs(sym_name, &sym_addr);
+ if (err)
+ return err;
+
+ err = libbpf_ensure_mem((void **) &res->addrs, &res->cap, sizeof(unsigned long),
+ res->cnt + 1);
+ if (err)
+ return err;
+
+ res->addrs[res->cnt++] = (unsigned long) sym_addr;
+ return 0;
+}
+
+int libbpf_available_filter_functions_parse(available_filter_functions_cb_t cb,
+ void *ctx)
+{
+ char sym_name[256];
+ FILE *f;
+ int ret, err = 0;
+
+ f = fopen("/sys/kernel/debug/tracing/available_filter_functions", "r");
+ if (!f) {
+ pr_warn("failed to open /sys/kernel/debug/tracing/available_filter_functions, ");
+ pr_warn("fallback to /proc/kallsyms.\n");
+ goto fallback;
+ }
+
+ while (true) {
+ ret = fscanf(f, "%s%*[^\n]\n", sym_name);
+ if (ret == EOF && feof(f))
+ break;
+ if (ret != 1) {
+ pr_warn("failed to read available_filter_functions entry: %d\n",
+ ret);
+ break;
+ }
+
+ err = cb(sym_name, ctx);
+ if (err)
+ return err;
+ }
+
+ fclose(f);
+ return err;
+
+fallback:
+ return libbpf_kallsyms_parse(kallsyms_resolve_kprobe_multi_cb, ctx);
+}
+
struct bpf_link *
bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
const char *pattern,
@@ -10476,7 +10569,8 @@ bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
return libbpf_err_ptr(-EINVAL);
if (pattern) {
- err = libbpf_kallsyms_parse(resolve_kprobe_multi_cb, &res);
+ err = libbpf_available_filter_functions_parse(resolve_kprobe_multi_cb,
+ &res);
if (err)
goto error;
if (!res.cnt) {
@@ -481,8 +481,10 @@ __s32 btf__find_by_name_kind_own(const struct btf *btf, const char *type_name,
typedef int (*kallsyms_cb_t)(unsigned long long sym_addr, char sym_type,
const char *sym_name, void *ctx);
-
int libbpf_kallsyms_parse(kallsyms_cb_t cb, void *arg);
+typedef int (*available_filter_functions_cb_t)(const char *sym_name, void *ctx);
+int libbpf_available_filter_functions_parse(available_filter_functions_cb_t cb,
+ void *arg);
/* handle direct returned errors */
static inline int libbpf_err(int ret)