[PATCH v3 14/18] tracing: probeevent: Add $argN for accessing function args

2018-02-23 Thread Masami Hiramatsu
Add $argN special fetch variable for accessing function
arguments. This allows user to trace the Nth argument easily
at the function entry.

Note that this returns most probably assignment of registers
and stacks. In some case, it may not work well. If you need
to access correct registers or stacks you should use perf-probe.

Signed-off-by: Masami Hiramatsu 
---
 Changes in v2:
  - Add $argN in README file
  - Make N start from 1 as same as auto-generate event argument
names.
 Changes in v3:
  - Show $arg in README only when this feature is supported.
---
 Documentation/trace/kprobetrace.txt |   10 ++
 kernel/trace/trace.c|4 
 kernel/trace/trace_kprobe.c |   18 +-
 kernel/trace/trace_probe.c  |   36 ++-
 kernel/trace/trace_probe.h  |9 -
 kernel/trace/trace_uprobe.c |2 +-
 6 files changed, 55 insertions(+), 24 deletions(-)

diff --git a/Documentation/trace/kprobetrace.txt 
b/Documentation/trace/kprobetrace.txt
index d49381f2e411..1d082f8ffeee 100644
--- a/Documentation/trace/kprobetrace.txt
+++ b/Documentation/trace/kprobetrace.txt
@@ -43,16 +43,18 @@ Synopsis of kprobe_events
   @SYM[+|-offs]: Fetch memory at SYM +|- offs (SYM should be a data 
symbol)
   $stackN  : Fetch Nth entry of stack (N >= 0)
   $stack   : Fetch stack address.
-  $retval  : Fetch return value.(*)
+  $argN: Fetch the Nth function argument. (N >= 1) (*1)
+  $retval  : Fetch return value.(*2)
   $comm: Fetch current task comm.
-  +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(**)
+  +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(*3)
   NAME=FETCHARG : Set NAME as the argument name of FETCHARG.
   FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types
  (u8/u16/u32/u64/s8/s16/s32/s64), hexadecimal types
  (x8/x16/x32/x64), "string" and bitfield are supported.
 
-  (*) only for return probe.
-  (**) this is useful for fetching a field of data structures.
+  (*1) only for the probe on function entry (offs == 0).
+  (*2) only for return probe.
+  (*3) this is useful for fetching a field of data structures.
 
 Types
 -
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 8f08811d15b8..bcd1fd87082d 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -4608,7 +4608,11 @@ static const char readme_msg[] =
 #endif
"\t args: =fetcharg[:type]\n"
"\t fetcharg: %, @, @[+|-],\n"
+#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
+   "\t   $stack, $stack, $retval, $comm, $arg\n"
+#else
"\t   $stack, $stack, $retval, $comm\n"
+#endif
"\t type: s8/16/32/64, u8/16/32/64, x8/16/32/64, string, symbol,\n"
"\t   b@/\n"
 #endif
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 292d5ae6d18b..e5a52b5f70ec 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -490,13 +490,15 @@ static int create_trace_kprobe(int argc, char **argv)
long offset = 0;
void *addr = NULL;
char buf[MAX_EVENT_NAME_LEN];
+   unsigned int flags = TPARG_FL_KERNEL;
 
/* argc must be >= 1 */
if (argv[0][0] == 'p')
is_return = false;
-   else if (argv[0][0] == 'r')
+   else if (argv[0][0] == 'r') {
is_return = true;
-   else if (argv[0][0] == '-')
+   flags |= TPARG_FL_RETURN;
+   } else if (argv[0][0] == '-')
is_delete = true;
else {
pr_info("Probe definition must be started with 'p', 'r' or"
@@ -579,8 +581,9 @@ static int create_trace_kprobe(int argc, char **argv)
pr_info("Failed to parse either an address or a 
symbol.\n");
return ret;
}
-   if (offset && is_return &&
-   !kprobe_on_func_entry(NULL, symbol, offset)) {
+   if (kprobe_on_func_entry(NULL, symbol, offset))
+   flags |= TPARG_FL_FENTRY;
+   if (offset && is_return && !(flags & TPARG_FL_FENTRY)) {
pr_info("Given offset is not valid for return 
probe.\n");
return -EINVAL;
}
@@ -650,7 +653,7 @@ static int create_trace_kprobe(int argc, char **argv)
 
/* Parse fetch argument */
ret = traceprobe_parse_probe_arg(arg, >tp.size, parg,
-is_return, true);
+flags);
if (ret) {
pr_info("Parse error at argument[%d]. (%d)\n", i, ret);
goto error;
@@ -890,6 +893,11 @@ process_fetch_insn(struct fetch_insn *code, struct pt_regs 
*regs, void *dest,
case FETCH_OP_COMM:

[PATCH v3 14/18] tracing: probeevent: Add $argN for accessing function args

2018-02-23 Thread Masami Hiramatsu
Add $argN special fetch variable for accessing function
arguments. This allows user to trace the Nth argument easily
at the function entry.

Note that this returns most probably assignment of registers
and stacks. In some case, it may not work well. If you need
to access correct registers or stacks you should use perf-probe.

Signed-off-by: Masami Hiramatsu 
---
 Changes in v2:
  - Add $argN in README file
  - Make N start from 1 as same as auto-generate event argument
names.
 Changes in v3:
  - Show $arg in README only when this feature is supported.
---
 Documentation/trace/kprobetrace.txt |   10 ++
 kernel/trace/trace.c|4 
 kernel/trace/trace_kprobe.c |   18 +-
 kernel/trace/trace_probe.c  |   36 ++-
 kernel/trace/trace_probe.h  |9 -
 kernel/trace/trace_uprobe.c |2 +-
 6 files changed, 55 insertions(+), 24 deletions(-)

diff --git a/Documentation/trace/kprobetrace.txt 
b/Documentation/trace/kprobetrace.txt
index d49381f2e411..1d082f8ffeee 100644
--- a/Documentation/trace/kprobetrace.txt
+++ b/Documentation/trace/kprobetrace.txt
@@ -43,16 +43,18 @@ Synopsis of kprobe_events
   @SYM[+|-offs]: Fetch memory at SYM +|- offs (SYM should be a data 
symbol)
   $stackN  : Fetch Nth entry of stack (N >= 0)
   $stack   : Fetch stack address.
-  $retval  : Fetch return value.(*)
+  $argN: Fetch the Nth function argument. (N >= 1) (*1)
+  $retval  : Fetch return value.(*2)
   $comm: Fetch current task comm.
-  +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(**)
+  +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(*3)
   NAME=FETCHARG : Set NAME as the argument name of FETCHARG.
   FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types
  (u8/u16/u32/u64/s8/s16/s32/s64), hexadecimal types
  (x8/x16/x32/x64), "string" and bitfield are supported.
 
-  (*) only for return probe.
-  (**) this is useful for fetching a field of data structures.
+  (*1) only for the probe on function entry (offs == 0).
+  (*2) only for return probe.
+  (*3) this is useful for fetching a field of data structures.
 
 Types
 -
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 8f08811d15b8..bcd1fd87082d 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -4608,7 +4608,11 @@ static const char readme_msg[] =
 #endif
"\t args: =fetcharg[:type]\n"
"\t fetcharg: %, @, @[+|-],\n"
+#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
+   "\t   $stack, $stack, $retval, $comm, $arg\n"
+#else
"\t   $stack, $stack, $retval, $comm\n"
+#endif
"\t type: s8/16/32/64, u8/16/32/64, x8/16/32/64, string, symbol,\n"
"\t   b@/\n"
 #endif
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 292d5ae6d18b..e5a52b5f70ec 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -490,13 +490,15 @@ static int create_trace_kprobe(int argc, char **argv)
long offset = 0;
void *addr = NULL;
char buf[MAX_EVENT_NAME_LEN];
+   unsigned int flags = TPARG_FL_KERNEL;
 
/* argc must be >= 1 */
if (argv[0][0] == 'p')
is_return = false;
-   else if (argv[0][0] == 'r')
+   else if (argv[0][0] == 'r') {
is_return = true;
-   else if (argv[0][0] == '-')
+   flags |= TPARG_FL_RETURN;
+   } else if (argv[0][0] == '-')
is_delete = true;
else {
pr_info("Probe definition must be started with 'p', 'r' or"
@@ -579,8 +581,9 @@ static int create_trace_kprobe(int argc, char **argv)
pr_info("Failed to parse either an address or a 
symbol.\n");
return ret;
}
-   if (offset && is_return &&
-   !kprobe_on_func_entry(NULL, symbol, offset)) {
+   if (kprobe_on_func_entry(NULL, symbol, offset))
+   flags |= TPARG_FL_FENTRY;
+   if (offset && is_return && !(flags & TPARG_FL_FENTRY)) {
pr_info("Given offset is not valid for return 
probe.\n");
return -EINVAL;
}
@@ -650,7 +653,7 @@ static int create_trace_kprobe(int argc, char **argv)
 
/* Parse fetch argument */
ret = traceprobe_parse_probe_arg(arg, >tp.size, parg,
-is_return, true);
+flags);
if (ret) {
pr_info("Parse error at argument[%d]. (%d)\n", i, ret);
goto error;
@@ -890,6 +893,11 @@ process_fetch_insn(struct fetch_insn *code, struct pt_regs 
*regs, void *dest,
case FETCH_OP_COMM:
val = (unsigned