aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNamhyung Kim <namhyung.kim@lge.com>2013-07-03 05:34:23 -0400
committerSteven Rostedt <rostedt@goodmis.org>2014-01-02 20:56:21 -0500
commitb079d374fd84637aba4b825a329e794990b7b486 (patch)
tree693970c6860735ade0842439ba67cc28a42e1dae
parentdcad1a204f72624796ae83359403898d10393b9c (diff)
tracing/uprobes: Add support for full argument access methods
Enable to fetch other types of argument for the uprobes. IOW, we can access stack, memory, deref, bitfield and retval from uprobes now. The format for the argument types are same as kprobes (but @SYMBOL type is not supported for uprobes), i.e: @ADDR : Fetch memory at ADDR $stackN : Fetch Nth entry of stack (N >= 0) $stack : Fetch stack address $retval : Fetch return value +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address Note that the retval only can be used with uretprobes. Original-patch-by: Hyeoncheol Lee <cheol.lee@lge.com> Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Acked-by: Oleg Nesterov <oleg@redhat.com> Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Cc: Oleg Nesterov <oleg@redhat.com> Cc: zhangwei(Jovi) <jovi.zhangwei@huawei.com> Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net> Signed-off-by: Hyeoncheol Lee <cheol.lee@lge.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
-rw-r--r--Documentation/trace/uprobetracer.txt25
-rw-r--r--kernel/trace/trace_probe.c34
2 files changed, 47 insertions, 12 deletions
diff --git a/Documentation/trace/uprobetracer.txt b/Documentation/trace/uprobetracer.txt
index 8f1a8b8956fc..6e5cff263e2b 100644
--- a/Documentation/trace/uprobetracer.txt
+++ b/Documentation/trace/uprobetracer.txt
@@ -31,6 +31,31 @@ Synopsis of uprobe_tracer
31 31
32 FETCHARGS : Arguments. Each probe can have up to 128 args. 32 FETCHARGS : Arguments. Each probe can have up to 128 args.
33 %REG : Fetch register REG 33 %REG : Fetch register REG
34 @ADDR : Fetch memory at ADDR (ADDR should be in userspace)
35 $stackN : Fetch Nth entry of stack (N >= 0)
36 $stack : Fetch stack address.
37 $retval : Fetch return value.(*)
38 +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(**)
39 NAME=FETCHARG : Set NAME as the argument name of FETCHARG.
40 FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types
41 (u8/u16/u32/u64/s8/s16/s32/s64), "string" and bitfield
42 are supported.
43
44 (*) only for return probe.
45 (**) this is useful for fetching a field of data structures.
46
47Types
48-----
49Several types are supported for fetch-args. Uprobe tracer will access memory
50by given type. Prefix 's' and 'u' means those types are signed and unsigned
51respectively. Traced arguments are shown in decimal (signed) or hex (unsigned).
52String type is a special type, which fetches a "null-terminated" string from
53user space.
54Bitfield is another special type, which takes 3 parameters, bit-width, bit-
55offset, and container-size (usually 32). The syntax is;
56
57 b<bit-width>@<bit-offset>/<container-size>
58
34 59
35Event Profiling 60Event Profiling
36--------------- 61---------------
diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c
index 8f7a2b6d389d..a130d612e705 100644
--- a/kernel/trace/trace_probe.c
+++ b/kernel/trace/trace_probe.c
@@ -255,12 +255,18 @@ fail:
255} 255}
256 256
257/* Special function : only accept unsigned long */ 257/* Special function : only accept unsigned long */
258static __kprobes void fetch_stack_address(struct pt_regs *regs, 258static __kprobes void fetch_kernel_stack_address(struct pt_regs *regs,
259 void *dummy, void *dest) 259 void *dummy, void *dest)
260{ 260{
261 *(unsigned long *)dest = kernel_stack_pointer(regs); 261 *(unsigned long *)dest = kernel_stack_pointer(regs);
262} 262}
263 263
264static __kprobes void fetch_user_stack_address(struct pt_regs *regs,
265 void *dummy, void *dest)
266{
267 *(unsigned long *)dest = user_stack_pointer(regs);
268}
269
264static fetch_func_t get_fetch_size_function(const struct fetch_type *type, 270static fetch_func_t get_fetch_size_function(const struct fetch_type *type,
265 fetch_func_t orig_fn, 271 fetch_func_t orig_fn,
266 const struct fetch_type *ftbl) 272 const struct fetch_type *ftbl)
@@ -305,7 +311,8 @@ int traceprobe_split_symbol_offset(char *symbol, unsigned long *offset)
305#define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long)) 311#define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long))
306 312
307static int parse_probe_vars(char *arg, const struct fetch_type *t, 313static int parse_probe_vars(char *arg, const struct fetch_type *t,
308 struct fetch_param *f, bool is_return) 314 struct fetch_param *f, bool is_return,
315 bool is_kprobe)
309{ 316{
310 int ret = 0; 317 int ret = 0;
311 unsigned long param; 318 unsigned long param;
@@ -317,13 +324,16 @@ static int parse_probe_vars(char *arg, const struct fetch_type *t,
317 ret = -EINVAL; 324 ret = -EINVAL;
318 } else if (strncmp(arg, "stack", 5) == 0) { 325 } else if (strncmp(arg, "stack", 5) == 0) {
319 if (arg[5] == '\0') { 326 if (arg[5] == '\0') {
320 if (strcmp(t->name, DEFAULT_FETCH_TYPE_STR) == 0) 327 if (strcmp(t->name, DEFAULT_FETCH_TYPE_STR))
321 f->fn = fetch_stack_address; 328 return -EINVAL;
329
330 if (is_kprobe)
331 f->fn = fetch_kernel_stack_address;
322 else 332 else
323 ret = -EINVAL; 333 f->fn = fetch_user_stack_address;
324 } else if (isdigit(arg[5])) { 334 } else if (isdigit(arg[5])) {
325 ret = kstrtoul(arg + 5, 10, &param); 335 ret = kstrtoul(arg + 5, 10, &param);
326 if (ret || param > PARAM_MAX_STACK) 336 if (ret || (is_kprobe && param > PARAM_MAX_STACK))
327 ret = -EINVAL; 337 ret = -EINVAL;
328 else { 338 else {
329 f->fn = t->fetch[FETCH_MTD_stack]; 339 f->fn = t->fetch[FETCH_MTD_stack];
@@ -350,13 +360,9 @@ static int parse_probe_arg(char *arg, const struct fetch_type *t,
350 ftbl = is_kprobe ? kprobes_fetch_type_table : uprobes_fetch_type_table; 360 ftbl = is_kprobe ? kprobes_fetch_type_table : uprobes_fetch_type_table;
351 BUG_ON(ftbl == NULL); 361 BUG_ON(ftbl == NULL);
352 362
353 /* Until uprobe_events supports only reg arguments */
354 if (!is_kprobe && arg[0] != '%')
355 return -EINVAL;
356
357 switch (arg[0]) { 363 switch (arg[0]) {
358 case '$': 364 case '$':
359 ret = parse_probe_vars(arg + 1, t, f, is_return); 365 ret = parse_probe_vars(arg + 1, t, f, is_return, is_kprobe);
360 break; 366 break;
361 367
362 case '%': /* named register */ 368 case '%': /* named register */
@@ -377,6 +383,10 @@ static int parse_probe_arg(char *arg, const struct fetch_type *t,
377 f->fn = t->fetch[FETCH_MTD_memory]; 383 f->fn = t->fetch[FETCH_MTD_memory];
378 f->data = (void *)param; 384 f->data = (void *)param;
379 } else { 385 } else {
386 /* uprobes don't support symbols */
387 if (!is_kprobe)
388 return -EINVAL;
389
380 ret = traceprobe_split_symbol_offset(arg + 1, &offset); 390 ret = traceprobe_split_symbol_offset(arg + 1, &offset);
381 if (ret) 391 if (ret)
382 break; 392 break;