diff options
-rw-r--r-- | Documentation/trace/kprobetrace.txt | 20 | ||||
-rw-r--r-- | kernel/trace/trace_kprobe.c | 60 |
2 files changed, 47 insertions, 33 deletions
diff --git a/Documentation/trace/kprobetrace.txt b/Documentation/trace/kprobetrace.txt index 9b8f7c6040a7..33f531858c56 100644 --- a/Documentation/trace/kprobetrace.txt +++ b/Documentation/trace/kprobetrace.txt | |||
@@ -36,13 +36,13 @@ Synopsis of kprobe_events | |||
36 | 36 | ||
37 | FETCHARGS : Arguments. Each probe can have up to 128 args. | 37 | FETCHARGS : Arguments. Each probe can have up to 128 args. |
38 | %REG : Fetch register REG | 38 | %REG : Fetch register REG |
39 | sN : Fetch Nth entry of stack (N >= 0) | ||
40 | sa : Fetch stack address. | ||
41 | @ADDR : Fetch memory at ADDR (ADDR should be in kernel) | 39 | @ADDR : Fetch memory at ADDR (ADDR should be in kernel) |
42 | @SYM[+|-offs] : Fetch memory at SYM +|- offs (SYM should be a data symbol) | 40 | @SYM[+|-offs] : Fetch memory at SYM +|- offs (SYM should be a data symbol) |
43 | aN : Fetch function argument. (N >= 0)(*) | 41 | $sN : Fetch Nth entry of stack (N >= 0) |
44 | rv : Fetch return value.(**) | 42 | $sa : Fetch stack address. |
45 | ra : Fetch return address.(**) | 43 | $aN : Fetch function argument. (N >= 0)(*) |
44 | $rv : Fetch return value.(**) | ||
45 | $ra : Fetch return address.(**) | ||
46 | +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(***) | 46 | +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(***) |
47 | NAME=FETCHARG: Set NAME as the argument name of FETCHARG. | 47 | NAME=FETCHARG: Set NAME as the argument name of FETCHARG. |
48 | 48 | ||
@@ -85,13 +85,13 @@ Usage examples | |||
85 | To add a probe as a new event, write a new definition to kprobe_events | 85 | To add a probe as a new event, write a new definition to kprobe_events |
86 | as below. | 86 | as below. |
87 | 87 | ||
88 | echo p:myprobe do_sys_open dfd=a0 filename=a1 flags=a2 mode=a3 > /sys/kernel/debug/tracing/kprobe_events | 88 | echo p:myprobe do_sys_open dfd=$a0 filename=$a1 flags=$a2 mode=$a3 > /sys/kernel/debug/tracing/kprobe_events |
89 | 89 | ||
90 | This sets a kprobe on the top of do_sys_open() function with recording | 90 | This sets a kprobe on the top of do_sys_open() function with recording |
91 | 1st to 4th arguments as "myprobe" event. As this example shows, users can | 91 | 1st to 4th arguments as "myprobe" event. As this example shows, users can |
92 | choose more familiar names for each arguments. | 92 | choose more familiar names for each arguments. |
93 | 93 | ||
94 | echo r:myretprobe do_sys_open rv ra >> /sys/kernel/debug/tracing/kprobe_events | 94 | echo r:myretprobe do_sys_open $rv $ra >> /sys/kernel/debug/tracing/kprobe_events |
95 | 95 | ||
96 | This sets a kretprobe on the return point of do_sys_open() function with | 96 | This sets a kretprobe on the return point of do_sys_open() function with |
97 | recording return value and return address as "myretprobe" event. | 97 | recording return value and return address as "myretprobe" event. |
@@ -138,11 +138,11 @@ events, you need to enable it. | |||
138 | # TASK-PID CPU# TIMESTAMP FUNCTION | 138 | # TASK-PID CPU# TIMESTAMP FUNCTION |
139 | # | | | | | | 139 | # | | | | | |
140 | <...>-1447 [001] 1038282.286875: myprobe: (do_sys_open+0x0/0xd6) dfd=3 filename=7fffd1ec4440 flags=8000 mode=0 | 140 | <...>-1447 [001] 1038282.286875: myprobe: (do_sys_open+0x0/0xd6) dfd=3 filename=7fffd1ec4440 flags=8000 mode=0 |
141 | <...>-1447 [001] 1038282.286878: myretprobe: (sys_openat+0xc/0xe <- do_sys_open) rv=fffffffffffffffe ra=ffffffff81367a3a | 141 | <...>-1447 [001] 1038282.286878: myretprobe: (sys_openat+0xc/0xe <- do_sys_open) $rv=fffffffffffffffe $ra=ffffffff81367a3a |
142 | <...>-1447 [001] 1038282.286885: myprobe: (do_sys_open+0x0/0xd6) dfd=ffffff9c filename=40413c flags=8000 mode=1b6 | 142 | <...>-1447 [001] 1038282.286885: myprobe: (do_sys_open+0x0/0xd6) dfd=ffffff9c filename=40413c flags=8000 mode=1b6 |
143 | <...>-1447 [001] 1038282.286915: myretprobe: (sys_open+0x1b/0x1d <- do_sys_open) rv=3 ra=ffffffff81367a3a | 143 | <...>-1447 [001] 1038282.286915: myretprobe: (sys_open+0x1b/0x1d <- do_sys_open) $rv=3 $ra=ffffffff81367a3a |
144 | <...>-1447 [001] 1038282.286969: myprobe: (do_sys_open+0x0/0xd6) dfd=ffffff9c filename=4041c6 flags=98800 mode=10 | 144 | <...>-1447 [001] 1038282.286969: myprobe: (do_sys_open+0x0/0xd6) dfd=ffffff9c filename=4041c6 flags=98800 mode=10 |
145 | <...>-1447 [001] 1038282.286976: myretprobe: (sys_open+0x1b/0x1d <- do_sys_open) rv=3 ra=ffffffff81367a3a | 145 | <...>-1447 [001] 1038282.286976: myretprobe: (sys_open+0x1b/0x1d <- do_sys_open) $rv=3 $ra=ffffffff81367a3a |
146 | 146 | ||
147 | 147 | ||
148 | Each line shows when the kernel hits an event, and <- SYMBOL means kernel | 148 | Each line shows when the kernel hits an event, and <- SYMBOL means kernel |
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 97309d4714f7..f63ead0cc5cf 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
@@ -220,24 +220,24 @@ static int probe_arg_string(char *buf, size_t n, struct fetch_func *ff) | |||
220 | int ret = -EINVAL; | 220 | int ret = -EINVAL; |
221 | 221 | ||
222 | if (ff->func == fetch_argument) | 222 | if (ff->func == fetch_argument) |
223 | ret = snprintf(buf, n, "a%lu", (unsigned long)ff->data); | 223 | ret = snprintf(buf, n, "$a%lu", (unsigned long)ff->data); |
224 | else if (ff->func == fetch_register) { | 224 | else if (ff->func == fetch_register) { |
225 | const char *name; | 225 | const char *name; |
226 | name = regs_query_register_name((unsigned int)((long)ff->data)); | 226 | name = regs_query_register_name((unsigned int)((long)ff->data)); |
227 | ret = snprintf(buf, n, "%%%s", name); | 227 | ret = snprintf(buf, n, "%%%s", name); |
228 | } else if (ff->func == fetch_stack) | 228 | } else if (ff->func == fetch_stack) |
229 | ret = snprintf(buf, n, "s%lu", (unsigned long)ff->data); | 229 | ret = snprintf(buf, n, "$s%lu", (unsigned long)ff->data); |
230 | else if (ff->func == fetch_memory) | 230 | else if (ff->func == fetch_memory) |
231 | ret = snprintf(buf, n, "@0x%p", ff->data); | 231 | ret = snprintf(buf, n, "@0x%p", ff->data); |
232 | else if (ff->func == fetch_symbol) { | 232 | else if (ff->func == fetch_symbol) { |
233 | struct symbol_cache *sc = ff->data; | 233 | struct symbol_cache *sc = ff->data; |
234 | ret = snprintf(buf, n, "@%s%+ld", sc->symbol, sc->offset); | 234 | ret = snprintf(buf, n, "@%s%+ld", sc->symbol, sc->offset); |
235 | } else if (ff->func == fetch_retvalue) | 235 | } else if (ff->func == fetch_retvalue) |
236 | ret = snprintf(buf, n, "rv"); | 236 | ret = snprintf(buf, n, "$rv"); |
237 | else if (ff->func == fetch_ip) | 237 | else if (ff->func == fetch_ip) |
238 | ret = snprintf(buf, n, "ra"); | 238 | ret = snprintf(buf, n, "$ra"); |
239 | else if (ff->func == fetch_stack_address) | 239 | else if (ff->func == fetch_stack_address) |
240 | ret = snprintf(buf, n, "sa"); | 240 | ret = snprintf(buf, n, "$sa"); |
241 | else if (ff->func == fetch_indirect) { | 241 | else if (ff->func == fetch_indirect) { |
242 | struct indirect_fetch_data *id = ff->data; | 242 | struct indirect_fetch_data *id = ff->data; |
243 | size_t l = 0; | 243 | size_t l = 0; |
@@ -429,12 +429,10 @@ static int split_symbol_offset(char *symbol, unsigned long *offset) | |||
429 | #define PARAM_MAX_ARGS 16 | 429 | #define PARAM_MAX_ARGS 16 |
430 | #define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long)) | 430 | #define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long)) |
431 | 431 | ||
432 | static int parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) | 432 | static int parse_probe_vars(char *arg, struct fetch_func *ff, int is_return) |
433 | { | 433 | { |
434 | int ret = 0; | 434 | int ret = 0; |
435 | unsigned long param; | 435 | unsigned long param; |
436 | long offset; | ||
437 | char *tmp; | ||
438 | 436 | ||
439 | switch (arg[0]) { | 437 | switch (arg[0]) { |
440 | case 'a': /* argument */ | 438 | case 'a': /* argument */ |
@@ -456,14 +454,6 @@ static int parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) | |||
456 | } else | 454 | } else |
457 | ret = -EINVAL; | 455 | ret = -EINVAL; |
458 | break; | 456 | break; |
459 | case '%': /* named register */ | ||
460 | ret = regs_query_register_offset(arg + 1); | ||
461 | if (ret >= 0) { | ||
462 | ff->func = fetch_register; | ||
463 | ff->data = (void *)(unsigned long)ret; | ||
464 | ret = 0; | ||
465 | } | ||
466 | break; | ||
467 | case 's': /* stack */ | 457 | case 's': /* stack */ |
468 | if (arg[1] == 'a') { | 458 | if (arg[1] == 'a') { |
469 | ff->func = fetch_stack_address; | 459 | ff->func = fetch_stack_address; |
@@ -478,6 +468,31 @@ static int parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) | |||
478 | } | 468 | } |
479 | } | 469 | } |
480 | break; | 470 | break; |
471 | default: | ||
472 | ret = -EINVAL; | ||
473 | } | ||
474 | return ret; | ||
475 | } | ||
476 | |||
477 | static int parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) | ||
478 | { | ||
479 | int ret = 0; | ||
480 | unsigned long param; | ||
481 | long offset; | ||
482 | char *tmp; | ||
483 | |||
484 | switch (arg[0]) { | ||
485 | case '$': | ||
486 | ret = parse_probe_vars(arg + 1, ff, is_return); | ||
487 | break; | ||
488 | case '%': /* named register */ | ||
489 | ret = regs_query_register_offset(arg + 1); | ||
490 | if (ret >= 0) { | ||
491 | ff->func = fetch_register; | ||
492 | ff->data = (void *)(unsigned long)ret; | ||
493 | ret = 0; | ||
494 | } | ||
495 | break; | ||
481 | case '@': /* memory or symbol */ | 496 | case '@': /* memory or symbol */ |
482 | if (isdigit(arg[1])) { | 497 | if (isdigit(arg[1])) { |
483 | ret = strict_strtoul(arg + 1, 0, ¶m); | 498 | ret = strict_strtoul(arg + 1, 0, ¶m); |
@@ -489,8 +504,7 @@ static int parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) | |||
489 | ret = split_symbol_offset(arg + 1, &offset); | 504 | ret = split_symbol_offset(arg + 1, &offset); |
490 | if (ret) | 505 | if (ret) |
491 | break; | 506 | break; |
492 | ff->data = alloc_symbol_cache(arg + 1, | 507 | ff->data = alloc_symbol_cache(arg + 1, offset); |
493 | offset); | ||
494 | if (ff->data) | 508 | if (ff->data) |
495 | ff->func = fetch_symbol; | 509 | ff->func = fetch_symbol; |
496 | else | 510 | else |
@@ -544,11 +558,11 @@ static int create_trace_probe(int argc, char **argv) | |||
544 | * - Add kprobe: p[:[GRP/]EVENT] KSYM[+OFFS]|KADDR [FETCHARGS] | 558 | * - Add kprobe: p[:[GRP/]EVENT] KSYM[+OFFS]|KADDR [FETCHARGS] |
545 | * - Add kretprobe: r[:[GRP/]EVENT] KSYM[+0] [FETCHARGS] | 559 | * - Add kretprobe: r[:[GRP/]EVENT] KSYM[+0] [FETCHARGS] |
546 | * Fetch args: | 560 | * Fetch args: |
547 | * aN : fetch Nth of function argument. (N:0-) | 561 | * $aN : fetch Nth of function argument. (N:0-) |
548 | * rv : fetch return value | 562 | * $rv : fetch return value |
549 | * ra : fetch return address | 563 | * $ra : fetch return address |
550 | * sa : fetch stack address | 564 | * $sa : fetch stack address |
551 | * sN : fetch Nth of stack (N:0-) | 565 | * $sN : fetch Nth of stack (N:0-) |
552 | * @ADDR : fetch memory at ADDR (ADDR should be in kernel) | 566 | * @ADDR : fetch memory at ADDR (ADDR should be in kernel) |
553 | * @SYM[+|-offs] : fetch memory at SYM +|- offs (SYM is a data symbol) | 567 | * @SYM[+|-offs] : fetch memory at SYM +|- offs (SYM is a data symbol) |
554 | * %REG : fetch register REG | 568 | * %REG : fetch register REG |