Message ID | 20210605111034.1810858-15-jolsa@kernel.org |
---|---|
State | New |
Headers | show |
Series | x86/ftrace/bpf: Add batch support for direct/tracing attach | expand |
On Sat, Jun 5, 2021 at 4:14 AM Jiri Olsa <jolsa@kernel.org> wrote: > > Adding btf__find_by_pattern_kind function that returns > array of BTF ids for given function name pattern. > > Using libc's regex.h support for that. > > Signed-off-by: Jiri Olsa <jolsa@kernel.org> > --- > tools/lib/bpf/btf.c | 68 +++++++++++++++++++++++++++++++++++++++++++++ > tools/lib/bpf/btf.h | 3 ++ > 2 files changed, 71 insertions(+) > > diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c > index b46760b93bb4..421dd6c1e44a 100644 > --- a/tools/lib/bpf/btf.c > +++ b/tools/lib/bpf/btf.c > @@ -1,6 +1,7 @@ > // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) > /* Copyright (c) 2018 Facebook */ > > +#define _GNU_SOURCE > #include <byteswap.h> > #include <endian.h> > #include <stdio.h> > @@ -16,6 +17,7 @@ > #include <linux/err.h> > #include <linux/btf.h> > #include <gelf.h> > +#include <regex.h> > #include "btf.h" > #include "bpf.h" > #include "libbpf.h" > @@ -711,6 +713,72 @@ __s32 btf__find_by_name_kind(const struct btf *btf, const char *type_name, > return libbpf_err(-ENOENT); > } > > +static bool is_wildcard(char c) > +{ > + static const char *wildchars = "*?[|"; > + > + return strchr(wildchars, c); > +} > + > +int btf__find_by_pattern_kind(const struct btf *btf, > + const char *type_pattern, __u32 kind, > + __s32 **__ids) > +{ > + __u32 i, nr_types = btf__get_nr_types(btf); > + __s32 *ids = NULL; > + int cnt = 0, alloc = 0, ret; > + regex_t regex; > + char *pattern; > + > + if (kind == BTF_KIND_UNKN || !strcmp(type_pattern, "void")) > + return 0; > + > + /* When the pattern does not start with wildcard, treat it as > + * if we'd want to match it from the beginning of the string. > + */ This assumption is absolutely atrocious. If we say it's regexp, then it has to always be regexp, not something based on some random heuristic based on the first character. Taking a step back, though. Do we really need to provide this API? Why applications can't implement it on their own, given regexp functionality is provided by libc. Which I didn't know, actually, so that's pretty nice, assuming that it's also available in more minimal implementations like musl. > + asprintf(&pattern, "%s%s", > + is_wildcard(type_pattern[0]) ? "^" : "", > + type_pattern); > + > + ret = regcomp(®ex, pattern, REG_EXTENDED); > + if (ret) { > + pr_warn("failed to compile regex\n"); > + free(pattern); > + return -EINVAL; > + } > + > + free(pattern); > + > + for (i = 1; i <= nr_types; i++) { > + const struct btf_type *t = btf__type_by_id(btf, i); > + const char *name; > + __s32 *p; > + > + if (btf_kind(t) != kind) > + continue; > + name = btf__name_by_offset(btf, t->name_off); > + if (name && regexec(®ex, name, 0, NULL, 0)) > + continue; > + if (cnt == alloc) { > + alloc = max(100, alloc * 3 / 2); > + p = realloc(ids, alloc * sizeof(__u32)); this memory allocation and re-allocation on behalf of users is another argument against this API > + if (!p) { > + free(ids); > + regfree(®ex); > + return -ENOMEM; > + } > + ids = p; > + } > + > + ids[cnt] = i; > + cnt++; > + } > + > + regfree(®ex); > + *__ids = ids; > + return cnt ?: -ENOENT; > +} > + > static bool btf_is_modifiable(const struct btf *btf) > { > return (void *)btf->hdr != btf->raw_data; > diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h > index b54f1c3ebd57..036857aded94 100644 > --- a/tools/lib/bpf/btf.h > +++ b/tools/lib/bpf/btf.h > @@ -371,6 +371,9 @@ btf_var_secinfos(const struct btf_type *t) > return (struct btf_var_secinfo *)(t + 1); > } > > +int btf__find_by_pattern_kind(const struct btf *btf, > + const char *type_pattern, __u32 kind, > + __s32 **__ids); > #ifdef __cplusplus > } /* extern "C" */ > #endif > -- > 2.31.1 >
On Tue, Jun 08, 2021 at 10:29:19PM -0700, Andrii Nakryiko wrote: > On Sat, Jun 5, 2021 at 4:14 AM Jiri Olsa <jolsa@kernel.org> wrote: > > > > Adding btf__find_by_pattern_kind function that returns > > array of BTF ids for given function name pattern. > > > > Using libc's regex.h support for that. > > > > Signed-off-by: Jiri Olsa <jolsa@kernel.org> > > --- > > tools/lib/bpf/btf.c | 68 +++++++++++++++++++++++++++++++++++++++++++++ > > tools/lib/bpf/btf.h | 3 ++ > > 2 files changed, 71 insertions(+) > > > > diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c > > index b46760b93bb4..421dd6c1e44a 100644 > > --- a/tools/lib/bpf/btf.c > > +++ b/tools/lib/bpf/btf.c > > @@ -1,6 +1,7 @@ > > // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) > > /* Copyright (c) 2018 Facebook */ > > > > +#define _GNU_SOURCE > > #include <byteswap.h> > > #include <endian.h> > > #include <stdio.h> > > @@ -16,6 +17,7 @@ > > #include <linux/err.h> > > #include <linux/btf.h> > > #include <gelf.h> > > +#include <regex.h> > > #include "btf.h" > > #include "bpf.h" > > #include "libbpf.h" > > @@ -711,6 +713,72 @@ __s32 btf__find_by_name_kind(const struct btf *btf, const char *type_name, > > return libbpf_err(-ENOENT); > > } > > > > +static bool is_wildcard(char c) > > +{ > > + static const char *wildchars = "*?[|"; > > + > > + return strchr(wildchars, c); > > +} > > + > > +int btf__find_by_pattern_kind(const struct btf *btf, > > + const char *type_pattern, __u32 kind, > > + __s32 **__ids) > > +{ > > + __u32 i, nr_types = btf__get_nr_types(btf); > > + __s32 *ids = NULL; > > + int cnt = 0, alloc = 0, ret; > > + regex_t regex; > > + char *pattern; > > + > > + if (kind == BTF_KIND_UNKN || !strcmp(type_pattern, "void")) > > + return 0; > > + > > + /* When the pattern does not start with wildcard, treat it as > > + * if we'd want to match it from the beginning of the string. > > + */ > > This assumption is absolutely atrocious. If we say it's regexp, then > it has to always be regexp, not something based on some random > heuristic based on the first character. > > Taking a step back, though. Do we really need to provide this API? Why > applications can't implement it on their own, given regexp > functionality is provided by libc. Which I didn't know, actually, so > that's pretty nice, assuming that it's also available in more minimal > implementations like musl. > so the only purpose for this function is to support wildcards in tests like: SEC("fentry.multi/bpf_fentry_test*") so the generic skeleton attach function can work.. but that can be removed and the test programs can be attached manually through some other attach function that will have list of functions as argument jirka > > + asprintf(&pattern, "%s%s", > > + is_wildcard(type_pattern[0]) ? "^" : "", > > + type_pattern); > > + > > + ret = regcomp(®ex, pattern, REG_EXTENDED); > > + if (ret) { > > + pr_warn("failed to compile regex\n"); > > + free(pattern); > > + return -EINVAL; > > + } > > + > > + free(pattern); > > + > > + for (i = 1; i <= nr_types; i++) { > > + const struct btf_type *t = btf__type_by_id(btf, i); > > + const char *name; > > + __s32 *p; > > + > > + if (btf_kind(t) != kind) > > + continue; > > + name = btf__name_by_offset(btf, t->name_off); > > + if (name && regexec(®ex, name, 0, NULL, 0)) > > + continue; > > + if (cnt == alloc) { > > + alloc = max(100, alloc * 3 / 2); > > + p = realloc(ids, alloc * sizeof(__u32)); > > this memory allocation and re-allocation on behalf of users is another > argument against this API > > > + if (!p) { > > + free(ids); > > + regfree(®ex); > > + return -ENOMEM; > > + } > > + ids = p; > > + } > > + > > + ids[cnt] = i; > > + cnt++; > > + } > > + > > + regfree(®ex); > > + *__ids = ids; > > + return cnt ?: -ENOENT; > > +} > > + > > static bool btf_is_modifiable(const struct btf *btf) > > { > > return (void *)btf->hdr != btf->raw_data; > > diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h > > index b54f1c3ebd57..036857aded94 100644 > > --- a/tools/lib/bpf/btf.h > > +++ b/tools/lib/bpf/btf.h > > @@ -371,6 +371,9 @@ btf_var_secinfos(const struct btf_type *t) > > return (struct btf_var_secinfo *)(t + 1); > > } > > > > +int btf__find_by_pattern_kind(const struct btf *btf, > > + const char *type_pattern, __u32 kind, > > + __s32 **__ids); > > #ifdef __cplusplus > > } /* extern "C" */ > > #endif > > -- > > 2.31.1 > > >
On Wed, Jun 09, 2021 at 03:59:47PM +0200, Jiri Olsa wrote: SNIP > > > + > > > + /* When the pattern does not start with wildcard, treat it as > > > + * if we'd want to match it from the beginning of the string. > > > + */ > > > > This assumption is absolutely atrocious. If we say it's regexp, then > > it has to always be regexp, not something based on some random > > heuristic based on the first character. > > > > Taking a step back, though. Do we really need to provide this API? Why > > applications can't implement it on their own, given regexp > > functionality is provided by libc. Which I didn't know, actually, so > > that's pretty nice, assuming that it's also available in more minimal > > implementations like musl. > > > > so the only purpose for this function is to support wildcards in > tests like: > > SEC("fentry.multi/bpf_fentry_test*") > > so the generic skeleton attach function can work.. but that can be > removed and the test programs can be attached manually through some > other attach function that will have list of functions as argument nah, no other attach function is needed, we have that support now in link_create ready to use ;-) sry jirka
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c index b46760b93bb4..421dd6c1e44a 100644 --- a/tools/lib/bpf/btf.c +++ b/tools/lib/bpf/btf.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) /* Copyright (c) 2018 Facebook */ +#define _GNU_SOURCE #include <byteswap.h> #include <endian.h> #include <stdio.h> @@ -16,6 +17,7 @@ #include <linux/err.h> #include <linux/btf.h> #include <gelf.h> +#include <regex.h> #include "btf.h" #include "bpf.h" #include "libbpf.h" @@ -711,6 +713,72 @@ __s32 btf__find_by_name_kind(const struct btf *btf, const char *type_name, return libbpf_err(-ENOENT); } +static bool is_wildcard(char c) +{ + static const char *wildchars = "*?[|"; + + return strchr(wildchars, c); +} + +int btf__find_by_pattern_kind(const struct btf *btf, + const char *type_pattern, __u32 kind, + __s32 **__ids) +{ + __u32 i, nr_types = btf__get_nr_types(btf); + __s32 *ids = NULL; + int cnt = 0, alloc = 0, ret; + regex_t regex; + char *pattern; + + if (kind == BTF_KIND_UNKN || !strcmp(type_pattern, "void")) + return 0; + + /* When the pattern does not start with wildcard, treat it as + * if we'd want to match it from the beginning of the string. + */ + asprintf(&pattern, "%s%s", + is_wildcard(type_pattern[0]) ? "^" : "", + type_pattern); + + ret = regcomp(®ex, pattern, REG_EXTENDED); + if (ret) { + pr_warn("failed to compile regex\n"); + free(pattern); + return -EINVAL; + } + + free(pattern); + + for (i = 1; i <= nr_types; i++) { + const struct btf_type *t = btf__type_by_id(btf, i); + const char *name; + __s32 *p; + + if (btf_kind(t) != kind) + continue; + name = btf__name_by_offset(btf, t->name_off); + if (name && regexec(®ex, name, 0, NULL, 0)) + continue; + if (cnt == alloc) { + alloc = max(100, alloc * 3 / 2); + p = realloc(ids, alloc * sizeof(__u32)); + if (!p) { + free(ids); + regfree(®ex); + return -ENOMEM; + } + ids = p; + } + + ids[cnt] = i; + cnt++; + } + + regfree(®ex); + *__ids = ids; + return cnt ?: -ENOENT; +} + static bool btf_is_modifiable(const struct btf *btf) { return (void *)btf->hdr != btf->raw_data; diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h index b54f1c3ebd57..036857aded94 100644 --- a/tools/lib/bpf/btf.h +++ b/tools/lib/bpf/btf.h @@ -371,6 +371,9 @@ btf_var_secinfos(const struct btf_type *t) return (struct btf_var_secinfo *)(t + 1); } +int btf__find_by_pattern_kind(const struct btf *btf, + const char *type_pattern, __u32 kind, + __s32 **__ids); #ifdef __cplusplus } /* extern "C" */ #endif
Adding btf__find_by_pattern_kind function that returns array of BTF ids for given function name pattern. Using libc's regex.h support for that. Signed-off-by: Jiri Olsa <jolsa@kernel.org> --- tools/lib/bpf/btf.c | 68 +++++++++++++++++++++++++++++++++++++++++++++ tools/lib/bpf/btf.h | 3 ++ 2 files changed, 71 insertions(+)