Skip to contentSkip to conversation

uprobes tracer: Add support for @ADDR, @stackN, dereference, bitfield arguments

PATCH In review Hyeoncheol Lee 2 participants 2 messages Nov 14, 2012 – Nov 16, 2012 Tracing

lore
Share & tools
lore
#0 lore raw

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.

Cc Masami Hiramatsu <[email protected]>
Cc Srikar Dronamraju <[email protected]>

---
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
index 1a21170..676f514 100644
@@ -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
#1 lore raw

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]