tracing/kprobes: Support perf-style return probe
authorMasami Hiramatsu <mhiramat@kernel.org>
Thu, 10 Sep 2020 08:55:35 +0000 (17:55 +0900)
committerSteven Rostedt (VMware) <rostedt@goodmis.org>
Tue, 22 Sep 2020 01:06:03 +0000 (21:06 -0400)
Support perf-style return probe ("SYMBOL%return") for kprobe events.
This will allow boot-time tracing user to define a return probe event.

Link: https://lkml.kernel.org/r/159972813535.428528.4437029657208468954.stgit@devnote2
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
kernel/trace/trace.c
kernel/trace/trace_kprobe.c
kernel/trace/trace_probe.h

index 55b8298..ca6da46 100644 (file)
@@ -5122,7 +5122,7 @@ static const char readme_msg[] =
        "\t           -:[<group>/]<event>\n"
 #ifdef CONFIG_KPROBE_EVENTS
        "\t    place: [<module>:]<symbol>[+<offset>]|<memaddr>\n"
-  "place (kretprobe): [<module>:]<symbol>[+<offset>]|<memaddr>\n"
+  "place (kretprobe): [<module>:]<symbol>[+<offset>]%return|<memaddr>\n"
 #endif
 #ifdef CONFIG_UPROBE_EVENTS
   "   place (uprobe): <path>:<offset>[(ref_ctr_offset)]\n"
index f8e4692..9d46415 100644 (file)
@@ -718,6 +718,9 @@ static int trace_kprobe_create(int argc, const char *argv[])
         *      p[:[GRP/]EVENT] [MOD:]KSYM[+OFFS]|KADDR [FETCHARGS]
         *  - Add kretprobe:
         *      r[MAXACTIVE][:[GRP/]EVENT] [MOD:]KSYM[+0] [FETCHARGS]
+        *    Or
+        *      p:[GRP/]EVENT] [MOD:]KSYM[+0]%return [FETCHARGS]
+        *
         * Fetch args:
         *  $retval     : fetch return value
         *  $stack      : fetch stack address
@@ -747,7 +750,6 @@ static int trace_kprobe_create(int argc, const char *argv[])
        switch (argv[0][0]) {
        case 'r':
                is_return = true;
-               flags |= TPARG_FL_RETURN;
                break;
        case 'p':
                break;
@@ -805,12 +807,26 @@ static int trace_kprobe_create(int argc, const char *argv[])
                symbol = kstrdup(argv[1], GFP_KERNEL);
                if (!symbol)
                        return -ENOMEM;
+
+               tmp = strchr(symbol, '%');
+               if (tmp) {
+                       if (!strcmp(tmp, "%return")) {
+                               *tmp = '\0';
+                               is_return = true;
+                       } else {
+                               trace_probe_log_err(tmp - symbol, BAD_ADDR_SUFFIX);
+                               goto parse_error;
+                       }
+               }
+
                /* TODO: support .init module functions */
                ret = traceprobe_split_symbol_offset(symbol, &offset);
                if (ret || offset < 0 || offset > UINT_MAX) {
                        trace_probe_log_err(0, BAD_PROBE_ADDR);
                        goto parse_error;
                }
+               if (is_return)
+                       flags |= TPARG_FL_RETURN;
                if (kprobe_on_func_entry(NULL, symbol, offset))
                        flags |= TPARG_FL_FENTRY;
                if (offset && is_return && !(flags & TPARG_FL_FENTRY)) {
index a22b628..04d0098 100644 (file)
@@ -404,6 +404,7 @@ extern int traceprobe_define_arg_fields(struct trace_event_call *event_call,
        C(MAXACT_TOO_BIG,       "Maxactive is too big"),                \
        C(BAD_PROBE_ADDR,       "Invalid probed address or symbol"),    \
        C(BAD_RETPROBE,         "Retprobe address must be an function entry"), \
+       C(BAD_ADDR_SUFFIX,      "Invalid probed address suffix"), \
        C(NO_GROUP_NAME,        "Group name is not specified"),         \
        C(GROUP_TOO_LONG,       "Group name is too long"),              \
        C(BAD_GROUP_NAME,       "Group name must follow the same rules as C identifiers"), \