Re: [PATCH 12/18] tracing: Add accessing direct address from function based events
On Tue, 13 Feb 2018 00:47:50 +0900 Masami Hiramatsuwrote: > > > if (WARN_ON(!fevent->last_arg)) > > > break; > > > - ret = kstrtoul(token, 0, ); > > > - if (ret < 0) > > > - break; > > > + if (isalpha(token[0]) || token[0] != '_') { > > > > I guess you wanted the token[0] being '_'. Maybe it'd be better adding > > > > #define isident0(x) (isalpha(x) || (x) == '_') > > If this '$' is only for the symbol or direct address(with 0x prefix), > you just need to check by !isdigit(token[0]), isn't it? > (and if it is insane get_symbol just fails) I modified a lot of this code for the next version (which I'm still tweaking). I have this for next_token() (which I may add for the trace_events_filter.c code as Al Viro has recently pointed out issues with its parsing): static char *next_token(char **ptr, char *last) { char *arg; char *str; if (!*ptr) return NULL; arg = *ptr; if (*last) *arg = *last; if (!*arg) return NULL; for (str = arg; *str; str++) { if (!isalnum(*str) && *str != '_') break; } if (*str) { if (str == arg) str++; *last = *str; *str = 0; *ptr = str; return arg; } *last = 0; *ptr = NULL; return arg; } And this: static bool valid_name(const char *token) { return isalpha(token[0]) || token[0] == '_'; } As all tokens will now be either entirely alphanumeric with '_' or a single character. -- Steve
Re: [PATCH 12/18] tracing: Add accessing direct address from function based events
On Tue, 13 Feb 2018 00:47:50 +0900 Masami Hiramatsu wrote: > > > if (WARN_ON(!fevent->last_arg)) > > > break; > > > - ret = kstrtoul(token, 0, ); > > > - if (ret < 0) > > > - break; > > > + if (isalpha(token[0]) || token[0] != '_') { > > > > I guess you wanted the token[0] being '_'. Maybe it'd be better adding > > > > #define isident0(x) (isalpha(x) || (x) == '_') > > If this '$' is only for the symbol or direct address(with 0x prefix), > you just need to check by !isdigit(token[0]), isn't it? > (and if it is insane get_symbol just fails) I modified a lot of this code for the next version (which I'm still tweaking). I have this for next_token() (which I may add for the trace_events_filter.c code as Al Viro has recently pointed out issues with its parsing): static char *next_token(char **ptr, char *last) { char *arg; char *str; if (!*ptr) return NULL; arg = *ptr; if (*last) *arg = *last; if (!*arg) return NULL; for (str = arg; *str; str++) { if (!isalnum(*str) && *str != '_') break; } if (*str) { if (str == arg) str++; *last = *str; *str = 0; *ptr = str; return arg; } *last = 0; *ptr = NULL; return arg; } And this: static bool valid_name(const char *token) { return isalpha(token[0]) || token[0] == '_'; } As all tokens will now be either entirely alphanumeric with '_' or a single character. -- Steve
Re: [PATCH 12/18] tracing: Add accessing direct address from function based events
On Mon, 12 Feb 2018 11:06:44 +0900 Namhyung Kimwrote: > Hi Steve, > > On Fri, Feb 09, 2018 at 05:07:37PM -0500, Steven Rostedt wrote: > > On Fri, 9 Feb 2018 09:34:36 +0900 > > Namhyung Kim wrote: > > > > > Couldn't we use the symbol name directly? Maybe it needs a syntax to > > > indicate global variable. Like this? > > > > > > # echo 'do_IRQ(int $total_forks)' > function_events > > > > > > I decided to stick with "$". > > Good. > > > [SNIP] > > static enum func_states > > process_event(struct func_event *fevent, const char *token, enum > > func_states state) > > { > > @@ -469,6 +479,8 @@ process_event(struct func_event *fevent, const char > > *token, enum func_states sta > > case FUNC_STATE_ARRAY_END: > > if (WARN_ON(!fevent->last_arg)) > > break; > > + if (token[0] == '$') > > + return FUNC_STATE_SYMBOL; > > if (update_arg_name(fevent, token) < 0) > > break; > > if (strncmp(token, "0x", 2) == 0) > > @@ -542,6 +554,11 @@ process_event(struct func_event *fevent, const char > > *token, enum func_states sta > > fevent->last_arg->index += val; > > return FUNC_STATE_VAR; > > > > + case FUNC_STATE_SYMBOL: > > + if (!isalpha(token[0]) && token[0] != '_') > > + break; > > + goto equal; > > + > > case FUNC_STATE_ADDR: > > switch (token[0]) { > > case ')': > > @@ -599,14 +616,26 @@ process_event(struct func_event *fevent, const char > > *token, enum func_states sta > > break; > > > > case FUNC_STATE_EQUAL: > > + if (token[0] == '$') > > + return FUNC_STATE_SYMBOL; > > if (strncmp(token, "0x", 2) != 0) > > break; > > equal: > > if (WARN_ON(!fevent->last_arg)) > > break; > > - ret = kstrtoul(token, 0, ); > > - if (ret < 0) > > - break; > > + if (isalpha(token[0]) || token[0] != '_') { > > I guess you wanted the token[0] being '_'. Maybe it'd be better adding > > #define isident0(x) (isalpha(x) || (x) == '_') If this '$' is only for the symbol or direct address(with 0x prefix), you just need to check by !isdigit(token[0]), isn't it? (and if it is insane get_symbol just fails) Thanks, > > ? > > Thanks, > Namhyung > > > > + ret = get_symbol(token, ); > > + if (ret < 0) > > + break; > > + if (!fevent->last_arg->name) { > > + if (update_arg_name(fevent, token) < 0) > > + break; > > + } > > + } else { > > + ret = kstrtoul(token, 0, ); > > + if (ret < 0) > > + break; > > + } > > update_arg = false; > > fevent->last_arg->index = val; > > fevent->last_arg->arg = -1; > > -- > > 2.13.6 > > -- Masami Hiramatsu
Re: [PATCH 12/18] tracing: Add accessing direct address from function based events
On Mon, 12 Feb 2018 11:06:44 +0900 Namhyung Kim wrote: > Hi Steve, > > On Fri, Feb 09, 2018 at 05:07:37PM -0500, Steven Rostedt wrote: > > On Fri, 9 Feb 2018 09:34:36 +0900 > > Namhyung Kim wrote: > > > > > Couldn't we use the symbol name directly? Maybe it needs a syntax to > > > indicate global variable. Like this? > > > > > > # echo 'do_IRQ(int $total_forks)' > function_events > > > > > > I decided to stick with "$". > > Good. > > > [SNIP] > > static enum func_states > > process_event(struct func_event *fevent, const char *token, enum > > func_states state) > > { > > @@ -469,6 +479,8 @@ process_event(struct func_event *fevent, const char > > *token, enum func_states sta > > case FUNC_STATE_ARRAY_END: > > if (WARN_ON(!fevent->last_arg)) > > break; > > + if (token[0] == '$') > > + return FUNC_STATE_SYMBOL; > > if (update_arg_name(fevent, token) < 0) > > break; > > if (strncmp(token, "0x", 2) == 0) > > @@ -542,6 +554,11 @@ process_event(struct func_event *fevent, const char > > *token, enum func_states sta > > fevent->last_arg->index += val; > > return FUNC_STATE_VAR; > > > > + case FUNC_STATE_SYMBOL: > > + if (!isalpha(token[0]) && token[0] != '_') > > + break; > > + goto equal; > > + > > case FUNC_STATE_ADDR: > > switch (token[0]) { > > case ')': > > @@ -599,14 +616,26 @@ process_event(struct func_event *fevent, const char > > *token, enum func_states sta > > break; > > > > case FUNC_STATE_EQUAL: > > + if (token[0] == '$') > > + return FUNC_STATE_SYMBOL; > > if (strncmp(token, "0x", 2) != 0) > > break; > > equal: > > if (WARN_ON(!fevent->last_arg)) > > break; > > - ret = kstrtoul(token, 0, ); > > - if (ret < 0) > > - break; > > + if (isalpha(token[0]) || token[0] != '_') { > > I guess you wanted the token[0] being '_'. Maybe it'd be better adding > > #define isident0(x) (isalpha(x) || (x) == '_') If this '$' is only for the symbol or direct address(with 0x prefix), you just need to check by !isdigit(token[0]), isn't it? (and if it is insane get_symbol just fails) Thanks, > > ? > > Thanks, > Namhyung > > > > + ret = get_symbol(token, ); > > + if (ret < 0) > > + break; > > + if (!fevent->last_arg->name) { > > + if (update_arg_name(fevent, token) < 0) > > + break; > > + } > > + } else { > > + ret = kstrtoul(token, 0, ); > > + if (ret < 0) > > + break; > > + } > > update_arg = false; > > fevent->last_arg->index = val; > > fevent->last_arg->arg = -1; > > -- > > 2.13.6 > > -- Masami Hiramatsu
Re: [PATCH 12/18] tracing: Add accessing direct address from function based events
Hi Steve, On Fri, Feb 09, 2018 at 05:07:37PM -0500, Steven Rostedt wrote: > On Fri, 9 Feb 2018 09:34:36 +0900 > Namhyung Kimwrote: > > > Couldn't we use the symbol name directly? Maybe it needs a syntax to > > indicate global variable. Like this? > > > > # echo 'do_IRQ(int $total_forks)' > function_events > > > I decided to stick with "$". Good. [SNIP] > static enum func_states > process_event(struct func_event *fevent, const char *token, enum func_states > state) > { > @@ -469,6 +479,8 @@ process_event(struct func_event *fevent, const char > *token, enum func_states sta > case FUNC_STATE_ARRAY_END: > if (WARN_ON(!fevent->last_arg)) > break; > + if (token[0] == '$') > + return FUNC_STATE_SYMBOL; > if (update_arg_name(fevent, token) < 0) > break; > if (strncmp(token, "0x", 2) == 0) > @@ -542,6 +554,11 @@ process_event(struct func_event *fevent, const char > *token, enum func_states sta > fevent->last_arg->index += val; > return FUNC_STATE_VAR; > > + case FUNC_STATE_SYMBOL: > + if (!isalpha(token[0]) && token[0] != '_') > + break; > + goto equal; > + > case FUNC_STATE_ADDR: > switch (token[0]) { > case ')': > @@ -599,14 +616,26 @@ process_event(struct func_event *fevent, const char > *token, enum func_states sta > break; > > case FUNC_STATE_EQUAL: > + if (token[0] == '$') > + return FUNC_STATE_SYMBOL; > if (strncmp(token, "0x", 2) != 0) > break; > equal: > if (WARN_ON(!fevent->last_arg)) > break; > - ret = kstrtoul(token, 0, ); > - if (ret < 0) > - break; > + if (isalpha(token[0]) || token[0] != '_') { I guess you wanted the token[0] being '_'. Maybe it'd be better adding #define isident0(x) (isalpha(x) || (x) == '_') ? Thanks, Namhyung > + ret = get_symbol(token, ); > + if (ret < 0) > + break; > + if (!fevent->last_arg->name) { > + if (update_arg_name(fevent, token) < 0) > + break; > + } > + } else { > + ret = kstrtoul(token, 0, ); > + if (ret < 0) > + break; > + } > update_arg = false; > fevent->last_arg->index = val; > fevent->last_arg->arg = -1; > -- > 2.13.6 >
Re: [PATCH 12/18] tracing: Add accessing direct address from function based events
Hi Steve, On Fri, Feb 09, 2018 at 05:07:37PM -0500, Steven Rostedt wrote: > On Fri, 9 Feb 2018 09:34:36 +0900 > Namhyung Kim wrote: > > > Couldn't we use the symbol name directly? Maybe it needs a syntax to > > indicate global variable. Like this? > > > > # echo 'do_IRQ(int $total_forks)' > function_events > > > I decided to stick with "$". Good. [SNIP] > static enum func_states > process_event(struct func_event *fevent, const char *token, enum func_states > state) > { > @@ -469,6 +479,8 @@ process_event(struct func_event *fevent, const char > *token, enum func_states sta > case FUNC_STATE_ARRAY_END: > if (WARN_ON(!fevent->last_arg)) > break; > + if (token[0] == '$') > + return FUNC_STATE_SYMBOL; > if (update_arg_name(fevent, token) < 0) > break; > if (strncmp(token, "0x", 2) == 0) > @@ -542,6 +554,11 @@ process_event(struct func_event *fevent, const char > *token, enum func_states sta > fevent->last_arg->index += val; > return FUNC_STATE_VAR; > > + case FUNC_STATE_SYMBOL: > + if (!isalpha(token[0]) && token[0] != '_') > + break; > + goto equal; > + > case FUNC_STATE_ADDR: > switch (token[0]) { > case ')': > @@ -599,14 +616,26 @@ process_event(struct func_event *fevent, const char > *token, enum func_states sta > break; > > case FUNC_STATE_EQUAL: > + if (token[0] == '$') > + return FUNC_STATE_SYMBOL; > if (strncmp(token, "0x", 2) != 0) > break; > equal: > if (WARN_ON(!fevent->last_arg)) > break; > - ret = kstrtoul(token, 0, ); > - if (ret < 0) > - break; > + if (isalpha(token[0]) || token[0] != '_') { I guess you wanted the token[0] being '_'. Maybe it'd be better adding #define isident0(x) (isalpha(x) || (x) == '_') ? Thanks, Namhyung > + ret = get_symbol(token, ); > + if (ret < 0) > + break; > + if (!fevent->last_arg->name) { > + if (update_arg_name(fevent, token) < 0) > + break; > + } > + } else { > + ret = kstrtoul(token, 0, ); > + if (ret < 0) > + break; > + } > update_arg = false; > fevent->last_arg->index = val; > fevent->last_arg->arg = -1; > -- > 2.13.6 >
Re: [PATCH 12/18] tracing: Add accessing direct address from function based events
On Fri, 9 Feb 2018 09:34:36 +0900 Namhyung Kimwrote: > Couldn't we use the symbol name directly? Maybe it needs a syntax to > indicate global variable. Like this? > > # echo 'do_IRQ(int $total_forks)' > function_events I decided to stick with "$". -- Steve >From ed303534dac5b2d9af7b4db9f042d7941c997288 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Fri, 9 Feb 2018 17:03:06 -0500 Subject: [PATCH] tracing: Add direct kallsym access to function based events Instead of searching for the address via kallsyms to print the variable in a function based event, have "$" be a way to tell the function based event to look up the symbol for you. Instead of: # grep total_forks /proc/kallsyms 82354c18 B total_forks # echo 'do_IRQ(int forks=0x82354c18)' > function_events One can do either: # echo 'do_IRQ(int forks=$total_forks)' > function_events or simply # echo 'do_IRQ(int $total_forks)' > function_events The latter will say "total_forks=" in the output where the formal says "forks=". Suggested-by: Namhyung Kim Signed-off-by: Steven Rostedt (VMware) --- Documentation/trace/function-based-events.rst | 25 ++- kernel/trace/trace_event_ftrace.c | 35 --- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/Documentation/trace/function-based-events.rst b/Documentation/trace/function-based-events.rst index 606981b876a0..9a30aee338f4 100644 --- a/Documentation/trace/function-based-events.rst +++ b/Documentation/trace/function-based-events.rst @@ -112,13 +112,19 @@ as follows: INDIRECT := INDEX | OFFSET | INDIRECT INDIRECT | '' - ADDR := A hexidecimal address starting with '0x' + ADDR := | Where is a unique string starting with an alphabetic character and consists only of letters and numbers and underscores. Where is a number that can be read by kstrtol() (hex, decimal, etc). + Where is an address starting with '0x' + + Where is a valid symbol name from kallsyms starting with "$". + For example: $total_forks + + Simple arguments @@ -317,6 +323,23 @@ Is the same as -0 [003] d..3 655.823498: ret_from_intr->do_IRQ(total_forks=1504, regs=tick_nohz_idle_enter+0x4c/0x50) -0 [003] d..3 655.954096: ret_from_intr->do_IRQ(total_forks=1504, regs=cpuidle_enter_state+0xb1/0x330) +You can also accomplish the same thing above using the kallsym name following +a "$" symbol. That is: + + # echo 'do_IRQ(int $total_forks)' > function_events + +is the same as the above command using the "0x82354c18" address. + +You can rename the variable by using "=": + + # echo 'do_IRQ(int forks=$total_forks)' > function_events + + # cat trace +-0 [003] d..3 698.226763: ret_from_intr->do_IRQ(forks=1475) +-0 [003] d..3 698.226810: ret_from_intr->do_IRQ(forks=1475) +-0 [003] d..3 698.227046: ret_from_intr->do_IRQ(forks=1475) +-0 [003] d..3 698.50: ret_from_intr->do_IRQ(forks=1475) + Array types === diff --git a/kernel/trace/trace_event_ftrace.c b/kernel/trace/trace_event_ftrace.c index 376c9324d65c..39abda19d5d2 100644 --- a/kernel/trace/trace_event_ftrace.c +++ b/kernel/trace/trace_event_ftrace.c @@ -92,6 +92,7 @@ static LIST_HEAD(func_events); C(ARRAY_END), \ C(REDIRECT_PLUS), \ C(REDIRECT_BRACKET),\ + C(SYMBOL), \ C(VAR), \ C(COMMA), \ C(NULL),\ @@ -281,6 +282,7 @@ static char *next_token(char **ptr, char *last) *str == '|' || *str == '+' || *str == '=' || + *str == '$' || *str == ')') break; } @@ -393,6 +395,14 @@ static int add_arg_redirect(struct func_arg *arg, long index, long indirect) return 0; } +static int get_symbol(const char *symbol, unsigned long *val) +{ + *val = kallsyms_lookup_name(symbol); + if (!*val) + return -1; + return 0; +} + static enum func_states process_event(struct func_event *fevent, const char *token, enum func_states state) { @@ -469,6 +479,8 @@ process_event(struct func_event *fevent, const char *token, enum func_states sta case FUNC_STATE_ARRAY_END: if (WARN_ON(!fevent->last_arg)) break; + if (token[0] == '$') + return FUNC_STATE_SYMBOL; if (update_arg_name(fevent, token) < 0) break; if (strncmp(token, "0x", 2) == 0) @@ -542,6 +554,11 @@ process_event(struct func_event *fevent, const char *token, enum func_states sta
Re: [PATCH 12/18] tracing: Add accessing direct address from function based events
On Fri, 9 Feb 2018 09:34:36 +0900 Namhyung Kim wrote: > Couldn't we use the symbol name directly? Maybe it needs a syntax to > indicate global variable. Like this? > > # echo 'do_IRQ(int $total_forks)' > function_events I decided to stick with "$". -- Steve >From ed303534dac5b2d9af7b4db9f042d7941c997288 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Fri, 9 Feb 2018 17:03:06 -0500 Subject: [PATCH] tracing: Add direct kallsym access to function based events Instead of searching for the address via kallsyms to print the variable in a function based event, have "$" be a way to tell the function based event to look up the symbol for you. Instead of: # grep total_forks /proc/kallsyms 82354c18 B total_forks # echo 'do_IRQ(int forks=0x82354c18)' > function_events One can do either: # echo 'do_IRQ(int forks=$total_forks)' > function_events or simply # echo 'do_IRQ(int $total_forks)' > function_events The latter will say "total_forks=" in the output where the formal says "forks=". Suggested-by: Namhyung Kim Signed-off-by: Steven Rostedt (VMware) --- Documentation/trace/function-based-events.rst | 25 ++- kernel/trace/trace_event_ftrace.c | 35 --- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/Documentation/trace/function-based-events.rst b/Documentation/trace/function-based-events.rst index 606981b876a0..9a30aee338f4 100644 --- a/Documentation/trace/function-based-events.rst +++ b/Documentation/trace/function-based-events.rst @@ -112,13 +112,19 @@ as follows: INDIRECT := INDEX | OFFSET | INDIRECT INDIRECT | '' - ADDR := A hexidecimal address starting with '0x' + ADDR := | Where is a unique string starting with an alphabetic character and consists only of letters and numbers and underscores. Where is a number that can be read by kstrtol() (hex, decimal, etc). + Where is an address starting with '0x' + + Where is a valid symbol name from kallsyms starting with "$". + For example: $total_forks + + Simple arguments @@ -317,6 +323,23 @@ Is the same as -0 [003] d..3 655.823498: ret_from_intr->do_IRQ(total_forks=1504, regs=tick_nohz_idle_enter+0x4c/0x50) -0 [003] d..3 655.954096: ret_from_intr->do_IRQ(total_forks=1504, regs=cpuidle_enter_state+0xb1/0x330) +You can also accomplish the same thing above using the kallsym name following +a "$" symbol. That is: + + # echo 'do_IRQ(int $total_forks)' > function_events + +is the same as the above command using the "0x82354c18" address. + +You can rename the variable by using "=": + + # echo 'do_IRQ(int forks=$total_forks)' > function_events + + # cat trace +-0 [003] d..3 698.226763: ret_from_intr->do_IRQ(forks=1475) +-0 [003] d..3 698.226810: ret_from_intr->do_IRQ(forks=1475) +-0 [003] d..3 698.227046: ret_from_intr->do_IRQ(forks=1475) +-0 [003] d..3 698.50: ret_from_intr->do_IRQ(forks=1475) + Array types === diff --git a/kernel/trace/trace_event_ftrace.c b/kernel/trace/trace_event_ftrace.c index 376c9324d65c..39abda19d5d2 100644 --- a/kernel/trace/trace_event_ftrace.c +++ b/kernel/trace/trace_event_ftrace.c @@ -92,6 +92,7 @@ static LIST_HEAD(func_events); C(ARRAY_END), \ C(REDIRECT_PLUS), \ C(REDIRECT_BRACKET),\ + C(SYMBOL), \ C(VAR), \ C(COMMA), \ C(NULL),\ @@ -281,6 +282,7 @@ static char *next_token(char **ptr, char *last) *str == '|' || *str == '+' || *str == '=' || + *str == '$' || *str == ')') break; } @@ -393,6 +395,14 @@ static int add_arg_redirect(struct func_arg *arg, long index, long indirect) return 0; } +static int get_symbol(const char *symbol, unsigned long *val) +{ + *val = kallsyms_lookup_name(symbol); + if (!*val) + return -1; + return 0; +} + static enum func_states process_event(struct func_event *fevent, const char *token, enum func_states state) { @@ -469,6 +479,8 @@ process_event(struct func_event *fevent, const char *token, enum func_states sta case FUNC_STATE_ARRAY_END: if (WARN_ON(!fevent->last_arg)) break; + if (token[0] == '$') + return FUNC_STATE_SYMBOL; if (update_arg_name(fevent, token) < 0) break; if (strncmp(token, "0x", 2) == 0) @@ -542,6 +554,11 @@ process_event(struct func_event *fevent, const char *token, enum func_states sta fevent->last_arg->index += val; return FUNC_STATE_VAR; +
Re: [PATCH 12/18] tracing: Add accessing direct address from function based events
On Fri, 9 Feb 2018 09:34:36 +0900 Namhyung Kimwrote: > > +Direct memory access > > + > > + > > +Function arguments are not the only thing that can be recorded from a > > function > > +based event. Memory addresses can also be examined. If there's a global > > variable > > +that you want to monitor via an interrupt, you can put in the address > > directly. > > + > > + # grep total_forks /proc/kallsyms > > +82354c18 B total_forks > > + > > + # echo 'do_IRQ(int total_forks=0x82354c18)' > function_events > > Couldn't we use the symbol name directly? Maybe it needs a syntax to > indicate global variable. Like this? > > # echo 'do_IRQ(int $total_forks)' > function_events Or perhaps use "@"? But that's a good idea and not hard to implement. > > case FUNC_STATE_TYPE: > > - if (!isalpha(token[0]) || token[0] == '_') > > - break; > > if (WARN_ON(!fevent->last_arg)) > > break; > > - fevent->last_arg->name = kstrdup(token, GFP_KERNEL); > > - if (!fevent->last_arg->name) > > + if (update_arg_name(fevent, token) < 0) > > + break; > > + if (strncmp(token, "0x", 2) == 0) > > + goto equal; > > Not sure it's needed here. IIUC it should see '=' first and you used > the same token with arg->name. Hmm.. do you want support accessing to > an unnamed address directly like below? > > # echo 'do_IRQ(int 0x82354c18)' > function_events Yes this works, and was the original way. Someone at DevConf.cz (Arnaldo maybe, can't remember) recommended giving a name and then we came up with the "=" sign to use. > > > + if (!isalpha(token[0]) && token[0] != '_') > > break; > > Maybe you want to check it before the update_arg_name(). Hmm, perhaps, I guess I should see what the error messages shows. Thanks! -- Steve
Re: [PATCH 12/18] tracing: Add accessing direct address from function based events
On Fri, 9 Feb 2018 09:34:36 +0900 Namhyung Kim wrote: > > +Direct memory access > > + > > + > > +Function arguments are not the only thing that can be recorded from a > > function > > +based event. Memory addresses can also be examined. If there's a global > > variable > > +that you want to monitor via an interrupt, you can put in the address > > directly. > > + > > + # grep total_forks /proc/kallsyms > > +82354c18 B total_forks > > + > > + # echo 'do_IRQ(int total_forks=0x82354c18)' > function_events > > Couldn't we use the symbol name directly? Maybe it needs a syntax to > indicate global variable. Like this? > > # echo 'do_IRQ(int $total_forks)' > function_events Or perhaps use "@"? But that's a good idea and not hard to implement. > > case FUNC_STATE_TYPE: > > - if (!isalpha(token[0]) || token[0] == '_') > > - break; > > if (WARN_ON(!fevent->last_arg)) > > break; > > - fevent->last_arg->name = kstrdup(token, GFP_KERNEL); > > - if (!fevent->last_arg->name) > > + if (update_arg_name(fevent, token) < 0) > > + break; > > + if (strncmp(token, "0x", 2) == 0) > > + goto equal; > > Not sure it's needed here. IIUC it should see '=' first and you used > the same token with arg->name. Hmm.. do you want support accessing to > an unnamed address directly like below? > > # echo 'do_IRQ(int 0x82354c18)' > function_events Yes this works, and was the original way. Someone at DevConf.cz (Arnaldo maybe, can't remember) recommended giving a name and then we came up with the "=" sign to use. > > > + if (!isalpha(token[0]) && token[0] != '_') > > break; > > Maybe you want to check it before the update_arg_name(). Hmm, perhaps, I guess I should see what the error messages shows. Thanks! -- Steve
Re: [PATCH 12/18] tracing: Add accessing direct address from function based events
On Fri, Feb 02, 2018 at 06:05:10PM -0500, Steven Rostedt wrote: > From: "Steven Rostedt (VMware)"> > Allow referencing any address during the function based event. The syntax is > to use = For example: > > # echo 'do_IRQ(long total_forks=0xa2a4b4c0)' > function_events > # echo 1 > events/function/enable > # cat trace > sshd-832 [000] d... 221639.210845: > ret_from_intr->do_IRQ(total_forks=855) > sshd-832 [000] d... 221639.24: > ret_from_intr->do_IRQ(total_forks=855) > -0 [000] d... 221639.211198: > ret_from_intr->do_IRQ(total_forks=855) > > Signed-off-by: Steven Rostedt (VMware) > --- > Documentation/trace/function-based-events.rst | 40 +++- > kernel/trace/trace_event_ftrace.c | 129 > +- > 2 files changed, 143 insertions(+), 26 deletions(-) > > diff --git a/Documentation/trace/function-based-events.rst > b/Documentation/trace/function-based-events.rst > index f18c8f3ef330..b0e6725f3032 100644 > --- a/Documentation/trace/function-based-events.rst > +++ b/Documentation/trace/function-based-events.rst > @@ -91,7 +91,7 @@ as follows: > > ARGS := ARG | ARG ',' ARGS | '' > > - ARG := TYPE FIELD | ARG '|' ARG > + ARG := TYPE FIELD | TYPE '=' ADDR | TYPE ADDR | ARG '|' ARG > > TYPE := ATOM | 'unsigned' ATOM > > @@ -107,6 +107,8 @@ as follows: > > OFFSET := '+' > > + ADDR := A hexidecimal address starting with '0x' > + > Where is a unique string starting with an alphabetic character > and consists only of letters and numbers and underscores. > > @@ -267,3 +269,39 @@ Again, using gdb to find the offset of the "func" field > of struct work_struct > -0 [000] dNs3 6241.172004: > delayed_work_timer_fn->__queue_work(cpu=128, wq=88011a010800, > func=vmstat_shepherd+0x0/0xb0) > worker/0:2-1689 [000] d..2 6241.172026: > __queue_delayed_work->__queue_work(cpu=7, wq=88011a11da00, > func=vmstat_update+0x0/0x70) > -0 [005] d.s3 6241.347996: > queue_work_on->__queue_work(cpu=128, wq=88011a011200, > func=fb_flashcursor+0x0/0x110 [fb]) > + > + > +Direct memory access > + > + > +Function arguments are not the only thing that can be recorded from a > function > +based event. Memory addresses can also be examined. If there's a global > variable > +that you want to monitor via an interrupt, you can put in the address > directly. > + > + # grep total_forks /proc/kallsyms > +82354c18 B total_forks > + > + # echo 'do_IRQ(int total_forks=0x82354c18)' > function_events Couldn't we use the symbol name directly? Maybe it needs a syntax to indicate global variable. Like this? # echo 'do_IRQ(int $total_forks)' > function_events > + > + # echo 1 events/functions/do_IRQ/enable > + # cat trace > +-0 [003] d..3 337.076709: > ret_from_intr->do_IRQ(total_forks=1419) > +-0 [003] d..3 337.077046: > ret_from_intr->do_IRQ(total_forks=1419) > +-0 [003] d..3 337.077076: > ret_from_intr->do_IRQ(total_forks=1420) > + > +Note, address notations do not affect the argument count. For instance, with > + > +__visible unsigned int __irq_entry do_IRQ(struct pt_regs *regs) > + > + # echo 'do_IRQ(int total_forks=0x82354c18, symbol regs[16])' > > function_events > + > +Is the same as > + > + # echo 'do_IRQ(int total_forks=0x82354c18 | symbol regs[16])' > > function_events > + > + # cat trace > +-0 [003] d..3 653.839546: > ret_from_intr->do_IRQ(total_forks=1504, regs=cpuidle_enter_state+0xb1/0x330) > +-0 [003] d..3 653.906011: > ret_from_intr->do_IRQ(total_forks=1504, regs=cpuidle_enter_state+0xb1/0x330) > +-0 [003] d..3 655.823498: > ret_from_intr->do_IRQ(total_forks=1504, regs=tick_nohz_idle_enter+0x4c/0x50) > +-0 [003] d..3 655.954096: > ret_from_intr->do_IRQ(total_forks=1504, regs=cpuidle_enter_state+0xb1/0x330) > + > diff --git a/kernel/trace/trace_event_ftrace.c > b/kernel/trace/trace_event_ftrace.c > index ba10177b9bd6..206114f192be 100644 > --- a/kernel/trace/trace_event_ftrace.c > +++ b/kernel/trace/trace_event_ftrace.c > @@ -256,14 +286,16 @@ static int add_arg(struct func_event *fevent, int > ftype, int unsign) > static enum func_states > process_event(struct func_event *fevent, const char *token, enum func_states > state) > { > + static bool update_arg; > static int unsign; > - long val; > + unsigned long val; > int ret; > int i; > > switch (state) { > case FUNC_STATE_INIT: > unsign = 0; > + update_arg = false; > if (!isalpha(token[0]) && token[0] != '_') > break; > /* Do not allow wild cards */ > @@ -279,15 +311,15 @@ process_event(struct func_event *fevent, const char > *token, enum func_states sta > break; > return
Re: [PATCH 12/18] tracing: Add accessing direct address from function based events
On Fri, Feb 02, 2018 at 06:05:10PM -0500, Steven Rostedt wrote: > From: "Steven Rostedt (VMware)" > > Allow referencing any address during the function based event. The syntax is > to use = For example: > > # echo 'do_IRQ(long total_forks=0xa2a4b4c0)' > function_events > # echo 1 > events/function/enable > # cat trace > sshd-832 [000] d... 221639.210845: > ret_from_intr->do_IRQ(total_forks=855) > sshd-832 [000] d... 221639.24: > ret_from_intr->do_IRQ(total_forks=855) > -0 [000] d... 221639.211198: > ret_from_intr->do_IRQ(total_forks=855) > > Signed-off-by: Steven Rostedt (VMware) > --- > Documentation/trace/function-based-events.rst | 40 +++- > kernel/trace/trace_event_ftrace.c | 129 > +- > 2 files changed, 143 insertions(+), 26 deletions(-) > > diff --git a/Documentation/trace/function-based-events.rst > b/Documentation/trace/function-based-events.rst > index f18c8f3ef330..b0e6725f3032 100644 > --- a/Documentation/trace/function-based-events.rst > +++ b/Documentation/trace/function-based-events.rst > @@ -91,7 +91,7 @@ as follows: > > ARGS := ARG | ARG ',' ARGS | '' > > - ARG := TYPE FIELD | ARG '|' ARG > + ARG := TYPE FIELD | TYPE '=' ADDR | TYPE ADDR | ARG '|' ARG > > TYPE := ATOM | 'unsigned' ATOM > > @@ -107,6 +107,8 @@ as follows: > > OFFSET := '+' > > + ADDR := A hexidecimal address starting with '0x' > + > Where is a unique string starting with an alphabetic character > and consists only of letters and numbers and underscores. > > @@ -267,3 +269,39 @@ Again, using gdb to find the offset of the "func" field > of struct work_struct > -0 [000] dNs3 6241.172004: > delayed_work_timer_fn->__queue_work(cpu=128, wq=88011a010800, > func=vmstat_shepherd+0x0/0xb0) > worker/0:2-1689 [000] d..2 6241.172026: > __queue_delayed_work->__queue_work(cpu=7, wq=88011a11da00, > func=vmstat_update+0x0/0x70) > -0 [005] d.s3 6241.347996: > queue_work_on->__queue_work(cpu=128, wq=88011a011200, > func=fb_flashcursor+0x0/0x110 [fb]) > + > + > +Direct memory access > + > + > +Function arguments are not the only thing that can be recorded from a > function > +based event. Memory addresses can also be examined. If there's a global > variable > +that you want to monitor via an interrupt, you can put in the address > directly. > + > + # grep total_forks /proc/kallsyms > +82354c18 B total_forks > + > + # echo 'do_IRQ(int total_forks=0x82354c18)' > function_events Couldn't we use the symbol name directly? Maybe it needs a syntax to indicate global variable. Like this? # echo 'do_IRQ(int $total_forks)' > function_events > + > + # echo 1 events/functions/do_IRQ/enable > + # cat trace > +-0 [003] d..3 337.076709: > ret_from_intr->do_IRQ(total_forks=1419) > +-0 [003] d..3 337.077046: > ret_from_intr->do_IRQ(total_forks=1419) > +-0 [003] d..3 337.077076: > ret_from_intr->do_IRQ(total_forks=1420) > + > +Note, address notations do not affect the argument count. For instance, with > + > +__visible unsigned int __irq_entry do_IRQ(struct pt_regs *regs) > + > + # echo 'do_IRQ(int total_forks=0x82354c18, symbol regs[16])' > > function_events > + > +Is the same as > + > + # echo 'do_IRQ(int total_forks=0x82354c18 | symbol regs[16])' > > function_events > + > + # cat trace > +-0 [003] d..3 653.839546: > ret_from_intr->do_IRQ(total_forks=1504, regs=cpuidle_enter_state+0xb1/0x330) > +-0 [003] d..3 653.906011: > ret_from_intr->do_IRQ(total_forks=1504, regs=cpuidle_enter_state+0xb1/0x330) > +-0 [003] d..3 655.823498: > ret_from_intr->do_IRQ(total_forks=1504, regs=tick_nohz_idle_enter+0x4c/0x50) > +-0 [003] d..3 655.954096: > ret_from_intr->do_IRQ(total_forks=1504, regs=cpuidle_enter_state+0xb1/0x330) > + > diff --git a/kernel/trace/trace_event_ftrace.c > b/kernel/trace/trace_event_ftrace.c > index ba10177b9bd6..206114f192be 100644 > --- a/kernel/trace/trace_event_ftrace.c > +++ b/kernel/trace/trace_event_ftrace.c > @@ -256,14 +286,16 @@ static int add_arg(struct func_event *fevent, int > ftype, int unsign) > static enum func_states > process_event(struct func_event *fevent, const char *token, enum func_states > state) > { > + static bool update_arg; > static int unsign; > - long val; > + unsigned long val; > int ret; > int i; > > switch (state) { > case FUNC_STATE_INIT: > unsign = 0; > + update_arg = false; > if (!isalpha(token[0]) && token[0] != '_') > break; > /* Do not allow wild cards */ > @@ -279,15 +311,15 @@ process_event(struct func_event *fevent, const char > *token, enum func_states sta > break; > return FUNC_STATE_PARAM; > > - case
[PATCH 12/18] tracing: Add accessing direct address from function based events
From: "Steven Rostedt (VMware)"Allow referencing any address during the function based event. The syntax is to use = For example: # echo 'do_IRQ(long total_forks=0xa2a4b4c0)' > function_events # echo 1 > events/function/enable # cat trace sshd-832 [000] d... 221639.210845: ret_from_intr->do_IRQ(total_forks=855) sshd-832 [000] d... 221639.24: ret_from_intr->do_IRQ(total_forks=855) -0 [000] d... 221639.211198: ret_from_intr->do_IRQ(total_forks=855) Signed-off-by: Steven Rostedt (VMware) --- Documentation/trace/function-based-events.rst | 40 +++- kernel/trace/trace_event_ftrace.c | 129 +- 2 files changed, 143 insertions(+), 26 deletions(-) diff --git a/Documentation/trace/function-based-events.rst b/Documentation/trace/function-based-events.rst index f18c8f3ef330..b0e6725f3032 100644 --- a/Documentation/trace/function-based-events.rst +++ b/Documentation/trace/function-based-events.rst @@ -91,7 +91,7 @@ as follows: ARGS := ARG | ARG ',' ARGS | '' - ARG := TYPE FIELD | ARG '|' ARG + ARG := TYPE FIELD | TYPE '=' ADDR | TYPE ADDR | ARG '|' ARG TYPE := ATOM | 'unsigned' ATOM @@ -107,6 +107,8 @@ as follows: OFFSET := '+' + ADDR := A hexidecimal address starting with '0x' + Where is a unique string starting with an alphabetic character and consists only of letters and numbers and underscores. @@ -267,3 +269,39 @@ Again, using gdb to find the offset of the "func" field of struct work_struct -0 [000] dNs3 6241.172004: delayed_work_timer_fn->__queue_work(cpu=128, wq=88011a010800, func=vmstat_shepherd+0x0/0xb0) worker/0:2-1689 [000] d..2 6241.172026: __queue_delayed_work->__queue_work(cpu=7, wq=88011a11da00, func=vmstat_update+0x0/0x70) -0 [005] d.s3 6241.347996: queue_work_on->__queue_work(cpu=128, wq=88011a011200, func=fb_flashcursor+0x0/0x110 [fb]) + + +Direct memory access + + +Function arguments are not the only thing that can be recorded from a function +based event. Memory addresses can also be examined. If there's a global variable +that you want to monitor via an interrupt, you can put in the address directly. + + # grep total_forks /proc/kallsyms +82354c18 B total_forks + + # echo 'do_IRQ(int total_forks=0x82354c18)' > function_events + + # echo 1 events/functions/do_IRQ/enable + # cat trace +-0 [003] d..3 337.076709: ret_from_intr->do_IRQ(total_forks=1419) +-0 [003] d..3 337.077046: ret_from_intr->do_IRQ(total_forks=1419) +-0 [003] d..3 337.077076: ret_from_intr->do_IRQ(total_forks=1420) + +Note, address notations do not affect the argument count. For instance, with + +__visible unsigned int __irq_entry do_IRQ(struct pt_regs *regs) + + # echo 'do_IRQ(int total_forks=0x82354c18, symbol regs[16])' > function_events + +Is the same as + + # echo 'do_IRQ(int total_forks=0x82354c18 | symbol regs[16])' > function_events + + # cat trace +-0 [003] d..3 653.839546: ret_from_intr->do_IRQ(total_forks=1504, regs=cpuidle_enter_state+0xb1/0x330) +-0 [003] d..3 653.906011: ret_from_intr->do_IRQ(total_forks=1504, regs=cpuidle_enter_state+0xb1/0x330) +-0 [003] d..3 655.823498: ret_from_intr->do_IRQ(total_forks=1504, regs=tick_nohz_idle_enter+0x4c/0x50) +-0 [003] d..3 655.954096: ret_from_intr->do_IRQ(total_forks=1504, regs=cpuidle_enter_state+0xb1/0x330) + diff --git a/kernel/trace/trace_event_ftrace.c b/kernel/trace/trace_event_ftrace.c index ba10177b9bd6..206114f192be 100644 --- a/kernel/trace/trace_event_ftrace.c +++ b/kernel/trace/trace_event_ftrace.c @@ -63,6 +63,8 @@ enum func_states { FUNC_STATE_BRACKET_END, FUNC_STATE_INDIRECT, FUNC_STATE_UNSIGNED, + FUNC_STATE_ADDR, + FUNC_STATE_EQUAL, FUNC_STATE_PIPE, FUNC_STATE_PLUS, FUNC_STATE_TYPE, @@ -199,6 +201,7 @@ static char *next_token(char **ptr, char *last) *str == ',' || *str == '|' || *str == '+' || + *str == '=' || *str == ')') break; } @@ -243,12 +246,39 @@ static int add_arg(struct func_event *fevent, int ftype, int unsign) arg->sign = func_type->sign; arg->offset = ALIGN(fevent->arg_offset, arg->size); arg->func_type = ftype; - arg->arg = fevent->arg_cnt; fevent->arg_offset = arg->offset + arg->size; list_add_tail(>list, >args); fevent->last_arg = arg; - fevent->arg_cnt++; + + return 0; +} + +static int update_arg_name(struct func_event *fevent, const char *name) +{ + struct func_arg *arg = fevent->last_arg; + + if (WARN_ON(!arg)) + return -EINVAL; + + arg->name = kstrdup(name, GFP_KERNEL); + if
[PATCH 12/18] tracing: Add accessing direct address from function based events
From: "Steven Rostedt (VMware)" Allow referencing any address during the function based event. The syntax is to use = For example: # echo 'do_IRQ(long total_forks=0xa2a4b4c0)' > function_events # echo 1 > events/function/enable # cat trace sshd-832 [000] d... 221639.210845: ret_from_intr->do_IRQ(total_forks=855) sshd-832 [000] d... 221639.24: ret_from_intr->do_IRQ(total_forks=855) -0 [000] d... 221639.211198: ret_from_intr->do_IRQ(total_forks=855) Signed-off-by: Steven Rostedt (VMware) --- Documentation/trace/function-based-events.rst | 40 +++- kernel/trace/trace_event_ftrace.c | 129 +- 2 files changed, 143 insertions(+), 26 deletions(-) diff --git a/Documentation/trace/function-based-events.rst b/Documentation/trace/function-based-events.rst index f18c8f3ef330..b0e6725f3032 100644 --- a/Documentation/trace/function-based-events.rst +++ b/Documentation/trace/function-based-events.rst @@ -91,7 +91,7 @@ as follows: ARGS := ARG | ARG ',' ARGS | '' - ARG := TYPE FIELD | ARG '|' ARG + ARG := TYPE FIELD | TYPE '=' ADDR | TYPE ADDR | ARG '|' ARG TYPE := ATOM | 'unsigned' ATOM @@ -107,6 +107,8 @@ as follows: OFFSET := '+' + ADDR := A hexidecimal address starting with '0x' + Where is a unique string starting with an alphabetic character and consists only of letters and numbers and underscores. @@ -267,3 +269,39 @@ Again, using gdb to find the offset of the "func" field of struct work_struct -0 [000] dNs3 6241.172004: delayed_work_timer_fn->__queue_work(cpu=128, wq=88011a010800, func=vmstat_shepherd+0x0/0xb0) worker/0:2-1689 [000] d..2 6241.172026: __queue_delayed_work->__queue_work(cpu=7, wq=88011a11da00, func=vmstat_update+0x0/0x70) -0 [005] d.s3 6241.347996: queue_work_on->__queue_work(cpu=128, wq=88011a011200, func=fb_flashcursor+0x0/0x110 [fb]) + + +Direct memory access + + +Function arguments are not the only thing that can be recorded from a function +based event. Memory addresses can also be examined. If there's a global variable +that you want to monitor via an interrupt, you can put in the address directly. + + # grep total_forks /proc/kallsyms +82354c18 B total_forks + + # echo 'do_IRQ(int total_forks=0x82354c18)' > function_events + + # echo 1 events/functions/do_IRQ/enable + # cat trace +-0 [003] d..3 337.076709: ret_from_intr->do_IRQ(total_forks=1419) +-0 [003] d..3 337.077046: ret_from_intr->do_IRQ(total_forks=1419) +-0 [003] d..3 337.077076: ret_from_intr->do_IRQ(total_forks=1420) + +Note, address notations do not affect the argument count. For instance, with + +__visible unsigned int __irq_entry do_IRQ(struct pt_regs *regs) + + # echo 'do_IRQ(int total_forks=0x82354c18, symbol regs[16])' > function_events + +Is the same as + + # echo 'do_IRQ(int total_forks=0x82354c18 | symbol regs[16])' > function_events + + # cat trace +-0 [003] d..3 653.839546: ret_from_intr->do_IRQ(total_forks=1504, regs=cpuidle_enter_state+0xb1/0x330) +-0 [003] d..3 653.906011: ret_from_intr->do_IRQ(total_forks=1504, regs=cpuidle_enter_state+0xb1/0x330) +-0 [003] d..3 655.823498: ret_from_intr->do_IRQ(total_forks=1504, regs=tick_nohz_idle_enter+0x4c/0x50) +-0 [003] d..3 655.954096: ret_from_intr->do_IRQ(total_forks=1504, regs=cpuidle_enter_state+0xb1/0x330) + diff --git a/kernel/trace/trace_event_ftrace.c b/kernel/trace/trace_event_ftrace.c index ba10177b9bd6..206114f192be 100644 --- a/kernel/trace/trace_event_ftrace.c +++ b/kernel/trace/trace_event_ftrace.c @@ -63,6 +63,8 @@ enum func_states { FUNC_STATE_BRACKET_END, FUNC_STATE_INDIRECT, FUNC_STATE_UNSIGNED, + FUNC_STATE_ADDR, + FUNC_STATE_EQUAL, FUNC_STATE_PIPE, FUNC_STATE_PLUS, FUNC_STATE_TYPE, @@ -199,6 +201,7 @@ static char *next_token(char **ptr, char *last) *str == ',' || *str == '|' || *str == '+' || + *str == '=' || *str == ')') break; } @@ -243,12 +246,39 @@ static int add_arg(struct func_event *fevent, int ftype, int unsign) arg->sign = func_type->sign; arg->offset = ALIGN(fevent->arg_offset, arg->size); arg->func_type = ftype; - arg->arg = fevent->arg_cnt; fevent->arg_offset = arg->offset + arg->size; list_add_tail(>list, >args); fevent->last_arg = arg; - fevent->arg_cnt++; + + return 0; +} + +static int update_arg_name(struct func_event *fevent, const char *name) +{ + struct func_arg *arg = fevent->last_arg; + + if (WARN_ON(!arg)) + return -EINVAL; + + arg->name = kstrdup(name, GFP_KERNEL); + if (!arg->name) + return -ENOMEM; +