Extend fprobe to support list-style filters and explicit entry/exit suffixes. Currentyl, fprobe only supports a single symbol (or wildcard) per event. This patch allows users to specify a comma-separated list of symbols.
New Syntax: - f:[GRP/][EVENT] func1,func2,func3:entry - f:[GRP/][EVENT] func1,func2,func3:exit
Logic changes: - Refactor parsing logic into 'parse_fprobe_spec' - Support '!' prefix for exclusion - Disable BTF lookup ('ctx->funcname = NULL') when a list or wildcard is used, as a single function signature cannot apply to multiple functions. - Reject legacy '%return' suffix when used with lists or wildcards - Update tracefs/README
Testing: Verified on x86_64 via QEMU. Checked registration of lists, exclusions, and explicit suffixes. Verified rejection of invalid syntax including trailing commas and mixed legacy/new syntax.
Seokwoo Chung (Ryan) (3): docs: tracing/fprobe: Document list filters and :entry/:exit tracing/fprobe: Support comma-separated symbols and :entry/:exit selftests/ftrace: Add accept cases for fprobe list syntax
Changes in v4: - Added validation to reject trailing commas (empty tokens) in symbol lists - Added vaildation to reject mixed of list syntax with %return suffix - Refactored parse_fprobe_spec to user __free(kfree) for automatic memory cleanup - Removed the now-unused parse_symbol_and_return function to avoid compiler warnings. - Tigtened %return detection to ensure it only matches as a strict suffix, not a substring - Link to v3: https://lore.kernel.org/lkml/20250904103219.f4937968362bfff1ecd3f004@kernel....
Documentation/trace/fprobetrace.rst | 17 +- kernel/trace/trace.c | 3 +- kernel/trace/trace_fprobe.c | 209 ++++++++++++++---- .../ftrace/test.d/dynevent/fprobe_list.tc | 92 ++++++++ 4 files changed, 269 insertions(+), 52 deletions(-) create mode 100644 tools/testing/selftests/ftrace/test.d/dynevent/fprobe_list.tc
Update fprobe event documentation to describe comma-separated symbol lists, exclusions, and explicit suffixes.
Signed-off-by: Seokwoo Chung (Ryan) seokwoo.chung130@gmail.com --- Documentation/trace/fprobetrace.rst | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/Documentation/trace/fprobetrace.rst b/Documentation/trace/fprobetrace.rst index b4c2ca3d02c1..bbcfd57f0005 100644 --- a/Documentation/trace/fprobetrace.rst +++ b/Documentation/trace/fprobetrace.rst @@ -25,14 +25,18 @@ Synopsis of fprobe-events ------------------------- ::
- f[:[GRP1/][EVENT1]] SYM [FETCHARGS] : Probe on function entry - f[MAXACTIVE][:[GRP1/][EVENT1]] SYM%return [FETCHARGS] : Probe on function exit + f[:[GRP1/][EVENT1]] SYM[%return] [FETCHARGS] : Single function + f[:[GRP1/][EVENT1]] SYM[,[!]SYM[,...]][:entry|:exit] [FETCHARGS] :Multiple + function t[:[GRP2/][EVENT2]] TRACEPOINT [FETCHARGS] : Probe on tracepoint
GRP1 : Group name for fprobe. If omitted, use "fprobes" for it. GRP2 : Group name for tprobe. If omitted, use "tracepoints" for it. EVENT1 : Event name for fprobe. If omitted, the event name is - "SYM__entry" or "SYM__exit". + - For a single literal symbol, the event name is + "SYM__entry" or "SYM__exit". + - For a *list or any wildcard*, an explicit [GRP1/][EVENT1] is + required; otherwise the parser rejects it. EVENT2 : Event name for tprobe. If omitted, the event name is the same as "TRACEPOINT", but if the "TRACEPOINT" starts with a digit character, "_TRACEPOINT" is used. @@ -40,6 +44,13 @@ Synopsis of fprobe-events can be probed simultaneously, or 0 for the default value as defined in Documentation/trace/fprobe.rst
+ SYM : Function name or comma-separated list of symbols. + - SYM prefixed with "!" are exclusions. + - ":entry" suffix means it probes entry of given symbols + (default) + - ":exit" suffix means it probes exit of given symbols. + - "%return" suffix means it probes exit of SYM (single + symbol). FETCHARGS : Arguments. Each probe can have up to 128 args. ARG : Fetch "ARG" function argument using BTF (only for function entry or tracepoint.) (*1)
- Update DEFINE_FREE to use standard __free() - Extend fprobe to support multiple symbols per event. Add parsing logic for lists, ! exclusions, and explicit suffixes. Update tracefs/README to reflect the new syntax
Signed-off-by: Seokwoo Chung (Ryan) seokwoo.chung130@gmail.com --- kernel/trace/trace.c | 3 +- kernel/trace/trace_fprobe.c | 209 +++++++++++++++++++++++++++--------- 2 files changed, 163 insertions(+), 49 deletions(-)
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index d1e527cf2aae..e0b77268a702 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -5518,7 +5518,8 @@ static const char readme_msg[] = "\t r[maxactive][:[<group>/][<event>]] <place> [<args>]\n" #endif #ifdef CONFIG_FPROBE_EVENTS - "\t f[:[<group>/][<event>]] <func-name>[%return] [<args>]\n" + "\t f[:[<group>/][<event>]] <func-name>[:entry|:exit] [<args>]\n" + "\t (single symbols still accept %return)\n" "\t t[:[<group>/][<event>]] <tracepoint> [<args>]\n" #endif #ifdef CONFIG_HIST_TRIGGERS diff --git a/kernel/trace/trace_fprobe.c b/kernel/trace/trace_fprobe.c index 8001dbf16891..6307d7d7dd9c 100644 --- a/kernel/trace/trace_fprobe.c +++ b/kernel/trace/trace_fprobe.c @@ -187,11 +187,14 @@ DEFINE_FREE(tuser_put, struct tracepoint_user *, */ struct trace_fprobe { struct dyn_event devent; + char *filter; struct fprobe fp; + bool list_mode; + char *nofilter; const char *symbol; + struct trace_probe tp; bool tprobe; struct tracepoint_user *tuser; - struct trace_probe tp; };
static bool is_trace_fprobe(struct dyn_event *ev) @@ -559,6 +562,8 @@ static void free_trace_fprobe(struct trace_fprobe *tf) trace_probe_cleanup(&tf->tp); if (tf->tuser) tracepoint_user_put(tf->tuser); + kfree(tf->filter); + kfree(tf->nofilter); kfree(tf->symbol); kfree(tf); } @@ -838,7 +843,12 @@ static int __register_trace_fprobe(struct trace_fprobe *tf) if (trace_fprobe_is_tracepoint(tf)) return __regsiter_tracepoint_fprobe(tf);
- /* TODO: handle filter, nofilter or symbol list */ + /* Registration path: + * - list_mode: pass filter/nofilter + * - single: pass symbol only (legacy) + */ + if (tf->list_mode) + return register_fprobe(&tf->fp, tf->filter, tf->nofilter); return register_fprobe(&tf->fp, tf->symbol, NULL); }
@@ -1154,60 +1164,119 @@ static struct notifier_block tprobe_event_module_nb = { }; #endif /* CONFIG_MODULES */
-static int parse_symbol_and_return(int argc, const char *argv[], - char **symbol, bool *is_return, - bool is_tracepoint) +static bool has_wildcard(const char *s) { - char *tmp = strchr(argv[1], '%'); - int i; + return s && (strchr(s, '*') || strchr(s, '?')); +}
- if (tmp) { - int len = tmp - argv[1]; +static int parse_fprobe_spec(const char *in, bool is_tracepoint, + char **base, bool *is_return, bool *list_mode, + char **filter, char **nofilter) +{ + char *work __free(kfree) = NULL; + char *b __free(kfree) = NULL; + char *f __free(kfree) = NULL; + char *nf __free(kfree) = NULL; + bool legacy_ret = false; + bool list = false; + const char *p; + int ret = 0;
- if (!is_tracepoint && !strcmp(tmp, "%return")) { - *is_return = true; - } else { - trace_probe_log_err(len, BAD_ADDR_SUFFIX); - return -EINVAL; - } - *symbol = kmemdup_nul(argv[1], len, GFP_KERNEL); - } else - *symbol = kstrdup(argv[1], GFP_KERNEL); - if (!*symbol) - return -ENOMEM; + if (!in || !base || !is_return || !list_mode || !filter || !nofilter) + return -EINVAL;
- if (*is_return) - return 0; + *base = NULL; *filter = NULL; *nofilter = NULL; + *is_return = false; *list_mode = false;
if (is_tracepoint) { - tmp = *symbol; - while (*tmp && (isalnum(*tmp) || *tmp == '_')) - tmp++; - if (*tmp) { - /* find a wrong character. */ - trace_probe_log_err(tmp - *symbol, BAD_TP_NAME); - kfree(*symbol); - *symbol = NULL; + if (strchr(in, ',') || strchr(in, ':')) return -EINVAL; - } + if (strstr(in, "%return")) + return -EINVAL; + for (p = in; *p; p++) + if (!isalnum(*p) && *p != '_') + return -EINVAL; + b = kstrdup(in, GFP_KERNEL); + if (!b) + return -ENOMEM; + *base = no_free_ptr(b); + return 0; }
- /* If there is $retval, this should be a return fprobe. */ - for (i = 2; i < argc; i++) { - tmp = strstr(argv[i], "$retval"); - if (tmp && !isalnum(tmp[7]) && tmp[7] != '_') { - if (is_tracepoint) { - trace_probe_log_set_index(i); - trace_probe_log_err(tmp - argv[i], RETVAL_ON_PROBE); - kfree(*symbol); - *symbol = NULL; + work = kstrdup(in, GFP_KERNEL); + if (!work) + return -ENOMEM; + + p = strstr(work, "%return"); + if (p && p[7] == '\0') { + *is_return = true; + legacy_ret = true; + *(char *)p = '\0'; + } else { + /* + * If "symbol:entry" or "symbol:exit" is given, it is new + * style probe. + */ + p = strrchr(work, ':'); + if (p) { + if (!strcmp(p, ":exit")) { + *is_return = true; + *(char *)p = '\0'; + } else if (!strcmp(p, ":entry")) { + *(char *)p = '\0'; + } else { return -EINVAL; } - *is_return = true; - break; } } - return 0; + + list = !!strchr(work, ','); + + if (list && legacy_ret) { + return -EINVAL; + } + + if (legacy_ret) + *is_return = true; + + b = kstrdup(work, GFP_KERNEL); + if (!b) + return -ENOMEM; + + if (list) { + char *tmp = b, *tok; + size_t fsz, nfsz; + + fsz = nfsz = strlen(b) + 1; + + f = kzalloc(fsz, GFP_KERNEL); + nf = kzalloc(nfsz, GFP_KERNEL); + if (!f || !nf) + return -ENOMEM; + + while ((tok = strsep(&tmp, ",")) != NULL) { + char *dst; + bool neg = (*tok == '!'); + + if (*tok == '\0') { + trace_probe_log_err(tmp - b - 1, BAD_TP_NAME); + return -EINVAL; + + if (neg) + tok++; + dst = neg ? nf : f; + if (dst[0] != '\0') + strcat(dst, ","); + strcat(dst, tok); + } + *list_mode = true; + } + + *base = no_free_ptr(b); + *filter = no_free_ptr(f); + *nofilter = no_free_ptr(nf); + + return ret; }
static int trace_fprobe_create_internal(int argc, const char *argv[], @@ -1241,6 +1310,8 @@ static int trace_fprobe_create_internal(int argc, const char *argv[], const char *event = NULL, *group = FPROBE_EVENT_SYSTEM; struct module *mod __free(module_put) = NULL; const char **new_argv __free(kfree) = NULL; + char *parsed_nofilter __free(kfree) = NULL; + char *parsed_filter __free(kfree) = NULL; char *symbol __free(kfree) = NULL; char *ebuf __free(kfree) = NULL; char *gbuf __free(kfree) = NULL; @@ -1249,6 +1320,7 @@ static int trace_fprobe_create_internal(int argc, const char *argv[], char *dbuf __free(kfree) = NULL; int i, new_argc = 0, ret = 0; bool is_tracepoint = false; + bool list_mode = false; bool is_return = false;
if ((argv[0][0] != 'f' && argv[0][0] != 't') || argc < 2) @@ -1270,11 +1342,26 @@ static int trace_fprobe_create_internal(int argc, const char *argv[],
trace_probe_log_set_index(1);
- /* a symbol(or tracepoint) must be specified */ - ret = parse_symbol_and_return(argc, argv, &symbol, &is_return, is_tracepoint); + /* Parse spec early (single vs list, suffix, base symbol) */ + ret = parse_fprobe_spec(argv[1], is_tracepoint, &symbol, &is_return, + &list_mode, &parsed_filter, &parsed_nofilter); if (ret < 0) return -EINVAL;
+ for (i = 2; i < argc; i++) { + char *tmp = strstr(argv[i], "$retval"); + + if (tmp && !isalnum(tmp[7]) && tmp[7] != '_') { + if (is_tracepoint) { + trace_probe_log_set_index(i); + trace_probe_log_err(tmp - argv[i], RETVAL_ON_PROBE); + return -EINVAL; + } + is_return = true; + break; + } + } + trace_probe_log_set_index(0); if (event) { gbuf = kmalloc(MAX_EVENT_NAME_LEN, GFP_KERNEL); @@ -1287,6 +1374,15 @@ static int trace_fprobe_create_internal(int argc, const char *argv[], }
if (!event) { + /* + * Event name rules: + * - For list/wildcard: require explicit [GROUP/]EVENT + * - For single literal: autogenerate symbol__entry/symbol__exit + */ + if (list_mode || has_wildcard(symbol)) { + trace_probe_log_err(0, NO_GROUP_NAME); + return -EINVAL; + } ebuf = kmalloc(MAX_EVENT_NAME_LEN, GFP_KERNEL); if (!ebuf) return -ENOMEM; @@ -1322,7 +1418,8 @@ static int trace_fprobe_create_internal(int argc, const char *argv[], NULL, NULL, NULL, sbuf); } } - if (!ctx->funcname) + + if (!list_mode && !has_wildcard(symbol) && !is_tracepoint) ctx->funcname = symbol;
abuf = kmalloc(MAX_BTF_ARGS_LEN, GFP_KERNEL); @@ -1356,6 +1453,21 @@ static int trace_fprobe_create_internal(int argc, const char *argv[], return ret; }
+ /* carry list parsing result into tf */ + if (!is_tracepoint) { + tf->list_mode = list_mode; + if (parsed_filter) { + tf->filter = kstrdup(parsed_filter, GFP_KERNEL); + if (!tf->filter) + return -ENOMEM; + } + if (parsed_nofilter) { + tf->nofilter = kstrdup(parsed_nofilter, GFP_KERNEL); + if (!tf->nofilter) + return -ENOMEM; + } + } + /* parse arguments */ for (i = 0; i < argc; i++) { trace_probe_log_set_index(i + 2); @@ -1442,8 +1554,9 @@ static int trace_fprobe_show(struct seq_file *m, struct dyn_event *ev) seq_printf(m, ":%s/%s", trace_probe_group_name(&tf->tp), trace_probe_name(&tf->tp));
- seq_printf(m, " %s%s", trace_fprobe_symbol(tf), - trace_fprobe_is_return(tf) ? "%return" : ""); + seq_printf(m, " %s", trace_fprobe_symbol(tf)); + if (!trace_fprobe_is_tracepoint(tf) && trace_fprobe_is_return(tf)) + seq_puts(m, ":exit");
for (i = 0; i < tf->tp.nr_args; i++) seq_printf(m, " %s=%s", tf->tp.args[i].name, tf->tp.args[i].comm);
Signed-off-by: Seokwoo Chung (Ryan) seokwoo.chung130@gmail.com --- .../ftrace/test.d/dynevent/fprobe_list.tc | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 tools/testing/selftests/ftrace/test.d/dynevent/fprobe_list.tc
diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_list.tc b/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_list.tc new file mode 100644 index 000000000000..45e57c6f487d --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_list.tc @@ -0,0 +1,92 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Fprobe event list syntax and :entry/:exit suffixes +# requires: dynamic_events "f[:[<group>/][<event>]] <func-name>[:entry|:exit] [<args>]":README + +# Setup symbols to test. These are common kernel functions. +PLACE=vfs_read +PLACE2=vfs_write +PLACE3=vfs_open + +echo 0 > events/enable +echo > dynamic_events + +# Get baseline count of enabled functions (should be 0 if clean, but be safe) +if [ -f enabled_functions ]; then + ocnt=`cat enabled_functions | wc -l` +else + ocnt=0 +fi + +# Test 1: List default (entry) with exclusion +# Target: Trace vfs_read and vfs_open, but EXCLUDE vfs_write +echo "f:test/list_entry $PLACE,!$PLACE2,$PLACE3" >> dynamic_events +grep -q "test/list_entry" dynamic_events +test -d events/test/list_entry + +echo 1 > events/test/list_entry/enable + +grep -q "$PLACE" enabled_functions +grep -q "$PLACE3" enabled_functions +! grep -q "$PLACE2" enabled_functions + +# Check count (Baseline + 2 new functions) +cnt=`cat enabled_functions | wc -l` +if [ $cnt -ne $((ocnt + 2)) ]; then + exit_fail +fi + +# Cleanup Test 1 +echo 0 > events/test/list_entry/enable +echo "-:test/list_entry" >> dynamic_events +! grep -q "test/list_entry" dynamic_events + +# Count should return to baseline +cnt=`cat enabled_functions | wc -l` +if [ $cnt -ne $ocnt ]; then + exit_fail +fi + +# Test 2: List with explicit :entry suffix +# (Should behave exactly like Test 1) +echo "f:test/list_entry_exp $PLACE,!$PLACE2,$PLACE3:entry" >> dynamic_events +grep -q "test/list_entry_exp" dynamic_events +test -d events/test/list_entry_exp + +echo 1 > events/test/list_entry_exp/enable + +grep -q "$PLACE" enabled_functions +grep -q "$PLACE3" enabled_functions +! grep -q "$PLACE2" enabled_functions + +cnt=`cat enabled_functions | wc -l` +if [ $cnt -ne $((ocnt + 2)) ]; then + exit_fail +fi + +# Cleanup Test 2 +echo 0 > events/test/list_entry_exp/enable +echo "-:test/list_entry_exp" >> dynamic_events + +# Test 3: List with :exit suffix +echo "f:test/list_exit $PLACE,!$PLACE2,$PLACE3:exit" >> dynamic_events +grep -q "test/list_exit" dynamic_events +test -d events/test/list_exit + +echo 1 > events/test/list_exit/enable + +# Even for return probes, enabled_functions lists the attached symbols +grep -q "$PLACE" enabled_functions +grep -q "$PLACE3" enabled_functions +! grep -q "$PLACE2" enabled_functions + +cnt=`cat enabled_functions | wc -l` +if [ $cnt -ne $((ocnt + 2)) ]; then + exit_fail +fi + +# Cleanup Test 3 +echo 0 > events/test/list_exit/enable +echo "-:test/list_exit" >> dynamic_events + +clear_trace
On Wed, 26 Nov 2025 13:41:09 -0500 "Seokwoo Chung (Ryan)" seokwoo.chung130@gmail.com wrote:
- Update DEFINE_FREE to use standard __free()
- Extend fprobe to support multiple symbols per event. Add parsing logic for lists, ! exclusions, and explicit suffixes. Update tracefs/README to reflect the new syntax
Signed-off-by: Seokwoo Chung (Ryan) seokwoo.chung130@gmail.com
kernel/trace/trace.c | 3 +- kernel/trace/trace_fprobe.c | 209 +++++++++++++++++++++++++++--------- 2 files changed, 163 insertions(+), 49 deletions(-)
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index d1e527cf2aae..e0b77268a702 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -5518,7 +5518,8 @@ static const char readme_msg[] = "\t r[maxactive][:[<group>/][<event>]] <place> [<args>]\n" #endif #ifdef CONFIG_FPROBE_EVENTS
- "\t f[:[<group>/][<event>]] <func-name>[%return] [<args>]\n"
- "\t f[:[<group>/][<event>]] <func-name>[:entry|:exit] [<args>]\n"
- "\t (single symbols still accept %return)\n"
Hm, I would like to keep previous line. What about this (instead of adding a note line)?
"\t f[:[<group>/][<event>]] <func-name>[%return] [<args>]\n" "\t f[:[<group>/][<event>]] <func-list>[:entry|:exit] [<args>]\n"
This shows both syntax exists clearly, and the new one accepts a list of functions.
"\t t[:[<group>/][<event>]] <tracepoint> [<args>]\n" #endif #ifdef CONFIG_HIST_TRIGGERS diff --git a/kernel/trace/trace_fprobe.c b/kernel/trace/trace_fprobe.c index 8001dbf16891..6307d7d7dd9c 100644 --- a/kernel/trace/trace_fprobe.c +++ b/kernel/trace/trace_fprobe.c @@ -187,11 +187,14 @@ DEFINE_FREE(tuser_put, struct tracepoint_user *, */ struct trace_fprobe { struct dyn_event devent;
- char *filter;
Please do not sort the field alphabetically. It should be gathered by semantics.
struct fprobe fp;
- bool list_mode;
So filter should be here.
- char *nofilter; const char *symbol;
- struct trace_probe tp;
Actually trace_probe must be the last field, because it has a variable length array at the end.
bool tprobe; struct tracepoint_user *tuser;
- struct trace_probe tp;
}; static bool is_trace_fprobe(struct dyn_event *ev) @@ -559,6 +562,8 @@ static void free_trace_fprobe(struct trace_fprobe *tf) trace_probe_cleanup(&tf->tp); if (tf->tuser) tracepoint_user_put(tf->tuser);
kfree(tf->filter); kfree(tf->symbol); kfree(tf); }kfree(tf->nofilter);@@ -838,7 +843,12 @@ static int __register_trace_fprobe(struct trace_fprobe *tf) if (trace_fprobe_is_tracepoint(tf)) return __regsiter_tracepoint_fprobe(tf);
- /* TODO: handle filter, nofilter or symbol list */
- /* Registration path:
* - list_mode: pass filter/nofilter* - single: pass symbol only (legacy)*/- if (tf->list_mode)
If tf have filter or nofilter, that means it is list_mode, right?
if (tf->filter || tf->nofilter)
is more straight.
I think you can add
static bool trace_fprobe_has_list(struct trace_fprobe *tf) { return tf->filter || tf->nofilter; }
then we don't need tf::list_mode.
return register_fprobe(&tf->fp, tf->symbol, NULL);return register_fprobe(&tf->fp, tf->filter, tf->nofilter);} @@ -1154,60 +1164,119 @@ static struct notifier_block tprobe_event_module_nb = { }; #endif /* CONFIG_MODULES */ -static int parse_symbol_and_return(int argc, const char *argv[],
char **symbol, bool *is_return,bool is_tracepoint)+static bool has_wildcard(const char *s) {
- char *tmp = strchr(argv[1], '%');
- int i;
- return s && (strchr(s, '*') || strchr(s, '?'));
+}
- if (tmp) {
int len = tmp - argv[1];+static int parse_fprobe_spec(const char *in, bool is_tracepoint,
char **base, bool *is_return, bool *list_mode,char **filter, char **nofilter)+{
- char *work __free(kfree) = NULL;
- char *b __free(kfree) = NULL;
- char *f __free(kfree) = NULL;
- char *nf __free(kfree) = NULL;
- bool legacy_ret = false;
- bool list = false;
- const char *p;
- int ret = 0;
if (!is_tracepoint && !strcmp(tmp, "%return")) {*is_return = true;} else {trace_probe_log_err(len, BAD_ADDR_SUFFIX);return -EINVAL;}*symbol = kmemdup_nul(argv[1], len, GFP_KERNEL);- } else
*symbol = kstrdup(argv[1], GFP_KERNEL);- if (!*symbol)
return -ENOMEM;
- if (!in || !base || !is_return || !list_mode || !filter || !nofilter)
return -EINVAL;
- if (*is_return)
return 0;
- *base = NULL; *filter = NULL; *nofilter = NULL;
- *is_return = false; *list_mode = false;
if (is_tracepoint) {
tmp = *symbol;while (*tmp && (isalnum(*tmp) || *tmp == '_'))tmp++;if (*tmp) {/* find a wrong character. */trace_probe_log_err(tmp - *symbol, BAD_TP_NAME);kfree(*symbol);*symbol = NULL;
if (strchr(in, ',') || strchr(in, ':')) return -EINVAL;
}
if (strstr(in, "%return"))return -EINVAL;
Please report some error before returning !ENOMEM error by trace_probe_log_err().
for (p = in; *p; p++)if (!isalnum(*p) && *p != '_')return -EINVAL;b = kstrdup(in, GFP_KERNEL);if (!b)return -ENOMEM;*base = no_free_ptr(b); }return 0;
- /* If there is $retval, this should be a return fprobe. */
- for (i = 2; i < argc; i++) {
tmp = strstr(argv[i], "$retval");if (tmp && !isalnum(tmp[7]) && tmp[7] != '_') {if (is_tracepoint) {trace_probe_log_set_index(i);trace_probe_log_err(tmp - argv[i], RETVAL_ON_PROBE);kfree(*symbol);*symbol = NULL;
- work = kstrdup(in, GFP_KERNEL);
- if (!work)
return -ENOMEM;- p = strstr(work, "%return");
- if (p && p[7] == '\0') {
*is_return = true;legacy_ret = true;*(char *)p = '\0';- } else {
/** If "symbol:entry" or "symbol:exit" is given, it is new* style probe.*/p = strrchr(work, ':');if (p) {if (!strcmp(p, ":exit")) {*is_return = true;*(char *)p = '\0';} else if (!strcmp(p, ":entry")) {*(char *)p = '\0';} else {
trace_probe_log_err(p - work, BAD_LIST_SUFFIX);
return -EINVAL; }
*is_return = true; } }break;- return 0;
- list = !!strchr(work, ',');
- if (list && legacy_ret) {
trace_probe_log_err(<legacy_ret offset>, BAD_LEGACY_RET);
return -EINVAL;- }
Or, you don't need this brace for 1 line if block.
- if (legacy_ret)
*is_return = true;
You've already done this for legacy_ret.
- b = kstrdup(work, GFP_KERNEL);
- if (!b)
return -ENOMEM;- if (list) {
char *tmp = b, *tok;size_t fsz, nfsz;fsz = nfsz = strlen(b) + 1;
fsz and nfsz are used only once. Can be replaced with "strlen(b) + 1".
f = kzalloc(fsz, GFP_KERNEL);nf = kzalloc(nfsz, GFP_KERNEL);if (!f || !nf)return -ENOMEM;while ((tok = strsep(&tmp, ",")) != NULL) {char *dst;bool neg = (*tok == '!');if (*tok == '\0') {trace_probe_log_err(tmp - b - 1, BAD_TP_NAME);return -EINVAL;
Forgot a closing brace here. (did you build and test it?)
if (neg)tok++;dst = neg ? nf : f;if (dst[0] != '\0')strcat(dst, ",");strcat(dst, tok);}*list_mode = true;- }
- *base = no_free_ptr(b);
- *filter = no_free_ptr(f);
- *nofilter = no_free_ptr(nf);
- return ret;
} static int trace_fprobe_create_internal(int argc, const char *argv[], @@ -1241,6 +1310,8 @@ static int trace_fprobe_create_internal(int argc, const char *argv[], const char *event = NULL, *group = FPROBE_EVENT_SYSTEM; struct module *mod __free(module_put) = NULL; const char **new_argv __free(kfree) = NULL;
- char *parsed_nofilter __free(kfree) = NULL;
- char *parsed_filter __free(kfree) = NULL; char *symbol __free(kfree) = NULL; char *ebuf __free(kfree) = NULL; char *gbuf __free(kfree) = NULL;
@@ -1249,6 +1320,7 @@ static int trace_fprobe_create_internal(int argc, const char *argv[], char *dbuf __free(kfree) = NULL; int i, new_argc = 0, ret = 0; bool is_tracepoint = false;
- bool list_mode = false; bool is_return = false;
if ((argv[0][0] != 'f' && argv[0][0] != 't') || argc < 2) @@ -1270,11 +1342,26 @@ static int trace_fprobe_create_internal(int argc, const char *argv[], trace_probe_log_set_index(1);
- /* a symbol(or tracepoint) must be specified */
- ret = parse_symbol_and_return(argc, argv, &symbol, &is_return, is_tracepoint);
- /* Parse spec early (single vs list, suffix, base symbol) */
- ret = parse_fprobe_spec(argv[1], is_tracepoint, &symbol, &is_return,
if (ret < 0) return -EINVAL;&list_mode, &parsed_filter, &parsed_nofilter);
- for (i = 2; i < argc; i++) {
char *tmp = strstr(argv[i], "$retval");if (tmp && !isalnum(tmp[7]) && tmp[7] != '_') {if (is_tracepoint) {trace_probe_log_set_index(i);trace_probe_log_err(tmp - argv[i], RETVAL_ON_PROBE);return -EINVAL;}is_return = true;break;}- }
- trace_probe_log_set_index(0); if (event) { gbuf = kmalloc(MAX_EVENT_NAME_LEN, GFP_KERNEL);
@@ -1287,6 +1374,15 @@ static int trace_fprobe_create_internal(int argc, const char *argv[], } if (!event) {
/** Event name rules:* - For list/wildcard: require explicit [GROUP/]EVENT* - For single literal: autogenerate symbol__entry/symbol__exit*/if (list_mode || has_wildcard(symbol)) {trace_probe_log_err(0, NO_GROUP_NAME);return -EINVAL; ebuf = kmalloc(MAX_EVENT_NAME_LEN, GFP_KERNEL); if (!ebuf) return -ENOMEM;}@@ -1322,7 +1418,8 @@ static int trace_fprobe_create_internal(int argc, const char *argv[], NULL, NULL, NULL, sbuf); } }
- if (!ctx->funcname)
- if (!list_mode && !has_wildcard(symbol) && !is_tracepoint) ctx->funcname = symbol;
abuf = kmalloc(MAX_BTF_ARGS_LEN, GFP_KERNEL); @@ -1356,6 +1453,21 @@ static int trace_fprobe_create_internal(int argc, const char *argv[], return ret; }
- /* carry list parsing result into tf */
- if (!is_tracepoint) {
tf->list_mode = list_mode;if (parsed_filter) {tf->filter = kstrdup(parsed_filter, GFP_KERNEL);if (!tf->filter)return -ENOMEM;}
You can just move it.
tf->filter = no_free_ptr(parsed_filter);
if (parsed_nofilter) {tf->nofilter = kstrdup(parsed_nofilter, GFP_KERNEL);if (!tf->nofilter)return -ENOMEM;}
Ditto.
- }
- /* parse arguments */ for (i = 0; i < argc; i++) { trace_probe_log_set_index(i + 2);
@@ -1442,8 +1554,9 @@ static int trace_fprobe_show(struct seq_file *m, struct dyn_event *ev) seq_printf(m, ":%s/%s", trace_probe_group_name(&tf->tp), trace_probe_name(&tf->tp));
- seq_printf(m, " %s%s", trace_fprobe_symbol(tf),
trace_fprobe_is_return(tf) ? "%return" : "");
- seq_printf(m, " %s", trace_fprobe_symbol(tf));
- if (!trace_fprobe_is_tracepoint(tf) && trace_fprobe_is_return(tf))
seq_puts(m, ":exit");for (i = 0; i < tf->tp.nr_args; i++) seq_printf(m, " %s=%s", tf->tp.args[i].name, tf->tp.args[i].comm); -- 2.43.0
Please build and run ftracetest under tools/testing/selftests.
Thank you,
On Wed, 26 Nov 2025 13:41:07 -0500 "Seokwoo Chung (Ryan)" seokwoo.chung130@gmail.com wrote:
Extend fprobe to support list-style filters and explicit entry/exit suffixes. Currentyl, fprobe only supports a single symbol (or wildcard) per event. This patch allows users to specify a comma-separated list of symbols.
New Syntax:
- f:[GRP/][EVENT] func1,func2,func3:entry
- f:[GRP/][EVENT] func1,func2,func3:exit
Thanks for updating!
Logic changes:
- Refactor parsing logic into 'parse_fprobe_spec'
- Support '!' prefix for exclusion
- Disable BTF lookup ('ctx->funcname = NULL') when a list or wildcard is used, as a single function signature cannot apply to multiple functions.
- Reject legacy '%return' suffix when used with lists or wildcards
- Update tracefs/README
Testing: Verified on x86_64 via QEMU. Checked registration of lists, exclusions, and explicit suffixes. Verified rejection of invalid syntax including trailing commas and mixed legacy/new syntax.
Seokwoo Chung (Ryan) (3): docs: tracing/fprobe: Document list filters and :entry/:exit tracing/fprobe: Support comma-separated symbols and :entry/:exit
For the next time, please add docs patch after code change because of bisect. (Or, include the document update into code update.)
selftests/ftrace: Add accept cases for fprobe list syntax
Testing after code is good. :)
Thank you,
Changes in v4:
- Added validation to reject trailing commas (empty tokens) in symbol lists
- Added vaildation to reject mixed of list syntax with %return suffix
- Refactored parse_fprobe_spec to user __free(kfree) for automatic memory cleanup
- Removed the now-unused parse_symbol_and_return function to avoid compiler warnings.
- Tigtened %return detection to ensure it only matches as a strict suffix, not a substring
- Link to v3: https://lore.kernel.org/lkml/20250904103219.f4937968362bfff1ecd3f004@kernel....
Documentation/trace/fprobetrace.rst | 17 +- kernel/trace/trace.c | 3 +- kernel/trace/trace_fprobe.c | 209 ++++++++++++++---- .../ftrace/test.d/dynevent/fprobe_list.tc | 92 ++++++++ 4 files changed, 269 insertions(+), 52 deletions(-) create mode 100644 tools/testing/selftests/ftrace/test.d/dynevent/fprobe_list.tc
-- 2.43.0
Hi Seokwoo,
kernel test robot noticed the following build warnings:
[auto build test WARNING on trace/for-next] [also build test WARNING on linus/master v6.18-rc7 next-20251127] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Seokwoo-Chung-Ryan/docs-traci... base: https://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace for-next patch link: https://lore.kernel.org/r/20251126184110.72241-3-seokwoo.chung130%40gmail.co... patch subject: [PATCH v4 2/3] tracing/fprobe: Support comma-separated symbols and :entry/:exit config: x86_64-randconfig-003-20251127 (https://download.01.org/0day-ci/archive/20251127/202511271925.xuaUx8bB-lkp@i...) compiler: gcc-14 (Debian 14.2.0-19) 14.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251127/202511271925.xuaUx8bB-lkp@i...)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot lkp@intel.com | Closes: https://lore.kernel.org/oe-kbuild-all/202511271925.xuaUx8bB-lkp@intel.com/
All warnings (new ones prefixed by >>):
kernel/trace/trace_fprobe.c: In function 'parse_fprobe_spec': kernel/trace/trace_fprobe.c:1282:12: error: invalid storage class for function 'trace_fprobe_create_internal' 1282 | static int trace_fprobe_create_internal(int argc, const char *argv[], | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ kernel/trace/trace_fprobe.c:1513:12: error: invalid storage class for function 'trace_fprobe_create_cb' 1513 | static int trace_fprobe_create_cb(int argc, const char *argv[]) | ^~~~~~~~~~~~~~~~~~~~~~ kernel/trace/trace_fprobe.c:1530:12: error: invalid storage class for function 'trace_fprobe_create' 1530 | static int trace_fprobe_create(const char *raw_command) | ^~~~~~~~~~~~~~~~~~~ kernel/trace/trace_fprobe.c:1535:12: error: invalid storage class for function 'trace_fprobe_release' 1535 | static int trace_fprobe_release(struct dyn_event *ev) | ^~~~~~~~~~~~~~~~~~~~ kernel/trace/trace_fprobe.c:1545:12: error: invalid storage class for function 'trace_fprobe_show' 1545 | static int trace_fprobe_show(struct seq_file *m, struct dyn_event *ev) | ^~~~~~~~~~~~~~~~~ kernel/trace/trace_fprobe.c:1572:12: error: invalid storage class for function 'enable_trace_fprobe' 1572 | static int enable_trace_fprobe(struct trace_event_call *call, | ^~~~~~~~~~~~~~~~~~~ kernel/trace/trace_fprobe.c:1608:12: error: invalid storage class for function 'disable_trace_fprobe' 1608 | static int disable_trace_fprobe(struct trace_event_call *call, | ^~~~~~~~~~~~~~~~~~~~ kernel/trace/trace_fprobe.c:1653:12: error: invalid storage class for function 'fprobe_register' 1653 | static int fprobe_register(struct trace_event_call *event, | ^~~~~~~~~~~~~~~ kernel/trace/trace_fprobe.c:1683:19: error: invalid storage class for function 'init_fprobe_trace_early' 1683 | static __init int init_fprobe_trace_early(void) | ^~~~~~~~~~~~~~~~~~~~~~~ In file included from include/linux/fprobe.h:6, from kernel/trace/trace_fprobe.c:8: include/linux/compiler.h:286:52: error: initializer element is not constant 286 | __UNIQUE_ID(__PASTE(__addressable_,sym)) = (void *)(uintptr_t)&sym; | ^ include/linux/compiler.h:289:9: note: in expansion of macro '___ADDRESSABLE' 289 | ___ADDRESSABLE(sym, __section(".discard.addressable")) | ^~~~~~~~~~~~~~ include/linux/init.h:250:9: note: in expansion of macro '__ADDRESSABLE' 250 | __ADDRESSABLE(fn) | ^~~~~~~~~~~~~ include/linux/init.h:255:9: note: in expansion of macro '__define_initcall_stub' 255 | __define_initcall_stub(__stub, fn) \ | ^~~~~~~~~~~~~~~~~~~~~~ include/linux/init.h:268:9: note: in expansion of macro '____define_initcall' 268 | ____define_initcall(fn, \ | ^~~~~~~~~~~~~~~~~~~ include/linux/init.h:274:9: note: in expansion of macro '__unique_initcall' 274 | __unique_initcall(fn, id, __sec, __initcall_id(fn)) | ^~~~~~~~~~~~~~~~~ include/linux/init.h:276:35: note: in expansion of macro '___define_initcall' 276 | #define __define_initcall(fn, id) ___define_initcall(fn, id, .initcall##id) | ^~~~~~~~~~~~~~~~~~ include/linux/init.h:294:41: note: in expansion of macro '__define_initcall' 294 | #define core_initcall(fn) __define_initcall(fn, 1) | ^~~~~~~~~~~~~~~~~ kernel/trace/trace_fprobe.c:1702:1: note: in expansion of macro 'core_initcall' 1702 | core_initcall(init_fprobe_trace_early); | ^~~~~~~~~~~~~ kernel/trace/trace_fprobe.c:1702:1: error: expected declaration or statement at end of input kernel/trace/trace_fprobe.c: At top level:
kernel/trace/trace_fprobe.c:28:12: warning: 'trace_fprobe_create' used but never defined
28 | static int trace_fprobe_create(const char *raw_command); | ^~~~~~~~~~~~~~~~~~~
kernel/trace/trace_fprobe.c:29:12: warning: 'trace_fprobe_show' used but never defined
29 | static int trace_fprobe_show(struct seq_file *m, struct dyn_event *ev); | ^~~~~~~~~~~~~~~~~
kernel/trace/trace_fprobe.c:30:12: warning: 'trace_fprobe_release' used but never defined
30 | static int trace_fprobe_release(struct dyn_event *ev); | ^~~~~~~~~~~~~~~~~~~~
kernel/trace/trace_fprobe.c:741:12: warning: 'fprobe_register' used but never defined
741 | static int fprobe_register(struct trace_event_call *event, | ^~~~~~~~~~~~~~~
kernel/trace/trace_fprobe.c:1653:12: warning: 'fprobe_register' defined but not used [-Wunused-function]
1653 | static int fprobe_register(struct trace_event_call *event, | ^~~~~~~~~~~~~~~
kernel/trace/trace_fprobe.c:1545:12: warning: 'trace_fprobe_show' defined but not used [-Wunused-function]
1545 | static int trace_fprobe_show(struct seq_file *m, struct dyn_event *ev) | ^~~~~~~~~~~~~~~~~
kernel/trace/trace_fprobe.c:1535:12: warning: 'trace_fprobe_release' defined but not used [-Wunused-function]
1535 | static int trace_fprobe_release(struct dyn_event *ev) | ^~~~~~~~~~~~~~~~~~~~
kernel/trace/trace_fprobe.c:1530:12: warning: 'trace_fprobe_create' defined but not used [-Wunused-function]
1530 | static int trace_fprobe_create(const char *raw_command) | ^~~~~~~~~~~~~~~~~~~
vim +/trace_fprobe_create +28 kernel/trace/trace_fprobe.c
334e5519c37570 Masami Hiramatsu (Google 2023-06-06 27) 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 @28) static int trace_fprobe_create(const char *raw_command); 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 @29) static int trace_fprobe_show(struct seq_file *m, struct dyn_event *ev); 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 @30) static int trace_fprobe_release(struct dyn_event *ev); 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 31) static bool trace_fprobe_is_busy(struct dyn_event *ev); 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 32) static bool trace_fprobe_match(const char *system, const char *event, 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 33) int argc, const char **argv, struct dyn_event *ev); 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 34)
Hi Seokwoo,
kernel test robot noticed the following build errors:
[auto build test ERROR on trace/for-next] [also build test ERROR on linus/master v6.18-rc7 next-20251127] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Seokwoo-Chung-Ryan/docs-traci... base: https://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace for-next patch link: https://lore.kernel.org/r/20251126184110.72241-3-seokwoo.chung130%40gmail.co... patch subject: [PATCH v4 2/3] tracing/fprobe: Support comma-separated symbols and :entry/:exit config: x86_64-randconfig-001-20251127 (https://download.01.org/0day-ci/archive/20251127/202511272254.BX8oUzwu-lkp@i...) compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251127/202511272254.BX8oUzwu-lkp@i...)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot lkp@intel.com | Closes: https://lore.kernel.org/oe-kbuild-all/202511272254.BX8oUzwu-lkp@intel.com/
All errors (new ones prefixed by >>):
kernel/trace/trace_fprobe.c:1284:1: error: function definition is not allowed here
1284 | { | ^ kernel/trace/trace_fprobe.c:1514:1: error: function definition is not allowed here 1514 | { | ^ kernel/trace/trace_fprobe.c:1531:1: error: function definition is not allowed here 1531 | { | ^ kernel/trace/trace_fprobe.c:1536:1: error: function definition is not allowed here 1536 | { | ^ kernel/trace/trace_fprobe.c:1546:1: error: function definition is not allowed here 1546 | { | ^ kernel/trace/trace_fprobe.c:1574:1: error: function definition is not allowed here 1574 | { | ^ kernel/trace/trace_fprobe.c:1610:1: error: function definition is not allowed here 1610 | { | ^ kernel/trace/trace_fprobe.c:1655:1: error: function definition is not allowed here 1655 | { | ^ kernel/trace/trace_fprobe.c:1684:1: error: function definition is not allowed here 1684 | { | ^
kernel/trace/trace_fprobe.c:1702:15: error: use of undeclared identifier 'init_fprobe_trace_early'
1702 | core_initcall(init_fprobe_trace_early); | ^
kernel/trace/trace_fprobe.c:1702:15: error: use of undeclared identifier 'init_fprobe_trace_early' kernel/trace/trace_fprobe.c:1702:40: error: expected '}'
1702 | core_initcall(init_fprobe_trace_early); | ^ kernel/trace/trace_fprobe.c:1175:1: note: to match this '{' 1175 | { | ^ 12 errors generated.
vim +1284 kernel/trace/trace_fprobe.c
08c9306fc2e32b Masami Hiramatsu (Google 2023-08-23 1281) 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1282) static int trace_fprobe_create_internal(int argc, const char *argv[], 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1283) struct traceprobe_parse_context *ctx) 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 @1284) { 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1285) /* 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1286) * Argument syntax: 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1287) * - Add fentry probe: 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1288) * f[:[GRP/][EVENT]] [MOD:]KSYM [FETCHARGS] 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1289) * - Add fexit probe: 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1290) * f[N][:[GRP/][EVENT]] [MOD:]KSYM%return [FETCHARGS] e2d0d7b2f42dca Masami Hiramatsu (Google 2023-06-06 1291) * - Add tracepoint probe: e2d0d7b2f42dca Masami Hiramatsu (Google 2023-06-06 1292) * t[:[GRP/][EVENT]] TRACEPOINT [FETCHARGS] 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1293) * 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1294) * Fetch args: 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1295) * $retval : fetch return value 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1296) * $stack : fetch stack address 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1297) * $stackN : fetch Nth entry of stack (N:0-) 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1298) * $argN : fetch Nth argument (N:1-) 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1299) * $comm : fetch current task comm 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1300) * @ADDR : fetch memory at ADDR (ADDR should be in kernel) 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1301) * @SYM[+|-offs] : fetch memory at SYM +|- offs (SYM is a data symbol) 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1302) * Dereferencing memory fetch: 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1303) * +|-offs(ARG) : fetch memory at ARG +|- offs address. 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1304) * Alias name of args: 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1305) * NAME=FETCHARG : set NAME as alias of FETCHARG. 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1306) * Type of args: 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1307) * FETCHARG:TYPE : use TYPE instead of unsigned long. 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1308) */ 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1309) struct trace_fprobe *tf __free(free_trace_fprobe) = NULL; 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1310) const char *event = NULL, *group = FPROBE_EVENT_SYSTEM; d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1311) struct module *mod __free(module_put) = NULL; 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1312) const char **new_argv __free(kfree) = NULL; a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1313) char *parsed_nofilter __free(kfree) = NULL; a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1314) char *parsed_filter __free(kfree) = NULL; d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1315) char *symbol __free(kfree) = NULL; d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1316) char *ebuf __free(kfree) = NULL; d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1317) char *gbuf __free(kfree) = NULL; d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1318) char *sbuf __free(kfree) = NULL; d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1319) char *abuf __free(kfree) = NULL; 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1320) char *dbuf __free(kfree) = NULL; d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1321) int i, new_argc = 0, ret = 0; e2d0d7b2f42dca Masami Hiramatsu (Google 2023-06-06 1322) bool is_tracepoint = false; a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1323) bool list_mode = false; d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1324) bool is_return = false; 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1325) e2d0d7b2f42dca Masami Hiramatsu (Google 2023-06-06 1326) if ((argv[0][0] != 'f' && argv[0][0] != 't') || argc < 2) 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1327) return -ECANCELED; 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1328) e2d0d7b2f42dca Masami Hiramatsu (Google 2023-06-06 1329) if (argv[0][0] == 't') { e2d0d7b2f42dca Masami Hiramatsu (Google 2023-06-06 1330) is_tracepoint = true; e2d0d7b2f42dca Masami Hiramatsu (Google 2023-06-06 1331) group = TRACEPOINT_EVENT_SYSTEM; e2d0d7b2f42dca Masami Hiramatsu (Google 2023-06-06 1332) } e2d0d7b2f42dca Masami Hiramatsu (Google 2023-06-06 1333) a2224559cbba1d Masami Hiramatsu (Google 2024-12-26 1334) if (argv[0][1] != '\0') { a2224559cbba1d Masami Hiramatsu (Google 2024-12-26 1335) if (argv[0][1] != ':') { a2224559cbba1d Masami Hiramatsu (Google 2024-12-26 1336) trace_probe_log_set_index(0); 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1337) trace_probe_log_err(1, BAD_MAXACT); 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1338) return -EINVAL; 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1339) } a2224559cbba1d Masami Hiramatsu (Google 2024-12-26 1340) event = &argv[0][2]; 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1341) } 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1342) 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1343) trace_probe_log_set_index(1); 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1344) a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1345) /* Parse spec early (single vs list, suffix, base symbol) */ a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1346) ret = parse_fprobe_spec(argv[1], is_tracepoint, &symbol, &is_return, a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1347) &list_mode, &parsed_filter, &parsed_nofilter); 08c9306fc2e32b Masami Hiramatsu (Google 2023-08-23 1348) if (ret < 0) 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1349) return -EINVAL; 08c9306fc2e32b Masami Hiramatsu (Google 2023-08-23 1350) a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1351) for (i = 2; i < argc; i++) { a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1352) char *tmp = strstr(argv[i], "$retval"); a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1353) a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1354) if (tmp && !isalnum(tmp[7]) && tmp[7] != '_') { a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1355) if (is_tracepoint) { a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1356) trace_probe_log_set_index(i); a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1357) trace_probe_log_err(tmp - argv[i], RETVAL_ON_PROBE); a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1358) return -EINVAL; a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1359) } a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1360) is_return = true; a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1361) break; a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1362) } a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1363) } a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1364) 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1365) trace_probe_log_set_index(0); 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1366) if (event) { d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1367) gbuf = kmalloc(MAX_EVENT_NAME_LEN, GFP_KERNEL); d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1368) if (!gbuf) d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1369) return -ENOMEM; 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1370) ret = traceprobe_parse_event_name(&event, &group, gbuf, 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1371) event - argv[0]); 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1372) if (ret) 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1373) return -EINVAL; 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1374) } 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1375) 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1376) if (!event) { a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1377) /* a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1378) * Event name rules: a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1379) * - For list/wildcard: require explicit [GROUP/]EVENT a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1380) * - For single literal: autogenerate symbol__entry/symbol__exit a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1381) */ a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1382) if (list_mode || has_wildcard(symbol)) { a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1383) trace_probe_log_err(0, NO_GROUP_NAME); a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1384) return -EINVAL; a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1385) } d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1386) ebuf = kmalloc(MAX_EVENT_NAME_LEN, GFP_KERNEL); d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1387) if (!ebuf) d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1388) return -ENOMEM; 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1389) /* Make a new event name */ e2d0d7b2f42dca Masami Hiramatsu (Google 2023-06-06 1390) if (is_tracepoint) d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1391) snprintf(ebuf, MAX_EVENT_NAME_LEN, "%s%s", b576e09701c7d0 Masami Hiramatsu (Google 2023-06-06 1392) isdigit(*symbol) ? "_" : "", symbol); e2d0d7b2f42dca Masami Hiramatsu (Google 2023-06-06 1393) else d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1394) snprintf(ebuf, MAX_EVENT_NAME_LEN, "%s__%s", symbol, 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1395) is_return ? "exit" : "entry"); d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1396) sanitize_event_name(ebuf); d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1397) event = ebuf; 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1398) } 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1399) b576e09701c7d0 Masami Hiramatsu (Google 2023-06-06 1400) if (is_return) 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1401) ctx->flags |= TPARG_FL_RETURN; b576e09701c7d0 Masami Hiramatsu (Google 2023-06-06 1402) else 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1403) ctx->flags |= TPARG_FL_FENTRY; b576e09701c7d0 Masami Hiramatsu (Google 2023-06-06 1404) 2867495dea8632 Masami Hiramatsu (Google 2025-04-01 1405) ctx->funcname = NULL; b576e09701c7d0 Masami Hiramatsu (Google 2023-06-06 1406) if (is_tracepoint) { 2867495dea8632 Masami Hiramatsu (Google 2025-04-01 1407) /* Get tracepoint and lock its module until the end of the registration. */ 2867495dea8632 Masami Hiramatsu (Google 2025-04-01 1408) struct tracepoint *tpoint; 2867495dea8632 Masami Hiramatsu (Google 2025-04-01 1409) 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1410) ctx->flags |= TPARG_FL_TPOINT; 2867495dea8632 Masami Hiramatsu (Google 2025-04-01 1411) mod = NULL; 2867495dea8632 Masami Hiramatsu (Google 2025-04-01 1412) tpoint = find_tracepoint(symbol, &mod); d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1413) if (tpoint) { d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1414) sbuf = kmalloc(KSYM_NAME_LEN, GFP_KERNEL); d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1415) if (!sbuf) d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1416) return -ENOMEM; 2867495dea8632 Masami Hiramatsu (Google 2025-04-01 1417) ctx->funcname = kallsyms_lookup((unsigned long)tpoint->probestub, 2867495dea8632 Masami Hiramatsu (Google 2025-04-01 1418) NULL, NULL, NULL, sbuf); b576e09701c7d0 Masami Hiramatsu (Google 2023-06-06 1419) } d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1420) } a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1421) a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1422) if (!list_mode && !has_wildcard(symbol) && !is_tracepoint) e3d6e1b9a34c74 Masami Hiramatsu (Google 2025-04-01 1423) ctx->funcname = symbol; b576e09701c7d0 Masami Hiramatsu (Google 2023-06-06 1424) d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1425) abuf = kmalloc(MAX_BTF_ARGS_LEN, GFP_KERNEL); d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1426) if (!abuf) d643eaa7082dc3 Masami Hiramatsu (Google 2025-07-23 1427) return -ENOMEM; 18b1e870a49671 Masami Hiramatsu (Google 2023-06-06 1428) argc -= 2; argv += 2; 18b1e870a49671 Masami Hiramatsu (Google 2023-06-06 1429) new_argv = traceprobe_expand_meta_args(argc, argv, &new_argc, 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1430) abuf, MAX_BTF_ARGS_LEN, ctx); 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1431) if (IS_ERR(new_argv)) 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1432) return PTR_ERR(new_argv); 18b1e870a49671 Masami Hiramatsu (Google 2023-06-06 1433) if (new_argv) { 18b1e870a49671 Masami Hiramatsu (Google 2023-06-06 1434) argc = new_argc; 18b1e870a49671 Masami Hiramatsu (Google 2023-06-06 1435) argv = new_argv; 18b1e870a49671 Masami Hiramatsu (Google 2023-06-06 1436) } 57faaa04804ccb Masami Hiramatsu (Google 2025-03-27 1437) if (argc > MAX_TRACE_ARGS) { 57faaa04804ccb Masami Hiramatsu (Google 2025-03-27 1438) trace_probe_log_set_index(2); 57faaa04804ccb Masami Hiramatsu (Google 2025-03-27 1439) trace_probe_log_err(0, TOO_MANY_ARGS); 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1440) return -E2BIG; 57faaa04804ccb Masami Hiramatsu (Google 2025-03-27 1441) } 18b1e870a49671 Masami Hiramatsu (Google 2023-06-06 1442) d9b15224dd8ff8 Ye Bin 2024-03-22 1443 ret = traceprobe_expand_dentry_args(argc, argv, &dbuf); d9b15224dd8ff8 Ye Bin 2024-03-22 1444 if (ret) 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1445) return ret; d9b15224dd8ff8 Ye Bin 2024-03-22 1446 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1447) /* setup a probe */ 2867495dea8632 Masami Hiramatsu (Google 2025-04-01 1448) tf = alloc_trace_fprobe(group, event, symbol, argc, is_return, is_tracepoint); 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1449) if (IS_ERR(tf)) { 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1450) ret = PTR_ERR(tf); 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1451) /* This must return -ENOMEM, else there is a bug */ 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1452) WARN_ON_ONCE(ret != -ENOMEM); 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1453) return ret; 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1454) } e2d0d7b2f42dca Masami Hiramatsu (Google 2023-06-06 1455) a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1456) /* carry list parsing result into tf */ a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1457) if (!is_tracepoint) { a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1458) tf->list_mode = list_mode; a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1459) if (parsed_filter) { a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1460) tf->filter = kstrdup(parsed_filter, GFP_KERNEL); a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1461) if (!tf->filter) a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1462) return -ENOMEM; a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1463) } a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1464) if (parsed_nofilter) { a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1465) tf->nofilter = kstrdup(parsed_nofilter, GFP_KERNEL); a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1466) if (!tf->nofilter) a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1467) return -ENOMEM; a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1468) } a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1469) } a90d508c939bee Seokwoo Chung (Ryan 2025-11-26 1470) 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1471) /* parse arguments */ 73f35080477e89 Mikel Rychliski 2024-09-30 1472 for (i = 0; i < argc; i++) { 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1473) trace_probe_log_set_index(i + 2); 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1474) ctx->offset = 0; 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1475) ret = traceprobe_parse_probe_arg(&tf->tp, i, argv[i], ctx); 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1476) if (ret) 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1477) return ret; /* This can be -ENOMEM */ 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1478) } 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1479) 25f00e40ce7953 Masami Hiramatsu (Google 2024-03-04 1480) if (is_return && tf->tp.entry_arg) { 25f00e40ce7953 Masami Hiramatsu (Google 2024-03-04 1481) tf->fp.entry_handler = trace_fprobe_entry_handler; 25f00e40ce7953 Masami Hiramatsu (Google 2024-03-04 1482) tf->fp.entry_data_size = traceprobe_get_entry_data_size(&tf->tp); db5e228611b118 Masami Hiramatsu (Google 2025-02-26 1483) if (ALIGN(tf->fp.entry_data_size, sizeof(long)) > MAX_FPROBE_DATA_SIZE) { db5e228611b118 Masami Hiramatsu (Google 2025-02-26 1484) trace_probe_log_set_index(2); db5e228611b118 Masami Hiramatsu (Google 2025-02-26 1485) trace_probe_log_err(0, TOO_MANY_EARGS); db5e228611b118 Masami Hiramatsu (Google 2025-02-26 1486) return -E2BIG; db5e228611b118 Masami Hiramatsu (Google 2025-02-26 1487) } 25f00e40ce7953 Masami Hiramatsu (Google 2024-03-04 1488) } 25f00e40ce7953 Masami Hiramatsu (Google 2024-03-04 1489) 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1490) ret = traceprobe_set_print_fmt(&tf->tp, 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1491) is_return ? PROBE_PRINT_RETURN : PROBE_PRINT_NORMAL); 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1492) if (ret < 0) 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1493) return ret; 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1494) 2db832ec9090d3 Masami Hiramatsu (Google 2025-04-01 1495) ret = register_trace_fprobe_event(tf); 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1496) if (ret) { 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1497) trace_probe_log_set_index(1); 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1498) if (ret == -EILSEQ) 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1499) trace_probe_log_err(0, BAD_INSN_BNDRY); 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1500) else if (ret == -ENOENT) 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1501) trace_probe_log_err(0, BAD_PROBE_ADDR); 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1502) else if (ret != -ENOMEM && ret != -EEXIST) 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1503) trace_probe_log_err(0, FAIL_REG_PROBE); 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1504) return -EINVAL; 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1505) } 334e5519c37570 Masami Hiramatsu (Google 2023-06-06 1506) 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1507) /* 'tf' is successfully registered. To avoid freeing, assign NULL. */ 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1508) tf = NULL; 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1509) 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1510) return 0; 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1511) } 8275637215bd3d Masami Hiramatsu (Google 2025-01-17 1512)
Hi Seokwoo,
kernel test robot noticed the following build warnings:
[auto build test WARNING on trace/for-next] [also build test WARNING on linus/master v6.18-rc7 next-20251127] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Seokwoo-Chung-Ryan/docs-traci... base: https://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace for-next patch link: https://lore.kernel.org/r/20251126184110.72241-3-seokwoo.chung130%40gmail.co... patch subject: [PATCH v4 2/3] tracing/fprobe: Support comma-separated symbols and :entry/:exit config: x86_64-randconfig-003-20251127 (https://download.01.org/0day-ci/archive/20251127/202511272241.s6tUpIgv-lkp@i...) compiler: gcc-14 (Debian 14.2.0-19) 14.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251127/202511272241.s6tUpIgv-lkp@i...)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot lkp@intel.com | Closes: https://lore.kernel.org/oe-kbuild-all/202511272241.s6tUpIgv-lkp@intel.com/
All warnings (new ones prefixed by >>):
kernel/trace/trace_fprobe.c: In function 'parse_fprobe_spec': kernel/trace/trace_fprobe.c:1282:12: error: invalid storage class for function 'trace_fprobe_create_internal' 1282 | static int trace_fprobe_create_internal(int argc, const char *argv[], | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ kernel/trace/trace_fprobe.c:1513:12: error: invalid storage class for function 'trace_fprobe_create_cb' 1513 | static int trace_fprobe_create_cb(int argc, const char *argv[]) | ^~~~~~~~~~~~~~~~~~~~~~ kernel/trace/trace_fprobe.c:1530:12: error: invalid storage class for function 'trace_fprobe_create' 1530 | static int trace_fprobe_create(const char *raw_command) | ^~~~~~~~~~~~~~~~~~~ kernel/trace/trace_fprobe.c:1535:12: error: invalid storage class for function 'trace_fprobe_release' 1535 | static int trace_fprobe_release(struct dyn_event *ev) | ^~~~~~~~~~~~~~~~~~~~ kernel/trace/trace_fprobe.c:1545:12: error: invalid storage class for function 'trace_fprobe_show' 1545 | static int trace_fprobe_show(struct seq_file *m, struct dyn_event *ev) | ^~~~~~~~~~~~~~~~~ kernel/trace/trace_fprobe.c:1572:12: error: invalid storage class for function 'enable_trace_fprobe' 1572 | static int enable_trace_fprobe(struct trace_event_call *call, | ^~~~~~~~~~~~~~~~~~~ kernel/trace/trace_fprobe.c:1608:12: error: invalid storage class for function 'disable_trace_fprobe' 1608 | static int disable_trace_fprobe(struct trace_event_call *call, | ^~~~~~~~~~~~~~~~~~~~ kernel/trace/trace_fprobe.c:1653:12: error: invalid storage class for function 'fprobe_register' 1653 | static int fprobe_register(struct trace_event_call *event, | ^~~~~~~~~~~~~~~ kernel/trace/trace_fprobe.c:1683:19: error: invalid storage class for function 'init_fprobe_trace_early' 1683 | static __init int init_fprobe_trace_early(void) | ^~~~~~~~~~~~~~~~~~~~~~~ In file included from include/linux/fprobe.h:6, from kernel/trace/trace_fprobe.c:8: include/linux/compiler.h:286:52: error: initializer element is not constant 286 | __UNIQUE_ID(__PASTE(__addressable_,sym)) = (void *)(uintptr_t)&sym; | ^ include/linux/compiler.h:289:9: note: in expansion of macro '___ADDRESSABLE' 289 | ___ADDRESSABLE(sym, __section(".discard.addressable")) | ^~~~~~~~~~~~~~ include/linux/init.h:250:9: note: in expansion of macro '__ADDRESSABLE' 250 | __ADDRESSABLE(fn) | ^~~~~~~~~~~~~ include/linux/init.h:255:9: note: in expansion of macro '__define_initcall_stub' 255 | __define_initcall_stub(__stub, fn) \ | ^~~~~~~~~~~~~~~~~~~~~~ include/linux/init.h:268:9: note: in expansion of macro '____define_initcall' 268 | ____define_initcall(fn, \ | ^~~~~~~~~~~~~~~~~~~ include/linux/init.h:274:9: note: in expansion of macro '__unique_initcall' 274 | __unique_initcall(fn, id, __sec, __initcall_id(fn)) | ^~~~~~~~~~~~~~~~~ include/linux/init.h:276:35: note: in expansion of macro '___define_initcall' 276 | #define __define_initcall(fn, id) ___define_initcall(fn, id, .initcall##id) | ^~~~~~~~~~~~~~~~~~ include/linux/init.h:294:41: note: in expansion of macro '__define_initcall' 294 | #define core_initcall(fn) __define_initcall(fn, 1) | ^~~~~~~~~~~~~~~~~ kernel/trace/trace_fprobe.c:1702:1: note: in expansion of macro 'core_initcall' 1702 | core_initcall(init_fprobe_trace_early); | ^~~~~~~~~~~~~ kernel/trace/trace_fprobe.c:1702:1: error: expected declaration or statement at end of input kernel/trace/trace_fprobe.c: At top level:
kernel/trace/trace_fprobe.c:28:12: warning: 'trace_fprobe_create' used but never defined
28 | static int trace_fprobe_create(const char *raw_command); | ^~~~~~~~~~~~~~~~~~~
kernel/trace/trace_fprobe.c:29:12: warning: 'trace_fprobe_show' used but never defined
29 | static int trace_fprobe_show(struct seq_file *m, struct dyn_event *ev); | ^~~~~~~~~~~~~~~~~
kernel/trace/trace_fprobe.c:30:12: warning: 'trace_fprobe_release' used but never defined
30 | static int trace_fprobe_release(struct dyn_event *ev); | ^~~~~~~~~~~~~~~~~~~~
kernel/trace/trace_fprobe.c:741:12: warning: 'fprobe_register' used but never defined
741 | static int fprobe_register(struct trace_event_call *event, | ^~~~~~~~~~~~~~~
kernel/trace/trace_fprobe.c:1653:12: warning: 'fprobe_register' defined but not used [-Wunused-function]
1653 | static int fprobe_register(struct trace_event_call *event, | ^~~~~~~~~~~~~~~
kernel/trace/trace_fprobe.c:1545:12: warning: 'trace_fprobe_show' defined but not used [-Wunused-function]
1545 | static int trace_fprobe_show(struct seq_file *m, struct dyn_event *ev) | ^~~~~~~~~~~~~~~~~
kernel/trace/trace_fprobe.c:1535:12: warning: 'trace_fprobe_release' defined but not used [-Wunused-function]
1535 | static int trace_fprobe_release(struct dyn_event *ev) | ^~~~~~~~~~~~~~~~~~~~
kernel/trace/trace_fprobe.c:1530:12: warning: 'trace_fprobe_create' defined but not used [-Wunused-function]
1530 | static int trace_fprobe_create(const char *raw_command) | ^~~~~~~~~~~~~~~~~~~
vim +/trace_fprobe_create +28 kernel/trace/trace_fprobe.c
334e5519c375701 Masami Hiramatsu (Google 2023-06-06 27) 334e5519c375701 Masami Hiramatsu (Google 2023-06-06 @28) static int trace_fprobe_create(const char *raw_command); 334e5519c375701 Masami Hiramatsu (Google 2023-06-06 @29) static int trace_fprobe_show(struct seq_file *m, struct dyn_event *ev); 334e5519c375701 Masami Hiramatsu (Google 2023-06-06 @30) static int trace_fprobe_release(struct dyn_event *ev); 334e5519c375701 Masami Hiramatsu (Google 2023-06-06 31) static bool trace_fprobe_is_busy(struct dyn_event *ev); 334e5519c375701 Masami Hiramatsu (Google 2023-06-06 32) static bool trace_fprobe_match(const char *system, const char *event, 334e5519c375701 Masami Hiramatsu (Google 2023-06-06 33) int argc, const char **argv, struct dyn_event *ev); 334e5519c375701 Masami Hiramatsu (Google 2023-06-06 34)
linux-kselftest-mirror@lists.linaro.org