Re: [PATCH 12/18] tracing: Add accessing direct address from function based events

2018-02-12 Thread Steven Rostedt
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

2018-02-12 Thread Steven Rostedt
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

2018-02-12 Thread Masami Hiramatsu
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

2018-02-12 Thread Masami Hiramatsu
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

2018-02-11 Thread Namhyung Kim
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

2018-02-11 Thread Namhyung Kim
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

2018-02-09 Thread Steven Rostedt
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
   

Re: [PATCH 12/18] tracing: Add accessing direct address from function based events

2018-02-09 Thread Steven Rostedt
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

2018-02-08 Thread Steven Rostedt
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

2018-02-08 Thread Steven Rostedt
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

2018-02-08 Thread Namhyung Kim
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

2018-02-08 Thread Namhyung Kim
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

2018-02-02 Thread Steven Rostedt
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

2018-02-02 Thread Steven Rostedt
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;
+