uprobes tracer: Add support for @ADDR, @stackN, dereference, bitfield arguments
PATCH 1/1 uprobes tracer: Add support for @ADDR, @stackN, dereference, bitfield arguments
Add support for @ADDR, @stackN, dereference, bitfield arguments. Uprobes tracer supported only register argument. @SYMBOL, $retval, $stack are not supported. because a symbol address and whether function starts at a given address can't be known.
Uprobes tracer and kprobes tracer have their own fetch type information tables and fetch type functions. But they share printing type functions and some fetch type functions for register, dereference, and bitfield. The common functions are defined in trace_probe.c.
---
v2 - separate fetch type functions for uprobes and kprobes tracer v3 - define macro for fetch type table definition and fix CHECK_FETCH_FUNCS and string dereference bugs
--- kernel/trace/trace_kprobe.c | 97 +++++++++- kernel/trace/trace_probe.c | 434 ++++++++++++++++--------------------------- kernel/trace/trace_probe.h | 140 +++++++++++++- kernel/trace/trace_uprobe.c | 166 ++++++++++++++++- 4 files changed, 546 insertions(+), 291 deletions(-)
kernel/trace/trace_kprobe.c +95 -2
@@ -24,10 +24,102 @@#define KPROBE_EVENT_SYSTEM "kprobes" +/* Stack fetch function */ +#define DEFINE_FETCH_stack (type) \ +static __kprobes void FETCH_FUNC_NAME(stack, type)(struct pt_regs *regs,\ + void *offset, void *dest) \ +{ \ + *(type *)dest = (type)regs_get_kernel_stack_nth(regs, \ + (unsigned int)((unsigned long)offset)); \ +} +DEFINE_BASIC_FETCH_FUNCS(stack) +#define fetch_stack_string NULL +#define fetch_stack_string_size NULL + +/* Memory fetch function */ +#define DEFINE_FETCH_memory (type) \ +static __kprobes void FETCH_FUNC_NAME(memory, type)(struct pt_regs *regs,\ + void *addr, void *dest) \ +{ \ + type retval; \ + if (probe_kernel_address(addr, retval)) \ + *(type *)dest = 0; \ + else \ + *(type *)dest = retval; \ +} +DEFINE_BASIC_FETCH_FUNCS (memory) + +/* +* Fetch a null-terminated string. Caller MUST set *(u32 *)dest with max +* length and relative data location. +*/ +static __kprobes void FETCH_FUNC_NAME(memory, string)(struct pt_regs *regs, +void *addr,void *dest) +{ +long ret; +int maxlen =get_rloc_len (*(u32 *)dest); +u8 *dst =get_rloc_data (dest); +u8 *src = addr; +mm_segment_t old_fs =get_fs (); + +if (!maxlen) +return ; + +/* +* Try to get string again, since the string can be changed while +* probing. +*/ +set_fs (KERNEL_DS ); +pagefault_disable (); + +do + ret =__copy_from_user_inatomic (dst++, src++,1 ); +while (dst[-1 ] && ret ==0 && src - (u8 *)addr < maxlen); + + dst[-1 ] ='\0' ; +pagefault_enable (); +set_fs (old_fs); + +if (ret <0 ) {/* Failed to fetch string */ + ((u8 *)get_rloc_data (dest))[0 ] ='\0' ; + *(u32 *)dest =make_data_rloc (0 ,get_rloc_offs (*(u32 *)dest)); + }else { + *(u32 *)dest =make_data_rloc (src - (u8 *)addr, +get_rloc_offs (*(u32 *)dest)); + } +} + +/* Return the length of string -- including null terminal byte */ +static __kprobes void FETCH_FUNC_NAME (memory ,string_size )(struct pt_regs *regs, +void *addr,void *dest) +{ +mm_segment_t old_fs; +int ret, len =0 ; +u8 c; + + old_fs =get_fs (); +set_fs (KERNEL_DS ); +pagefault_disable (); + +do { + ret =__copy_from_user_inatomic (&c, (u8 *)addr + len,1 ); + len++; + }while (c && ret ==0 && len <MAX_STRING_SIZE ); + +pagefault_enable (); +set_fs (old_fs); + +if (ret <0 )/* Failed to check the length */ + *(u32 *)dest =0 ; +else + *(u32 *)dest = len; +} + +static DEFINE_FETCH_TYPE_TABLE (fetch_type_table); +/** * Kprobe event core functions */ -struct trace_probe {struct list_head list;struct kretprobe rp;/* Use rp.kp for kprobe use */
@@ -525,7 +617,8 @@ static int create_trace_probe(int argc, char **argv)/* Parse fetch argument */ ret =traceprobe_parse_probe_arg (arg, &tp->size, &tp->args[i], - is_return, true); + is_return, true, + fetch_type_table);if (ret) {pr_info ("Parse error at argument[%d]. (%d)\n" , i, ret); goto error;
kernel/trace/trace_probe.c +158 -276
686 lines not on this page · raw message
kernel/trace/trace_probe.h +134 -6
179 lines not on this page · raw message
kernel/trace/trace_uprobe.c +159 -7
202 lines not on this page · raw message
Signature · 1 line
1.7.10.4
Hi Hyeoncheol,
Thank you for working on uprobe enhancement!
First of all, I've failed to apply this on the latest tip tree because of conflict with below patch.
http://marc.info/?l=linux-kernel&m=134869014622386
Quoted 4 lines · Hyeoncheol Lee
Add support for @ADDR, @stackN, dereference, bitfield arguments. Uprobes tracer supported only register argument. @SYMBOL, $retval, $stack are not supported. because a symbol address and whether function starts at a given address can't be known.
I see why the @SYMBOL is not supported, but I can't understand the reason why $retval and $stack aren't supported. At least we can support $stack, isn't it?
Quoted 4 lines
Uprobes tracer and kprobes tracer have their own fetch type information tables and fetch type functions. But they share printing type functions and some fetch type functions for register, dereference, and bitfield. The common functions are defined in
trace_probe.c.
By the way, for easy to review and debug, please separate this into several patches. This seems to do (1) moving some interfaces out from trace_probe.c, (2) add fetch_size/fetch members into recursive fetch function data, (3) introduce userspace memory fetching functions, and some cleanups.
So, could you split those parts? unless, it is hard to maintain the source code.
Thank you,
Signature · 4 lines
Masami HIRAMATSU IT Management Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]