Merge branch 'perf' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 into perf/core
diff --git a/Documentation/trace/kprobetrace.txt b/Documentation/trace/kprobetrace.txt
index a9100b2..ec94748 100644
--- a/Documentation/trace/kprobetrace.txt
+++ b/Documentation/trace/kprobetrace.txt
@@ -40,7 +40,9 @@
   $stack	: Fetch stack address.
   $retval	: Fetch return value.(*)
   +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(**)
-  NAME=FETCHARG: Set NAME as the argument name of FETCHARG.
+  NAME=FETCHARG : Set NAME as the argument name of FETCHARG.
+  FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types
+		  (u8/u16/u32/u64/s8/s16/s32/s64) are supported.
 
   (*) only for return probe.
   (**) this is useful for fetching a field of data structures.
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index bec2c97..3ebdb6b 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -102,29 +102,17 @@
 	long			ret;
 };
 
-struct kprobe_trace_entry {
+struct kprobe_trace_entry_head {
 	struct trace_entry	ent;
 	unsigned long		ip;
-	int			nargs;
-	unsigned long		args[];
 };
 
-#define SIZEOF_KPROBE_TRACE_ENTRY(n)			\
-	(offsetof(struct kprobe_trace_entry, args) +	\
-	(sizeof(unsigned long) * (n)))
-
-struct kretprobe_trace_entry {
+struct kretprobe_trace_entry_head {
 	struct trace_entry	ent;
 	unsigned long		func;
 	unsigned long		ret_ip;
-	int			nargs;
-	unsigned long		args[];
 };
 
-#define SIZEOF_KRETPROBE_TRACE_ENTRY(n)			\
-	(offsetof(struct kretprobe_trace_entry, args) +	\
-	(sizeof(unsigned long) * (n)))
-
 /*
  * trace_flag_type is an enumeration that holds different
  * states when a trace occurs. These are:
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 1251e36..a751432 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -29,6 +29,8 @@
 #include <linux/ctype.h>
 #include <linux/ptrace.h>
 #include <linux/perf_event.h>
+#include <linux/stringify.h>
+#include <asm/bitsperlong.h>
 
 #include "trace.h"
 #include "trace_output.h"
@@ -40,7 +42,6 @@
 
 /* Reserved field names */
 #define FIELD_STRING_IP "__probe_ip"
-#define FIELD_STRING_NARGS "__probe_nargs"
 #define FIELD_STRING_RETIP "__probe_ret_ip"
 #define FIELD_STRING_FUNC "__probe_func"
 
@@ -52,56 +53,102 @@
 	"common_tgid",
 	"common_lock_depth",
 	FIELD_STRING_IP,
-	FIELD_STRING_NARGS,
 	FIELD_STRING_RETIP,
 	FIELD_STRING_FUNC,
 };
 
-struct fetch_func {
-	unsigned long (*func)(struct pt_regs *, void *);
+/* Printing function type */
+typedef int (*print_type_func_t)(struct trace_seq *, const char *, void *);
+#define PRINT_TYPE_FUNC_NAME(type)	print_type_##type
+#define PRINT_TYPE_FMT_NAME(type)	print_type_format_##type
+
+/* Printing  in basic type function template */
+#define DEFINE_BASIC_PRINT_TYPE_FUNC(type, fmt, cast)			\
+static __kprobes int PRINT_TYPE_FUNC_NAME(type)(struct trace_seq *s,	\
+						const char *name, void *data)\
+{									\
+	return trace_seq_printf(s, " %s=" fmt, name, (cast)*(type *)data);\
+}									\
+static const char PRINT_TYPE_FMT_NAME(type)[] = fmt;
+
+DEFINE_BASIC_PRINT_TYPE_FUNC(u8, "%x", unsigned int)
+DEFINE_BASIC_PRINT_TYPE_FUNC(u16, "%x", unsigned int)
+DEFINE_BASIC_PRINT_TYPE_FUNC(u32, "%lx", unsigned long)
+DEFINE_BASIC_PRINT_TYPE_FUNC(u64, "%llx", unsigned long long)
+DEFINE_BASIC_PRINT_TYPE_FUNC(s8, "%d", int)
+DEFINE_BASIC_PRINT_TYPE_FUNC(s16, "%d", int)
+DEFINE_BASIC_PRINT_TYPE_FUNC(s32, "%ld", long)
+DEFINE_BASIC_PRINT_TYPE_FUNC(s64, "%lld", long long)
+
+/* Data fetch function type */
+typedef	void (*fetch_func_t)(struct pt_regs *, void *, void *);
+
+struct fetch_param {
+	fetch_func_t	fn;
 	void *data;
 };
 
-static __kprobes unsigned long call_fetch(struct fetch_func *f,
-					  struct pt_regs *regs)
+static __kprobes void call_fetch(struct fetch_param *fprm,
+				 struct pt_regs *regs, void *dest)
 {
-	return f->func(regs, f->data);
+	return fprm->fn(regs, fprm->data, dest);
 }
 
-/* fetch handlers */
-static __kprobes unsigned long fetch_register(struct pt_regs *regs,
-					      void *offset)
-{
-	return regs_get_register(regs, (unsigned int)((unsigned long)offset));
-}
+#define FETCH_FUNC_NAME(kind, type)	fetch_##kind##_##type
+/*
+ * Define macro for basic types - we don't need to define s* types, because
+ * we have to care only about bitwidth at recording time.
+ */
+#define DEFINE_BASIC_FETCH_FUNCS(kind)  \
+DEFINE_FETCH_##kind(u8)			\
+DEFINE_FETCH_##kind(u16)		\
+DEFINE_FETCH_##kind(u32)		\
+DEFINE_FETCH_##kind(u64)
 
-static __kprobes unsigned long fetch_stack(struct pt_regs *regs,
-					   void *num)
-{
-	return regs_get_kernel_stack_nth(regs,
-					 (unsigned int)((unsigned long)num));
-}
+#define CHECK_BASIC_FETCH_FUNCS(kind, fn)	\
+	((FETCH_FUNC_NAME(kind, u8) == fn) ||	\
+	 (FETCH_FUNC_NAME(kind, u16) == fn) ||	\
+	 (FETCH_FUNC_NAME(kind, u32) == fn) ||	\
+	 (FETCH_FUNC_NAME(kind, u64) == fn))
 
-static __kprobes unsigned long fetch_memory(struct pt_regs *regs, void *addr)
-{
-	unsigned long retval;
-
-	if (probe_kernel_address(addr, retval))
-		return 0;
-	return retval;
+/* Data fetch function templates */
+#define DEFINE_FETCH_reg(type)						\
+static __kprobes void FETCH_FUNC_NAME(reg, type)(struct pt_regs *regs,	\
+					  void *offset, void *dest)	\
+{									\
+	*(type *)dest = (type)regs_get_register(regs,			\
+				(unsigned int)((unsigned long)offset));	\
 }
+DEFINE_BASIC_FETCH_FUNCS(reg)
 
-static __kprobes unsigned long fetch_retvalue(struct pt_regs *regs,
-					      void *dummy)
-{
-	return regs_return_value(regs);
+#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)
 
-static __kprobes unsigned long fetch_stack_address(struct pt_regs *regs,
-						   void *dummy)
-{
-	return kernel_stack_pointer(regs);
+#define DEFINE_FETCH_retval(type)					\
+static __kprobes void FETCH_FUNC_NAME(retval, type)(struct pt_regs *regs,\
+					  void *dummy, void *dest)	\
+{									\
+	*(type *)dest = (type)regs_return_value(regs);			\
 }
+DEFINE_BASIC_FETCH_FUNCS(retval)
+
+#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)
 
 /* Memory fetching by symbol */
 struct symbol_cache {
@@ -145,51 +192,126 @@
 	return sc;
 }
 
-static __kprobes unsigned long fetch_symbol(struct pt_regs *regs, void *data)
-{
-	struct symbol_cache *sc = data;
-
-	if (sc->addr)
-		return fetch_memory(regs, (void *)sc->addr);
-	else
-		return 0;
+#define DEFINE_FETCH_symbol(type)					\
+static __kprobes void FETCH_FUNC_NAME(symbol, type)(struct pt_regs *regs,\
+					  void *data, void *dest)	\
+{									\
+	struct symbol_cache *sc = data;					\
+	if (sc->addr)							\
+		fetch_memory_##type(regs, (void *)sc->addr, dest);	\
+	else								\
+		*(type *)dest = 0;					\
 }
+DEFINE_BASIC_FETCH_FUNCS(symbol)
 
-/* Special indirect memory access interface */
-struct indirect_fetch_data {
-	struct fetch_func orig;
+/* Dereference memory access function */
+struct deref_fetch_param {
+	struct fetch_param orig;
 	long offset;
 };
 
-static __kprobes unsigned long fetch_indirect(struct pt_regs *regs, void *data)
-{
-	struct indirect_fetch_data *ind = data;
-	unsigned long addr;
-
-	addr = call_fetch(&ind->orig, regs);
-	if (addr) {
-		addr += ind->offset;
-		return fetch_memory(regs, (void *)addr);
-	} else
-		return 0;
+#define DEFINE_FETCH_deref(type)					\
+static __kprobes void FETCH_FUNC_NAME(deref, type)(struct pt_regs *regs,\
+					    void *data, void *dest)	\
+{									\
+	struct deref_fetch_param *dprm = data;				\
+	unsigned long addr;						\
+	call_fetch(&dprm->orig, regs, &addr);				\
+	if (addr) {							\
+		addr += dprm->offset;					\
+		fetch_memory_##type(regs, (void *)addr, dest);		\
+	} else								\
+		*(type *)dest = 0;					\
 }
+DEFINE_BASIC_FETCH_FUNCS(deref)
 
-static __kprobes void free_indirect_fetch_data(struct indirect_fetch_data *data)
+static __kprobes void free_deref_fetch_param(struct deref_fetch_param *data)
 {
-	if (data->orig.func == fetch_indirect)
-		free_indirect_fetch_data(data->orig.data);
-	else if (data->orig.func == fetch_symbol)
+	if (CHECK_BASIC_FETCH_FUNCS(deref, data->orig.fn))
+		free_deref_fetch_param(data->orig.data);
+	else if (CHECK_BASIC_FETCH_FUNCS(symbol, data->orig.fn))
 		free_symbol_cache(data->orig.data);
 	kfree(data);
 }
 
+/* Default (unsigned long) fetch type */
+#define __DEFAULT_FETCH_TYPE(t) u##t
+#define _DEFAULT_FETCH_TYPE(t) __DEFAULT_FETCH_TYPE(t)
+#define DEFAULT_FETCH_TYPE _DEFAULT_FETCH_TYPE(BITS_PER_LONG)
+#define DEFAULT_FETCH_TYPE_STR __stringify(DEFAULT_FETCH_TYPE)
+
+#define ASSIGN_FETCH_FUNC(kind, type)	\
+	.kind = FETCH_FUNC_NAME(kind, type)
+
+#define ASSIGN_FETCH_TYPE(ptype, ftype, sign)	\
+	{.name = #ptype,			\
+	 .size = sizeof(ftype),			\
+	 .is_signed = sign,			\
+	 .print = PRINT_TYPE_FUNC_NAME(ptype),	\
+	 .fmt = PRINT_TYPE_FMT_NAME(ptype),	\
+ASSIGN_FETCH_FUNC(reg, ftype),			\
+ASSIGN_FETCH_FUNC(stack, ftype),		\
+ASSIGN_FETCH_FUNC(retval, ftype),		\
+ASSIGN_FETCH_FUNC(memory, ftype),		\
+ASSIGN_FETCH_FUNC(symbol, ftype),		\
+ASSIGN_FETCH_FUNC(deref, ftype),		\
+	}
+
+/* Fetch type information table */
+static const struct fetch_type {
+	const char	*name;		/* Name of type */
+	size_t		size;		/* Byte size of type */
+	int		is_signed;	/* Signed flag */
+	print_type_func_t	print;	/* Print functions */
+	const char	*fmt;		/* Fromat string */
+	/* Fetch functions */
+	fetch_func_t	reg;
+	fetch_func_t	stack;
+	fetch_func_t	retval;
+	fetch_func_t	memory;
+	fetch_func_t	symbol;
+	fetch_func_t	deref;
+} fetch_type_table[] = {
+	ASSIGN_FETCH_TYPE(u8,  u8,  0),
+	ASSIGN_FETCH_TYPE(u16, u16, 0),
+	ASSIGN_FETCH_TYPE(u32, u32, 0),
+	ASSIGN_FETCH_TYPE(u64, u64, 0),
+	ASSIGN_FETCH_TYPE(s8,  u8,  1),
+	ASSIGN_FETCH_TYPE(s16, u16, 1),
+	ASSIGN_FETCH_TYPE(s32, u32, 1),
+	ASSIGN_FETCH_TYPE(s64, u64, 1),
+};
+
+static const struct fetch_type *find_fetch_type(const char *type)
+{
+	int i;
+
+	if (!type)
+		type = DEFAULT_FETCH_TYPE_STR;
+
+	for (i = 0; i < ARRAY_SIZE(fetch_type_table); i++)
+		if (strcmp(type, fetch_type_table[i].name) == 0)
+			return &fetch_type_table[i];
+	return NULL;
+}
+
+/* Special function : only accept unsigned long */
+static __kprobes void fetch_stack_address(struct pt_regs *regs,
+					  void *dummy, void *dest)
+{
+	*(unsigned long *)dest = kernel_stack_pointer(regs);
+}
+
 /**
  * Kprobe event core functions
  */
 
 struct probe_arg {
-	struct fetch_func	fetch;
-	const char		*name;
+	struct fetch_param	fetch;
+	unsigned int		offset;	/* Offset from argument entry */
+	const char		*name;	/* Name of this argument */
+	const char		*comm;	/* Command of this argument */
+	const struct fetch_type	*type;	/* Type of this argument */
 };
 
 /* Flags for trace_probe */
@@ -204,6 +326,7 @@
 	const char		*symbol;	/* symbol name */
 	struct ftrace_event_call	call;
 	struct trace_event		event;
+	ssize_t			size;		/* trace entry size */
 	unsigned int		nr_args;
 	struct probe_arg	args[];
 };
@@ -212,6 +335,7 @@
 	(offsetof(struct trace_probe, args) +	\
 	(sizeof(struct probe_arg) * (n)))
 
+
 static __kprobes int probe_is_return(struct trace_probe *tp)
 {
 	return tp->rp.handler != NULL;
@@ -222,49 +346,6 @@
 	return tp->symbol ? tp->symbol : "unknown";
 }
 
-static int probe_arg_string(char *buf, size_t n, struct fetch_func *ff)
-{
-	int ret = -EINVAL;
-
-	if (ff->func == fetch_register) {
-		const char *name;
-		name = regs_query_register_name((unsigned int)((long)ff->data));
-		ret = snprintf(buf, n, "%%%s", name);
-	} else if (ff->func == fetch_stack)
-		ret = snprintf(buf, n, "$stack%lu", (unsigned long)ff->data);
-	else if (ff->func == fetch_memory)
-		ret = snprintf(buf, n, "@0x%p", ff->data);
-	else if (ff->func == fetch_symbol) {
-		struct symbol_cache *sc = ff->data;
-		if (sc->offset)
-			ret = snprintf(buf, n, "@%s%+ld", sc->symbol,
-					sc->offset);
-		else
-			ret = snprintf(buf, n, "@%s", sc->symbol);
-	} else if (ff->func == fetch_retvalue)
-		ret = snprintf(buf, n, "$retval");
-	else if (ff->func == fetch_stack_address)
-		ret = snprintf(buf, n, "$stack");
-	else if (ff->func == fetch_indirect) {
-		struct indirect_fetch_data *id = ff->data;
-		size_t l = 0;
-		ret = snprintf(buf, n, "%+ld(", id->offset);
-		if (ret >= n)
-			goto end;
-		l += ret;
-		ret = probe_arg_string(buf + l, n - l, &id->orig);
-		if (ret < 0)
-			goto end;
-		l += ret;
-		ret = snprintf(buf + l, n - l, ")");
-		ret += l;
-	}
-end:
-	if (ret >= n)
-		return -ENOSPC;
-	return ret;
-}
-
 static int register_probe_event(struct trace_probe *tp);
 static void unregister_probe_event(struct trace_probe *tp);
 
@@ -347,11 +428,12 @@
 
 static void free_probe_arg(struct probe_arg *arg)
 {
-	if (arg->fetch.func == fetch_symbol)
+	if (CHECK_BASIC_FETCH_FUNCS(deref, arg->fetch.fn))
+		free_deref_fetch_param(arg->fetch.data);
+	else if (CHECK_BASIC_FETCH_FUNCS(symbol, arg->fetch.fn))
 		free_symbol_cache(arg->fetch.data);
-	else if (arg->fetch.func == fetch_indirect)
-		free_indirect_fetch_data(arg->fetch.data);
 	kfree(arg->name);
+	kfree(arg->comm);
 }
 
 static void free_trace_probe(struct trace_probe *tp)
@@ -457,28 +539,30 @@
 #define PARAM_MAX_ARGS 16
 #define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long))
 
-static int parse_probe_vars(char *arg, struct fetch_func *ff, int is_return)
+static int parse_probe_vars(char *arg, const struct fetch_type *t,
+			    struct fetch_param *f, int is_return)
 {
 	int ret = 0;
 	unsigned long param;
 
 	if (strcmp(arg, "retval") == 0) {
-		if (is_return) {
-			ff->func = fetch_retvalue;
-			ff->data = NULL;
-		} else
+		if (is_return)
+			f->fn = t->retval;
+		else
 			ret = -EINVAL;
 	} else if (strncmp(arg, "stack", 5) == 0) {
 		if (arg[5] == '\0') {
-			ff->func = fetch_stack_address;
-			ff->data = NULL;
+			if (strcmp(t->name, DEFAULT_FETCH_TYPE_STR) == 0)
+				f->fn = fetch_stack_address;
+			else
+				ret = -EINVAL;
 		} else if (isdigit(arg[5])) {
 			ret = strict_strtoul(arg + 5, 10, &param);
 			if (ret || param > PARAM_MAX_STACK)
 				ret = -EINVAL;
 			else {
-				ff->func = fetch_stack;
-				ff->data = (void *)param;
+				f->fn = t->stack;
+				f->data = (void *)param;
 			}
 		} else
 			ret = -EINVAL;
@@ -488,7 +572,8 @@
 }
 
 /* Recursive argument parser */
-static int __parse_probe_arg(char *arg, struct fetch_func *ff, int is_return)
+static int __parse_probe_arg(char *arg, const struct fetch_type *t,
+			     struct fetch_param *f, int is_return)
 {
 	int ret = 0;
 	unsigned long param;
@@ -497,13 +582,13 @@
 
 	switch (arg[0]) {
 	case '$':
-		ret = parse_probe_vars(arg + 1, ff, is_return);
+		ret = parse_probe_vars(arg + 1, t, f, is_return);
 		break;
 	case '%':	/* named register */
 		ret = regs_query_register_offset(arg + 1);
 		if (ret >= 0) {
-			ff->func = fetch_register;
-			ff->data = (void *)(unsigned long)ret;
+			f->fn = t->reg;
+			f->data = (void *)(unsigned long)ret;
 			ret = 0;
 		}
 		break;
@@ -512,26 +597,22 @@
 			ret = strict_strtoul(arg + 1, 0, &param);
 			if (ret)
 				break;
-			ff->func = fetch_memory;
-			ff->data = (void *)param;
+			f->fn = t->memory;
+			f->data = (void *)param;
 		} else {
 			ret = split_symbol_offset(arg + 1, &offset);
 			if (ret)
 				break;
-			ff->data = alloc_symbol_cache(arg + 1, offset);
-			if (ff->data)
-				ff->func = fetch_symbol;
-			else
-				ret = -EINVAL;
+			f->data = alloc_symbol_cache(arg + 1, offset);
+			if (f->data)
+				f->fn = t->symbol;
 		}
 		break;
-	case '+':	/* indirect memory */
+	case '+':	/* deref memory */
 	case '-':
 		tmp = strchr(arg, '(');
-		if (!tmp) {
-			ret = -EINVAL;
+		if (!tmp)
 			break;
-		}
 		*tmp = '\0';
 		ret = strict_strtol(arg + 1, 0, &offset);
 		if (ret)
@@ -541,38 +622,58 @@
 		arg = tmp + 1;
 		tmp = strrchr(arg, ')');
 		if (tmp) {
-			struct indirect_fetch_data *id;
+			struct deref_fetch_param *dprm;
+			const struct fetch_type *t2 = find_fetch_type(NULL);
 			*tmp = '\0';
-			id = kzalloc(sizeof(struct indirect_fetch_data),
-				     GFP_KERNEL);
-			if (!id)
+			dprm = kzalloc(sizeof(struct deref_fetch_param),
+				       GFP_KERNEL);
+			if (!dprm)
 				return -ENOMEM;
-			id->offset = offset;
-			ret = __parse_probe_arg(arg, &id->orig, is_return);
+			dprm->offset = offset;
+			ret = __parse_probe_arg(arg, t2, &dprm->orig,
+						is_return);
 			if (ret)
-				kfree(id);
+				kfree(dprm);
 			else {
-				ff->func = fetch_indirect;
-				ff->data = (void *)id;
+				f->fn = t->deref;
+				f->data = (void *)dprm;
 			}
-		} else
-			ret = -EINVAL;
+		}
 		break;
-	default:
-		/* TODO: support custom handler */
-		ret = -EINVAL;
 	}
+	if (!ret && !f->fn)
+		ret = -EINVAL;
 	return ret;
 }
 
 /* String length checking wrapper */
-static int parse_probe_arg(char *arg, struct fetch_func *ff, int is_return)
+static int parse_probe_arg(char *arg, struct trace_probe *tp,
+			   struct probe_arg *parg, int is_return)
 {
+	const char *t;
+
 	if (strlen(arg) > MAX_ARGSTR_LEN) {
 		pr_info("Argument is too long.: %s\n",  arg);
 		return -ENOSPC;
 	}
-	return __parse_probe_arg(arg, ff, is_return);
+	parg->comm = kstrdup(arg, GFP_KERNEL);
+	if (!parg->comm) {
+		pr_info("Failed to allocate memory for command '%s'.\n", arg);
+		return -ENOMEM;
+	}
+	t = strchr(parg->comm, ':');
+	if (t) {
+		arg[t - parg->comm] = '\0';
+		t++;
+	}
+	parg->type = find_fetch_type(t);
+	if (!parg->type) {
+		pr_info("Unsupported type: %s\n", t);
+		return -EINVAL;
+	}
+	parg->offset = tp->size;
+	tp->size += parg->type->size;
+	return __parse_probe_arg(arg, parg->type, &parg->fetch, is_return);
 }
 
 /* Return 1 if name is reserved or already used by another argument */
@@ -602,15 +703,18 @@
 	 *  @ADDR	: fetch memory at ADDR (ADDR should be in kernel)
 	 *  @SYM[+|-offs] : fetch memory at SYM +|- offs (SYM is a data symbol)
 	 *  %REG	: fetch register REG
-	 * Indirect memory fetch:
+	 * Dereferencing memory fetch:
 	 *  +|-offs(ARG) : fetch memory at ARG +|- offs address.
 	 * Alias name of args:
 	 *  NAME=FETCHARG : set NAME as alias of FETCHARG.
+	 * Type of args:
+	 *  FETCHARG:TYPE : use TYPE instead of unsigned long.
 	 */
 	struct trace_probe *tp;
 	int i, ret = 0;
 	int is_return = 0, is_delete = 0;
-	char *symbol = NULL, *event = NULL, *arg = NULL, *group = NULL;
+	char *symbol = NULL, *event = NULL, *group = NULL;
+	char *arg, *tmp;
 	unsigned long offset = 0;
 	void *addr = NULL;
 	char buf[MAX_EVENT_NAME_LEN];
@@ -723,13 +827,6 @@
 		else
 			arg = argv[i];
 
-		if (conflict_field_name(argv[i], tp->args, i)) {
-			pr_info("Argument%d name '%s' conflicts with "
-				"another field.\n", i, argv[i]);
-			ret = -EINVAL;
-			goto error;
-		}
-
 		tp->args[i].name = kstrdup(argv[i], GFP_KERNEL);
 		if (!tp->args[i].name) {
 			pr_info("Failed to allocate argument%d name '%s'.\n",
@@ -737,9 +834,19 @@
 			ret = -ENOMEM;
 			goto error;
 		}
+		tmp = strchr(tp->args[i].name, ':');
+		if (tmp)
+			*tmp = '_';	/* convert : to _ */
+
+		if (conflict_field_name(tp->args[i].name, tp->args, i)) {
+			pr_info("Argument%d name '%s' conflicts with "
+				"another field.\n", i, argv[i]);
+			ret = -EINVAL;
+			goto error;
+		}
 
 		/* Parse fetch argument */
-		ret = parse_probe_arg(arg, &tp->args[i].fetch, is_return);
+		ret = parse_probe_arg(arg, tp, &tp->args[i], is_return);
 		if (ret) {
 			pr_info("Parse error at argument%d. (%d)\n", i, ret);
 			kfree(tp->args[i].name);
@@ -794,8 +901,7 @@
 static int probes_seq_show(struct seq_file *m, void *v)
 {
 	struct trace_probe *tp = v;
-	int i, ret;
-	char buf[MAX_ARGSTR_LEN + 1];
+	int i;
 
 	seq_printf(m, "%c", probe_is_return(tp) ? 'r' : 'p');
 	seq_printf(m, ":%s/%s", tp->call.system, tp->call.name);
@@ -807,15 +913,10 @@
 	else
 		seq_printf(m, " %s", probe_symbol(tp));
 
-	for (i = 0; i < tp->nr_args; i++) {
-		ret = probe_arg_string(buf, MAX_ARGSTR_LEN, &tp->args[i].fetch);
-		if (ret < 0) {
-			pr_warning("Argument%d decoding error(%d).\n", i, ret);
-			return ret;
-		}
-		seq_printf(m, " %s=%s", tp->args[i].name, buf);
-	}
+	for (i = 0; i < tp->nr_args; i++)
+		seq_printf(m, " %s=%s", tp->args[i].name, tp->args[i].comm);
 	seq_printf(m, "\n");
+
 	return 0;
 }
 
@@ -945,9 +1046,10 @@
 static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs)
 {
 	struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp);
-	struct kprobe_trace_entry *entry;
+	struct kprobe_trace_entry_head *entry;
 	struct ring_buffer_event *event;
 	struct ring_buffer *buffer;
+	u8 *data;
 	int size, i, pc;
 	unsigned long irq_flags;
 	struct ftrace_event_call *call = &tp->call;
@@ -957,7 +1059,7 @@
 	local_save_flags(irq_flags);
 	pc = preempt_count();
 
-	size = SIZEOF_KPROBE_TRACE_ENTRY(tp->nr_args);
+	size = sizeof(*entry) + tp->size;
 
 	event = trace_current_buffer_lock_reserve(&buffer, call->id, size,
 						  irq_flags, pc);
@@ -965,10 +1067,10 @@
 		return;
 
 	entry = ring_buffer_event_data(event);
-	entry->nargs = tp->nr_args;
 	entry->ip = (unsigned long)kp->addr;
+	data = (u8 *)&entry[1];
 	for (i = 0; i < tp->nr_args; i++)
-		entry->args[i] = call_fetch(&tp->args[i].fetch, regs);
+		call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset);
 
 	if (!filter_current_check_discard(buffer, call, entry, event))
 		trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc);
@@ -979,9 +1081,10 @@
 					  struct pt_regs *regs)
 {
 	struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp);
-	struct kretprobe_trace_entry *entry;
+	struct kretprobe_trace_entry_head *entry;
 	struct ring_buffer_event *event;
 	struct ring_buffer *buffer;
+	u8 *data;
 	int size, i, pc;
 	unsigned long irq_flags;
 	struct ftrace_event_call *call = &tp->call;
@@ -989,7 +1092,7 @@
 	local_save_flags(irq_flags);
 	pc = preempt_count();
 
-	size = SIZEOF_KRETPROBE_TRACE_ENTRY(tp->nr_args);
+	size = sizeof(*entry) + tp->size;
 
 	event = trace_current_buffer_lock_reserve(&buffer, call->id, size,
 						  irq_flags, pc);
@@ -997,11 +1100,11 @@
 		return;
 
 	entry = ring_buffer_event_data(event);
-	entry->nargs = tp->nr_args;
 	entry->func = (unsigned long)tp->rp.kp.addr;
 	entry->ret_ip = (unsigned long)ri->ret_addr;
+	data = (u8 *)&entry[1];
 	for (i = 0; i < tp->nr_args; i++)
-		entry->args[i] = call_fetch(&tp->args[i].fetch, regs);
+		call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset);
 
 	if (!filter_current_check_discard(buffer, call, entry, event))
 		trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc);
@@ -1011,13 +1114,14 @@
 enum print_line_t
 print_kprobe_event(struct trace_iterator *iter, int flags)
 {
-	struct kprobe_trace_entry *field;
+	struct kprobe_trace_entry_head *field;
 	struct trace_seq *s = &iter->seq;
 	struct trace_event *event;
 	struct trace_probe *tp;
+	u8 *data;
 	int i;
 
-	field = (struct kprobe_trace_entry *)iter->ent;
+	field = (struct kprobe_trace_entry_head *)iter->ent;
 	event = ftrace_find_event(field->ent.type);
 	tp = container_of(event, struct trace_probe, event);
 
@@ -1030,9 +1134,10 @@
 	if (!trace_seq_puts(s, ")"))
 		goto partial;
 
-	for (i = 0; i < field->nargs; i++)
-		if (!trace_seq_printf(s, " %s=%lx",
-				      tp->args[i].name, field->args[i]))
+	data = (u8 *)&field[1];
+	for (i = 0; i < tp->nr_args; i++)
+		if (!tp->args[i].type->print(s, tp->args[i].name,
+					     data + tp->args[i].offset))
 			goto partial;
 
 	if (!trace_seq_puts(s, "\n"))
@@ -1046,13 +1151,14 @@
 enum print_line_t
 print_kretprobe_event(struct trace_iterator *iter, int flags)
 {
-	struct kretprobe_trace_entry *field;
+	struct kretprobe_trace_entry_head *field;
 	struct trace_seq *s = &iter->seq;
 	struct trace_event *event;
 	struct trace_probe *tp;
+	u8 *data;
 	int i;
 
-	field = (struct kretprobe_trace_entry *)iter->ent;
+	field = (struct kretprobe_trace_entry_head *)iter->ent;
 	event = ftrace_find_event(field->ent.type);
 	tp = container_of(event, struct trace_probe, event);
 
@@ -1071,9 +1177,10 @@
 	if (!trace_seq_puts(s, ")"))
 		goto partial;
 
-	for (i = 0; i < field->nargs; i++)
-		if (!trace_seq_printf(s, " %s=%lx",
-				      tp->args[i].name, field->args[i]))
+	data = (u8 *)&field[1];
+	for (i = 0; i < tp->nr_args; i++)
+		if (!tp->args[i].type->print(s, tp->args[i].name,
+					     data + tp->args[i].offset))
 			goto partial;
 
 	if (!trace_seq_puts(s, "\n"))
@@ -1129,29 +1236,43 @@
 static int kprobe_event_define_fields(struct ftrace_event_call *event_call)
 {
 	int ret, i;
-	struct kprobe_trace_entry field;
+	struct kprobe_trace_entry_head field;
 	struct trace_probe *tp = (struct trace_probe *)event_call->data;
 
 	DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0);
-	DEFINE_FIELD(int, nargs, FIELD_STRING_NARGS, 1);
 	/* Set argument names as fields */
-	for (i = 0; i < tp->nr_args; i++)
-		DEFINE_FIELD(unsigned long, args[i], tp->args[i].name, 0);
+	for (i = 0; i < tp->nr_args; i++) {
+		ret = trace_define_field(event_call, tp->args[i].type->name,
+					 tp->args[i].name,
+					 sizeof(field) + tp->args[i].offset,
+					 tp->args[i].type->size,
+					 tp->args[i].type->is_signed,
+					 FILTER_OTHER);
+		if (ret)
+			return ret;
+	}
 	return 0;
 }
 
 static int kretprobe_event_define_fields(struct ftrace_event_call *event_call)
 {
 	int ret, i;
-	struct kretprobe_trace_entry field;
+	struct kretprobe_trace_entry_head field;
 	struct trace_probe *tp = (struct trace_probe *)event_call->data;
 
 	DEFINE_FIELD(unsigned long, func, FIELD_STRING_FUNC, 0);
 	DEFINE_FIELD(unsigned long, ret_ip, FIELD_STRING_RETIP, 0);
-	DEFINE_FIELD(int, nargs, FIELD_STRING_NARGS, 1);
 	/* Set argument names as fields */
-	for (i = 0; i < tp->nr_args; i++)
-		DEFINE_FIELD(unsigned long, args[i], tp->args[i].name, 0);
+	for (i = 0; i < tp->nr_args; i++) {
+		ret = trace_define_field(event_call, tp->args[i].type->name,
+					 tp->args[i].name,
+					 sizeof(field) + tp->args[i].offset,
+					 tp->args[i].type->size,
+					 tp->args[i].type->is_signed,
+					 FILTER_OTHER);
+		if (ret)
+			return ret;
+	}
 	return 0;
 }
 
@@ -1176,8 +1297,8 @@
 	pos += snprintf(buf + pos, LEN_OR_ZERO, "\"%s", fmt);
 
 	for (i = 0; i < tp->nr_args; i++) {
-		pos += snprintf(buf + pos, LEN_OR_ZERO, " %s=%%lx",
-				tp->args[i].name);
+		pos += snprintf(buf + pos, LEN_OR_ZERO, " %s=%s",
+				tp->args[i].name, tp->args[i].type->fmt);
 	}
 
 	pos += snprintf(buf + pos, LEN_OR_ZERO, "\", %s", arg);
@@ -1219,12 +1340,13 @@
 {
 	struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp);
 	struct ftrace_event_call *call = &tp->call;
-	struct kprobe_trace_entry *entry;
+	struct kprobe_trace_entry_head *entry;
+	u8 *data;
 	int size, __size, i;
 	unsigned long irq_flags;
 	int rctx;
 
-	__size = SIZEOF_KPROBE_TRACE_ENTRY(tp->nr_args);
+	__size = sizeof(*entry) + tp->size;
 	size = ALIGN(__size + sizeof(u32), sizeof(u64));
 	size -= sizeof(u32);
 	if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE,
@@ -1235,10 +1357,10 @@
 	if (!entry)
 		return;
 
-	entry->nargs = tp->nr_args;
 	entry->ip = (unsigned long)kp->addr;
+	data = (u8 *)&entry[1];
 	for (i = 0; i < tp->nr_args; i++)
-		entry->args[i] = call_fetch(&tp->args[i].fetch, regs);
+		call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset);
 
 	perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, irq_flags, regs);
 }
@@ -1249,12 +1371,13 @@
 {
 	struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp);
 	struct ftrace_event_call *call = &tp->call;
-	struct kretprobe_trace_entry *entry;
+	struct kretprobe_trace_entry_head *entry;
+	u8 *data;
 	int size, __size, i;
 	unsigned long irq_flags;
 	int rctx;
 
-	__size = SIZEOF_KRETPROBE_TRACE_ENTRY(tp->nr_args);
+	__size = sizeof(*entry) + tp->size;
 	size = ALIGN(__size + sizeof(u32), sizeof(u64));
 	size -= sizeof(u32);
 	if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE,
@@ -1265,11 +1388,11 @@
 	if (!entry)
 		return;
 
-	entry->nargs = tp->nr_args;
 	entry->func = (unsigned long)tp->rp.kp.addr;
 	entry->ret_ip = (unsigned long)ri->ret_addr;
+	data = (u8 *)&entry[1];
 	for (i = 0; i < tp->nr_args; i++)
-		entry->args[i] = call_fetch(&tp->args[i].fetch, regs);
+		call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset);
 
 	perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1,
 			       irq_flags, regs);
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index bb671b3..63c25d3 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -79,7 +79,16 @@
 'EVENT' specifies the name of new event, if omitted, it will be set the name of the probed function. Currently, event group name is set as 'probe'.
 'FUNC' specifies a probed function name, and it may have one of the following options; '+OFFS' is the offset from function entry address in bytes, ':RLN' is the relative-line number from function entry line, and '%return' means that it probes function return. And ';PTN' means lazy matching pattern (see LAZY MATCHING). Note that ';PTN' must be the end of the probe point definition.  In addition, '@SRC' specifies a source file which has that function.
 It is also possible to specify a probe point by the source line number or lazy matching by using 'SRC:ALN' or 'SRC;PTN' syntax, where 'SRC' is the source file path, ':ALN' is the line number and ';PTN' is the lazy matching pattern.
-'ARG' specifies the arguments of this probe point. You can use the name of local variable, or kprobe-tracer argument format (e.g. $retval, %ax, etc).
+'ARG' specifies the arguments of this probe point, (see PROBE ARGUMENT).
+
+PROBE ARGUMENT
+--------------
+Each probe argument follows below syntax.
+
+ [NAME=]LOCALVAR|$retval|%REG|@SYMBOL[:TYPE]
+
+'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), or kprobe-tracer argument format (e.g. $retval, %ax, etc). Note that the name of this argument will be set as the last member name if you specify a local data structure member (e.g. field2 for 'var->field1.field2'.)
+'TYPE' casts the type of this argument (optional). If omitted, perf probe automatically set the type based on debuginfo.
 
 LINE SYNTAX
 -----------
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index bfc47ff..c1e5403 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -40,7 +40,6 @@
 #include "util/debug.h"
 #include "util/debugfs.h"
 #include "util/parse-options.h"
-#include "util/parse-events.h"	/* For debugfs_path */
 #include "util/probe-finder.h"
 #include "util/probe-event.h"
 
@@ -59,23 +58,25 @@
 
 
 /* Parse an event definition. Note that any error must die. */
-static void parse_probe_event(const char *str)
+static int parse_probe_event(const char *str)
 {
 	struct perf_probe_event *pev = &params.events[params.nevents];
+	int ret;
 
 	pr_debug("probe-definition(%d): %s\n", params.nevents, str);
 	if (++params.nevents == MAX_PROBES)
 		die("Too many probes (> %d) are specified.", MAX_PROBES);
 
 	/* Parse a perf-probe command into event */
-	parse_perf_probe_command(str, pev);
-
+	ret = parse_perf_probe_command(str, pev);
 	pr_debug("%d arguments\n", pev->nargs);
+
+	return ret;
 }
 
-static void parse_probe_event_argv(int argc, const char **argv)
+static int parse_probe_event_argv(int argc, const char **argv)
 {
-	int i, len;
+	int i, len, ret;
 	char *buf;
 
 	/* Bind up rest arguments */
@@ -86,16 +87,18 @@
 	len = 0;
 	for (i = 0; i < argc; i++)
 		len += sprintf(&buf[len], "%s ", argv[i]);
-	parse_probe_event(buf);
+	ret = parse_probe_event(buf);
 	free(buf);
+	return ret;
 }
 
 static int opt_add_probe_event(const struct option *opt __used,
 			      const char *str, int unset __used)
 {
 	if (str)
-		parse_probe_event(str);
-	return 0;
+		return parse_probe_event(str);
+	else
+		return 0;
 }
 
 static int opt_del_probe_event(const struct option *opt __used,
@@ -113,11 +116,14 @@
 static int opt_show_lines(const struct option *opt __used,
 			  const char *str, int unset __used)
 {
+	int ret = 0;
+
 	if (str)
-		parse_line_range_desc(str, &params.line_range);
+		ret = parse_line_range_desc(str, &params.line_range);
 	INIT_LIST_HEAD(&params.line_range.line_list);
 	params.show_lines = true;
-	return 0;
+
+	return ret;
 }
 #endif
 
@@ -142,9 +148,9 @@
 	OPT_CALLBACK('a', "add", NULL,
 #ifdef DWARF_SUPPORT
 		"[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT"
-		" [ARG ...]",
+		" [[NAME=]ARG ...]",
 #else
-		"[EVENT=]FUNC[+OFF|%return] [ARG ...]",
+		"[EVENT=]FUNC[+OFF|%return] [[NAME=]ARG ...]",
 #endif
 		"probe point definition, where\n"
 		"\t\tGROUP:\tGroup name (optional)\n"
@@ -178,6 +184,8 @@
 
 int cmd_probe(int argc, const char **argv, const char *prefix __used)
 {
+	int ret;
+
 	argc = parse_options(argc, argv, options, probe_usage,
 			     PARSE_OPT_STOP_AT_NON_OPTION);
 	if (argc > 0) {
@@ -185,28 +193,31 @@
 			pr_warning("  Error: '-' is not supported.\n");
 			usage_with_options(probe_usage, options);
 		}
-		parse_probe_event_argv(argc, argv);
+		ret = parse_probe_event_argv(argc, argv);
+		if (ret < 0) {
+			pr_err("  Error: Parse Error.  (%d)\n", ret);
+			return ret;
+		}
 	}
 
 	if ((!params.nevents && !params.dellist && !params.list_events &&
 	     !params.show_lines))
 		usage_with_options(probe_usage, options);
 
-	if (debugfs_valid_mountpoint(debugfs_path) < 0)
-		die("Failed to find debugfs path.");
-
 	if (params.list_events) {
 		if (params.nevents != 0 || params.dellist) {
-			pr_warning("  Error: Don't use --list with"
-				   " --add/--del.\n");
+			pr_err("  Error: Don't use --list with --add/--del.\n");
 			usage_with_options(probe_usage, options);
 		}
 		if (params.show_lines) {
-			pr_warning("  Error: Don't use --list with --line.\n");
+			pr_err("  Error: Don't use --list with --line.\n");
 			usage_with_options(probe_usage, options);
 		}
-		show_perf_probe_events();
-		return 0;
+		ret = show_perf_probe_events();
+		if (ret < 0)
+			pr_err("  Error: Failed to show event list. (%d)\n",
+			       ret);
+		return ret;
 	}
 
 #ifdef DWARF_SUPPORT
@@ -217,19 +228,30 @@
 			usage_with_options(probe_usage, options);
 		}
 
-		show_line_range(&params.line_range);
-		return 0;
+		ret = show_line_range(&params.line_range);
+		if (ret < 0)
+			pr_err("  Error: Failed to show lines. (%d)\n", ret);
+		return ret;
 	}
 #endif
 
 	if (params.dellist) {
-		del_perf_probe_events(params.dellist);
+		ret = del_perf_probe_events(params.dellist);
 		strlist__delete(params.dellist);
-		if (params.nevents == 0)
-			return 0;
+		if (ret < 0) {
+			pr_err("  Error: Failed to delete events. (%d)\n", ret);
+			return ret;
+		}
 	}
 
-	add_perf_probe_events(params.events, params.nevents, params.force_add);
+	if (params.nevents) {
+		ret = add_perf_probe_events(params.events, params.nevents,
+					    params.force_add);
+		if (ret < 0) {
+			pr_err("  Error: Failed to add events. (%d)\n", ret);
+			return ret;
+		}
+	}
 	return 0;
 }
 
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 18cf8b3..9c2b874 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -68,7 +68,7 @@
 	int64_t cmp = 0;
 
 	list_for_each_entry(se, &hist_entry__sort_list, list) {
-		cmp = se->cmp(left, right);
+		cmp = se->se_cmp(left, right);
 		if (cmp)
 			break;
 	}
@@ -85,7 +85,7 @@
 	list_for_each_entry(se, &hist_entry__sort_list, list) {
 		int64_t (*f)(struct hist_entry *, struct hist_entry *);
 
-		f = se->collapse ?: se->cmp;
+		f = se->se_collapse ?: se->se_cmp;
 
 		cmp = f(left, right);
 		if (cmp)
@@ -536,8 +536,8 @@
 			continue;
 
 		ret += snprintf(s + ret, size - ret, "%s", sep ?: "  ");
-		ret += se->snprintf(self, s + ret, size - ret,
-				    se->width ? *se->width : 0);
+		ret += se->se_snprintf(self, s + ret, size - ret,
+				       se->se_width ? *se->se_width : 0);
 	}
 
 	return ret;
@@ -564,7 +564,7 @@
 	if (sort__first_dimension == SORT_COMM) {
 		struct sort_entry *se = list_first_entry(&hist_entry__sort_list,
 							 typeof(*se), list);
-		left_margin = se->width ? *se->width : 0;
+		left_margin = se->se_width ? *se->se_width : 0;
 		left_margin -= thread__comm_len(self->thread);
 	}
 
@@ -615,22 +615,22 @@
 		if (se->elide)
 			continue;
 		if (sep) {
-			fprintf(fp, "%c%s", *sep, se->header);
+			fprintf(fp, "%c%s", *sep, se->se_header);
 			continue;
 		}
-		width = strlen(se->header);
-		if (se->width) {
+		width = strlen(se->se_header);
+		if (se->se_width) {
 			if (symbol_conf.col_width_list_str) {
 				if (col_width) {
-					*se->width = atoi(col_width);
+					*se->se_width = atoi(col_width);
 					col_width = strchr(col_width, ',');
 					if (col_width)
 						++col_width;
 				}
 			}
-			width = *se->width = max(*se->width, width);
+			width = *se->se_width = max(*se->se_width, width);
 		}
-		fprintf(fp, "  %*s", width, se->header);
+		fprintf(fp, "  %*s", width, se->se_header);
 	}
 	fprintf(fp, "\n");
 
@@ -652,10 +652,10 @@
 			continue;
 
 		fprintf(fp, "  ");
-		if (se->width)
-			width = *se->width;
+		if (se->se_width)
+			width = *se->se_width;
 		else
-			width = strlen(se->header);
+			width = strlen(se->se_header);
 		for (i = 0; i < width; i++)
 			fprintf(fp, ".");
 	}
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 3fc0be7..5bf8ab0 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -42,8 +42,8 @@
 #include "color.h"
 #include "symbol.h"
 #include "thread.h"
+#include "debugfs.h"
 #include "trace-event.h"	/* For __unused */
-#include "parse-events.h"	/* For debugfs_path */
 #include "probe-event.h"
 #include "probe-finder.h"
 
@@ -53,7 +53,7 @@
 
 bool probe_event_dry_run;	/* Dry run flag */
 
-#define semantic_error(msg ...) die("Semantic error :" msg)
+#define semantic_error(msg ...) pr_err("Semantic error :" msg)
 
 /* If there is no space to write, returns -E2BIG. */
 static int e_snprintf(char *str, size_t size, const char *format, ...)
@@ -76,19 +76,30 @@
 static struct map *kmaps[MAP__NR_TYPES];
 
 /* Initialize symbol maps and path of vmlinux */
-static void init_vmlinux(void)
+static int init_vmlinux(void)
 {
+	int ret;
+
 	symbol_conf.sort_by_name = true;
 	if (symbol_conf.vmlinux_name == NULL)
 		symbol_conf.try_vmlinux_path = true;
 	else
 		pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name);
-	if (symbol__init() < 0)
-		die("Failed to init symbol map.");
+	ret = symbol__init();
+	if (ret < 0) {
+		pr_debug("Failed to init symbol map.\n");
+		goto out;
+	}
 
 	map_groups__init(&kmap_groups);
-	if (map_groups__create_kernel_maps(&kmap_groups, kmaps) < 0)
-		die("Failed to create kernel maps.");
+	ret = map_groups__create_kernel_maps(&kmap_groups, kmaps);
+	if (ret < 0)
+		pr_debug("Failed to create kernel maps.\n");
+
+out:
+	if (ret < 0)
+		pr_warning("Failed to init vmlinux path.\n");
+	return ret;
 }
 
 #ifdef DWARF_SUPPORT
@@ -102,24 +113,34 @@
 	return open(kmaps[MAP__FUNCTION]->dso->long_name, O_RDONLY);
 }
 
-static void convert_to_perf_probe_point(struct kprobe_trace_point *tp,
-					struct perf_probe_point *pp)
+/* Convert trace point to probe point with debuginfo */
+static int convert_to_perf_probe_point(struct kprobe_trace_point *tp,
+				       struct perf_probe_point *pp)
 {
 	struct symbol *sym;
-	int fd, ret = 0;
+	int fd, ret = -ENOENT;
 
 	sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION],
 				       tp->symbol, NULL);
 	if (sym) {
 		fd = open_vmlinux();
-		ret = find_perf_probe_point(fd, sym->start + tp->offset, pp);
-		close(fd);
+		if (fd >= 0) {
+			ret = find_perf_probe_point(fd,
+						 sym->start + tp->offset, pp);
+			close(fd);
+		}
 	}
 	if (ret <= 0) {
-		pp->function = xstrdup(tp->symbol);
+		pr_debug("Failed to find corresponding probes from "
+			 "debuginfo. Use kprobe event information.\n");
+		pp->function = strdup(tp->symbol);
+		if (pp->function == NULL)
+			return -ENOMEM;
 		pp->offset = tp->offset;
 	}
 	pp->retprobe = tp->retprobe;
+
+	return 0;
 }
 
 /* Try to find perf_probe_event with debuginfo */
@@ -131,9 +152,10 @@
 
 	fd = open_vmlinux();
 	if (fd < 0) {
-		if (need_dwarf)
-			die("Could not open debuginfo file.");
-
+		if (need_dwarf) {
+			pr_warning("Failed to open debuginfo file.\n");
+			return fd;
+		}
 		pr_debug("Could not open vmlinux. Try to use symbols.\n");
 		return 0;
 	}
@@ -142,30 +164,32 @@
 	ntevs = find_kprobe_trace_events(fd, pev, tevs);
 	close(fd);
 
-	if (ntevs > 0)	/* Succeeded to find trace events */
+	if (ntevs > 0) {	/* Succeeded to find trace events */
+		pr_debug("find %d kprobe_trace_events.\n", ntevs);
 		return ntevs;
+	}
 
-	if (ntevs == 0)	/* No error but failed to find probe point. */
-		die("Probe point '%s' not found. - probe not added.",
-		    synthesize_perf_probe_point(&pev->point));
-
-	/* Error path */
+	if (ntevs == 0)	{	/* No error but failed to find probe point. */
+		pr_warning("Probe point '%s' not found.\n",
+			   synthesize_perf_probe_point(&pev->point));
+		return -ENOENT;
+	}
+	/* Error path : ntevs < 0 */
 	if (need_dwarf) {
-		if (ntevs == -ENOENT)
+		if (ntevs == -EBADF)
 			pr_warning("No dwarf info found in the vmlinux - "
 				"please rebuild with CONFIG_DEBUG_INFO=y.\n");
-		die("Could not analyze debuginfo.");
+		return ntevs;
 	}
 	pr_debug("An error occurred in debuginfo analysis."
 		 " Try to use symbols.\n");
 	return 0;
-
 }
 
 #define LINEBUF_SIZE 256
 #define NR_ADDITIONAL_LINES 2
 
-static void show_one_line(FILE *fp, unsigned int l, bool skip, bool show_num)
+static int show_one_line(FILE *fp, int l, bool skip, bool show_num)
 {
 	char buf[LINEBUF_SIZE];
 	const char *color = PERF_COLOR_BLUE;
@@ -174,7 +198,7 @@
 		goto error;
 	if (!skip) {
 		if (show_num)
-			fprintf(stdout, "%7u  %s", l, buf);
+			fprintf(stdout, "%7d  %s", l, buf);
 		else
 			color_fprintf(stdout, color, "         %s", buf);
 	}
@@ -190,34 +214,48 @@
 				color_fprintf(stdout, color, "%s", buf);
 		}
 	}
-	return;
+
+	return 0;
 error:
 	if (feof(fp))
-		die("Source file is shorter than expected.");
+		pr_warning("Source file is shorter than expected.\n");
 	else
-		die("File read error: %s", strerror(errno));
+		pr_warning("File read error: %s\n", strerror(errno));
+
+	return -1;
 }
 
 /*
  * Show line-range always requires debuginfo to find source file and
  * line number.
  */
-void show_line_range(struct line_range *lr)
+int show_line_range(struct line_range *lr)
 {
-	unsigned int l = 1;
+	int l = 1;
 	struct line_node *ln;
 	FILE *fp;
 	int fd, ret;
 
 	/* Search a line range */
-	init_vmlinux();
+	ret = init_vmlinux();
+	if (ret < 0)
+		return ret;
+
 	fd = open_vmlinux();
-	if (fd < 0)
-		die("Could not open debuginfo file.");
+	if (fd < 0) {
+		pr_warning("Failed to open debuginfo file.\n");
+		return fd;
+	}
+
 	ret = find_line_range(fd, lr);
-	if (ret <= 0)
-		die("Source line is not found.\n");
 	close(fd);
+	if (ret == 0) {
+		pr_warning("Specified source line is not found.\n");
+		return -ENOENT;
+	} else if (ret < 0) {
+		pr_warning("Debuginfo analysis failed. (%d)\n", ret);
+		return ret;
+	}
 
 	setup_pager();
 
@@ -228,52 +266,70 @@
 		fprintf(stdout, "<%s:%d>\n", lr->file, lr->start);
 
 	fp = fopen(lr->path, "r");
-	if (fp == NULL)
-		die("Failed to open %s: %s", lr->path, strerror(errno));
+	if (fp == NULL) {
+		pr_warning("Failed to open %s: %s\n", lr->path,
+			   strerror(errno));
+		return -errno;
+	}
 	/* Skip to starting line number */
-	while (l < lr->start)
-		show_one_line(fp, l++, true, false);
+	while (l < lr->start && ret >= 0)
+		ret = show_one_line(fp, l++, true, false);
+	if (ret < 0)
+		goto end;
 
 	list_for_each_entry(ln, &lr->line_list, list) {
-		while (ln->line > l)
-			show_one_line(fp, (l++) - lr->offset, false, false);
-		show_one_line(fp, (l++) - lr->offset, false, true);
+		while (ln->line > l && ret >= 0)
+			ret = show_one_line(fp, (l++) - lr->offset,
+					    false, false);
+		if (ret >= 0)
+			ret = show_one_line(fp, (l++) - lr->offset,
+					    false, true);
+		if (ret < 0)
+			goto end;
 	}
 
 	if (lr->end == INT_MAX)
 		lr->end = l + NR_ADDITIONAL_LINES;
-	while (l < lr->end && !feof(fp))
-		show_one_line(fp, (l++) - lr->offset, false, false);
-
+	while (l <= lr->end && !feof(fp) && ret >= 0)
+		ret = show_one_line(fp, (l++) - lr->offset, false, false);
+end:
 	fclose(fp);
+	return ret;
 }
 
 #else	/* !DWARF_SUPPORT */
 
-static void convert_to_perf_probe_point(struct kprobe_trace_point *tp,
+static int convert_to_perf_probe_point(struct kprobe_trace_point *tp,
 					struct perf_probe_point *pp)
 {
-	pp->function = xstrdup(tp->symbol);
+	pp->function = strdup(tp->symbol);
+	if (pp->function == NULL)
+		return -ENOMEM;
 	pp->offset = tp->offset;
 	pp->retprobe = tp->retprobe;
+
+	return 0;
 }
 
 static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,
 				struct kprobe_trace_event **tevs __unused)
 {
-	if (perf_probe_event_need_dwarf(pev))
-		die("Debuginfo-analysis is not supported");
+	if (perf_probe_event_need_dwarf(pev)) {
+		pr_warning("Debuginfo-analysis is not supported.\n");
+		return -ENOSYS;
+	}
 	return 0;
 }
 
-void show_line_range(struct line_range *lr __unused)
+int show_line_range(struct line_range *lr __unused)
 {
-	die("Debuginfo-analysis is not supported");
+	pr_warning("Debuginfo-analysis is not supported.\n");
+	return -ENOSYS;
 }
 
 #endif
 
-void parse_line_range_desc(const char *arg, struct line_range *lr)
+int parse_line_range_desc(const char *arg, struct line_range *lr)
 {
 	const char *ptr;
 	char *tmp;
@@ -284,29 +340,45 @@
 	 */
 	ptr = strchr(arg, ':');
 	if (ptr) {
-		lr->start = (unsigned int)strtoul(ptr + 1, &tmp, 0);
-		if (*tmp == '+')
-			lr->end = lr->start + (unsigned int)strtoul(tmp + 1,
-								    &tmp, 0);
-		else if (*tmp == '-')
-			lr->end = (unsigned int)strtoul(tmp + 1, &tmp, 0);
+		lr->start = (int)strtoul(ptr + 1, &tmp, 0);
+		if (*tmp == '+') {
+			lr->end = lr->start + (int)strtoul(tmp + 1, &tmp, 0);
+			lr->end--;	/*
+					 * Adjust the number of lines here.
+					 * If the number of lines == 1, the
+					 * the end of line should be equal to
+					 * the start of line.
+					 */
+		} else if (*tmp == '-')
+			lr->end = (int)strtoul(tmp + 1, &tmp, 0);
 		else
-			lr->end = 0;
-		pr_debug("Line range is %u to %u\n", lr->start, lr->end);
-		if (lr->end && lr->start > lr->end)
+			lr->end = INT_MAX;
+		pr_debug("Line range is %d to %d\n", lr->start, lr->end);
+		if (lr->start > lr->end) {
 			semantic_error("Start line must be smaller"
-				       " than end line.");
-		if (*tmp != '\0')
-			semantic_error("Tailing with invalid character '%d'.",
+				       " than end line.\n");
+			return -EINVAL;
+		}
+		if (*tmp != '\0') {
+			semantic_error("Tailing with invalid character '%d'.\n",
 				       *tmp);
-		tmp = xstrndup(arg, (ptr - arg));
-	} else
-		tmp = xstrdup(arg);
+			return -EINVAL;
+		}
+		tmp = strndup(arg, (ptr - arg));
+	} else {
+		tmp = strdup(arg);
+		lr->end = INT_MAX;
+	}
+
+	if (tmp == NULL)
+		return -ENOMEM;
 
 	if (strchr(tmp, '.'))
 		lr->file = tmp;
 	else
 		lr->function = tmp;
+
+	return 0;
 }
 
 /* Check the name is good for event/group */
@@ -322,7 +394,7 @@
 }
 
 /* Parse probepoint definition. */
-static void parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
+static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
 {
 	struct perf_probe_point *pp = &pev->point;
 	char *ptr, *tmp;
@@ -339,13 +411,18 @@
 	if (ptr && *ptr == '=') {	/* Event name */
 		*ptr = '\0';
 		tmp = ptr + 1;
-		ptr = strchr(arg, ':');
-		if (ptr)	/* Group name is not supported yet. */
-			semantic_error("Group name is not supported yet.");
-		if (!check_event_name(arg))
+		if (strchr(arg, ':')) {
+			semantic_error("Group name is not supported yet.\n");
+			return -ENOTSUP;
+		}
+		if (!check_event_name(arg)) {
 			semantic_error("%s is bad for event name -it must "
-				       "follow C symbol-naming rule.", arg);
-		pev->event = xstrdup(arg);
+				       "follow C symbol-naming rule.\n", arg);
+			return -EINVAL;
+		}
+		pev->event = strdup(arg);
+		if (pev->event == NULL)
+			return -ENOMEM;
 		pev->group = NULL;
 		arg = tmp;
 	}
@@ -356,18 +433,24 @@
 		*ptr++ = '\0';
 	}
 
+	tmp = strdup(arg);
+	if (tmp == NULL)
+		return -ENOMEM;
+
 	/* Check arg is function or file and copy it */
-	if (strchr(arg, '.'))	/* File */
-		pp->file = xstrdup(arg);
+	if (strchr(tmp, '.'))	/* File */
+		pp->file = tmp;
 	else			/* Function */
-		pp->function = xstrdup(arg);
+		pp->function = tmp;
 
 	/* Parse other options */
 	while (ptr) {
 		arg = ptr;
 		c = nc;
 		if (c == ';') {	/* Lazy pattern must be the last part */
-			pp->lazy_line = xstrdup(arg);
+			pp->lazy_line = strdup(arg);
+			if (pp->lazy_line == NULL)
+				return -ENOMEM;
 			break;
 		}
 		ptr = strpbrk(arg, ";:+@%");
@@ -378,131 +461,211 @@
 		switch (c) {
 		case ':':	/* Line number */
 			pp->line = strtoul(arg, &tmp, 0);
-			if (*tmp != '\0')
+			if (*tmp != '\0') {
 				semantic_error("There is non-digit char"
-					       " in line number.");
+					       " in line number.\n");
+				return -EINVAL;
+			}
 			break;
 		case '+':	/* Byte offset from a symbol */
 			pp->offset = strtoul(arg, &tmp, 0);
-			if (*tmp != '\0')
+			if (*tmp != '\0') {
 				semantic_error("There is non-digit character"
-						" in offset.");
+						" in offset.\n");
+				return -EINVAL;
+			}
 			break;
 		case '@':	/* File name */
-			if (pp->file)
-				semantic_error("SRC@SRC is not allowed.");
-			pp->file = xstrdup(arg);
+			if (pp->file) {
+				semantic_error("SRC@SRC is not allowed.\n");
+				return -EINVAL;
+			}
+			pp->file = strdup(arg);
+			if (pp->file == NULL)
+				return -ENOMEM;
 			break;
 		case '%':	/* Probe places */
 			if (strcmp(arg, "return") == 0) {
 				pp->retprobe = 1;
-			} else	/* Others not supported yet */
-				semantic_error("%%%s is not supported.", arg);
+			} else {	/* Others not supported yet */
+				semantic_error("%%%s is not supported.\n", arg);
+				return -ENOTSUP;
+			}
 			break;
-		default:
-			DIE_IF("Program has a bug.");
+		default:	/* Buggy case */
+			pr_err("This program has a bug at %s:%d.\n",
+				__FILE__, __LINE__);
+			return -ENOTSUP;
 			break;
 		}
 	}
 
 	/* Exclusion check */
-	if (pp->lazy_line && pp->line)
+	if (pp->lazy_line && pp->line) {
 		semantic_error("Lazy pattern can't be used with line number.");
+		return -EINVAL;
+	}
 
-	if (pp->lazy_line && pp->offset)
+	if (pp->lazy_line && pp->offset) {
 		semantic_error("Lazy pattern can't be used with offset.");
+		return -EINVAL;
+	}
 
-	if (pp->line && pp->offset)
+	if (pp->line && pp->offset) {
 		semantic_error("Offset can't be used with line number.");
+		return -EINVAL;
+	}
 
-	if (!pp->line && !pp->lazy_line && pp->file && !pp->function)
+	if (!pp->line && !pp->lazy_line && pp->file && !pp->function) {
 		semantic_error("File always requires line number or "
 			       "lazy pattern.");
+		return -EINVAL;
+	}
 
-	if (pp->offset && !pp->function)
+	if (pp->offset && !pp->function) {
 		semantic_error("Offset requires an entry function.");
+		return -EINVAL;
+	}
 
-	if (pp->retprobe && !pp->function)
+	if (pp->retprobe && !pp->function) {
 		semantic_error("Return probe requires an entry function.");
+		return -EINVAL;
+	}
 
-	if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe)
+	if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) {
 		semantic_error("Offset/Line/Lazy pattern can't be used with "
 			       "return probe.");
+		return -EINVAL;
+	}
 
 	pr_debug("symbol:%s file:%s line:%d offset:%lu return:%d lazy:%s\n",
 		 pp->function, pp->file, pp->line, pp->offset, pp->retprobe,
 		 pp->lazy_line);
+	return 0;
 }
 
 /* Parse perf-probe event argument */
-static void parse_perf_probe_arg(const char *str, struct perf_probe_arg *arg)
+static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
 {
-	const char *tmp;
+	char *tmp;
 	struct perf_probe_arg_field **fieldp;
 
 	pr_debug("parsing arg: %s into ", str);
 
+	tmp = strchr(str, '=');
+	if (tmp) {
+		arg->name = strndup(str, tmp - str);
+		if (arg->name == NULL)
+			return -ENOMEM;
+		pr_debug("name:%s ", arg->name);
+		str = tmp + 1;
+	}
+
+	tmp = strchr(str, ':');
+	if (tmp) {	/* Type setting */
+		*tmp = '\0';
+		arg->type = strdup(tmp + 1);
+		if (arg->type == NULL)
+			return -ENOMEM;
+		pr_debug("type:%s ", arg->type);
+	}
+
 	tmp = strpbrk(str, "-.");
 	if (!is_c_varname(str) || !tmp) {
 		/* A variable, register, symbol or special value */
-		arg->name = xstrdup(str);
-		pr_debug("%s\n", arg->name);
-		return;
+		arg->var = strdup(str);
+		if (arg->var == NULL)
+			return -ENOMEM;
+		pr_debug("%s\n", arg->var);
+		return 0;
 	}
 
 	/* Structure fields */
-	arg->name = xstrndup(str, tmp - str);
-	pr_debug("%s, ", arg->name);
+	arg->var = strndup(str, tmp - str);
+	if (arg->var == NULL)
+		return -ENOMEM;
+	pr_debug("%s, ", arg->var);
 	fieldp = &arg->field;
 
 	do {
-		*fieldp = xzalloc(sizeof(struct perf_probe_arg_field));
+		*fieldp = zalloc(sizeof(struct perf_probe_arg_field));
+		if (*fieldp == NULL)
+			return -ENOMEM;
 		if (*tmp == '.') {
 			str = tmp + 1;
 			(*fieldp)->ref = false;
 		} else if (tmp[1] == '>') {
 			str = tmp + 2;
 			(*fieldp)->ref = true;
-		} else
-			semantic_error("Argument parse error: %s", str);
+		} else {
+			semantic_error("Argument parse error: %s\n", str);
+			return -EINVAL;
+		}
 
 		tmp = strpbrk(str, "-.");
 		if (tmp) {
-			(*fieldp)->name = xstrndup(str, tmp - str);
+			(*fieldp)->name = strndup(str, tmp - str);
+			if ((*fieldp)->name == NULL)
+				return -ENOMEM;
 			pr_debug("%s(%d), ", (*fieldp)->name, (*fieldp)->ref);
 			fieldp = &(*fieldp)->next;
 		}
 	} while (tmp);
-	(*fieldp)->name = xstrdup(str);
+	(*fieldp)->name = strdup(str);
+	if ((*fieldp)->name == NULL)
+		return -ENOMEM;
 	pr_debug("%s(%d)\n", (*fieldp)->name, (*fieldp)->ref);
+
+	/* If no name is specified, set the last field name */
+	if (!arg->name) {
+		arg->name = strdup((*fieldp)->name);
+		if (arg->name == NULL)
+			return -ENOMEM;
+	}
+	return 0;
 }
 
 /* Parse perf-probe event command */
-void parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev)
+int parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev)
 {
 	char **argv;
-	int argc, i;
+	int argc, i, ret = 0;
 
 	argv = argv_split(cmd, &argc);
-	if (!argv)
-		die("argv_split failed.");
-	if (argc > MAX_PROBE_ARGS + 1)
-		semantic_error("Too many arguments");
-
+	if (!argv) {
+		pr_debug("Failed to split arguments.\n");
+		return -ENOMEM;
+	}
+	if (argc - 1 > MAX_PROBE_ARGS) {
+		semantic_error("Too many probe arguments (%d).\n", argc - 1);
+		ret = -ERANGE;
+		goto out;
+	}
 	/* Parse probe point */
-	parse_perf_probe_point(argv[0], pev);
+	ret = parse_perf_probe_point(argv[0], pev);
+	if (ret < 0)
+		goto out;
 
 	/* Copy arguments and ensure return probe has no C argument */
 	pev->nargs = argc - 1;
-	pev->args = xzalloc(sizeof(struct perf_probe_arg) * pev->nargs);
-	for (i = 0; i < pev->nargs; i++) {
-		parse_perf_probe_arg(argv[i + 1], &pev->args[i]);
-		if (is_c_varname(pev->args[i].name) && pev->point.retprobe)
-			semantic_error("You can't specify local variable for"
-				       " kretprobe");
+	pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs);
+	if (pev->args == NULL) {
+		ret = -ENOMEM;
+		goto out;
 	}
-
+	for (i = 0; i < pev->nargs && ret >= 0; i++) {
+		ret = parse_perf_probe_arg(argv[i + 1], &pev->args[i]);
+		if (ret >= 0 &&
+		    is_c_varname(pev->args[i].var) && pev->point.retprobe) {
+			semantic_error("You can't specify local variable for"
+				       " kretprobe.\n");
+			ret = -EINVAL;
+		}
+	}
+out:
 	argv_free(argv);
+
+	return ret;
 }
 
 /* Return true if this perf_probe_event requires debuginfo */
@@ -514,14 +677,14 @@
 		return true;
 
 	for (i = 0; i < pev->nargs; i++)
-		if (is_c_varname(pev->args[i].name))
+		if (is_c_varname(pev->args[i].var))
 			return true;
 
 	return false;
 }
 
 /* Parse kprobe_events event into struct probe_point */
-void parse_kprobe_trace_command(const char *cmd, struct kprobe_trace_event *tev)
+int parse_kprobe_trace_command(const char *cmd, struct kprobe_trace_event *tev)
 {
 	struct kprobe_trace_point *tp = &tev->point;
 	char pr;
@@ -531,17 +694,25 @@
 
 	pr_debug("Parsing kprobe_events: %s\n", cmd);
 	argv = argv_split(cmd, &argc);
-	if (!argv)
-		die("argv_split failed.");
-	if (argc < 2)
-		semantic_error("Too less arguments.");
+	if (!argv) {
+		pr_debug("Failed to split arguments.\n");
+		return -ENOMEM;
+	}
+	if (argc < 2) {
+		semantic_error("Too few probe arguments.\n");
+		ret = -ERANGE;
+		goto out;
+	}
 
 	/* Scan event and group name. */
 	ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]",
 		     &pr, (float *)(void *)&tev->group,
 		     (float *)(void *)&tev->event);
-	if (ret != 3)
-		semantic_error("Failed to parse event name: %s", argv[0]);
+	if (ret != 3) {
+		semantic_error("Failed to parse event name: %s\n", argv[0]);
+		ret = -EINVAL;
+		goto out;
+	}
 	pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr);
 
 	tp->retprobe = (pr == 'r');
@@ -553,19 +724,29 @@
 		tp->offset = 0;
 
 	tev->nargs = argc - 2;
-	tev->args = xzalloc(sizeof(struct kprobe_trace_arg) * tev->nargs);
+	tev->args = zalloc(sizeof(struct kprobe_trace_arg) * tev->nargs);
+	if (tev->args == NULL) {
+		ret = -ENOMEM;
+		goto out;
+	}
 	for (i = 0; i < tev->nargs; i++) {
 		p = strchr(argv[i + 2], '=');
 		if (p)	/* We don't need which register is assigned. */
 			*p++ = '\0';
 		else
 			p = argv[i + 2];
-		tev->args[i].name = xstrdup(argv[i + 2]);
+		tev->args[i].name = strdup(argv[i + 2]);
 		/* TODO: parse regs and offset */
-		tev->args[i].value = xstrdup(p);
+		tev->args[i].value = strdup(p);
+		if (tev->args[i].name == NULL || tev->args[i].value == NULL) {
+			ret = -ENOMEM;
+			goto out;
+		}
 	}
-
+	ret = 0;
+out:
 	argv_free(argv);
+	return ret;
 }
 
 /* Compose only probe arg */
@@ -575,7 +756,10 @@
 	int ret;
 	char *tmp = buf;
 
-	ret = e_snprintf(tmp, len, "%s", pa->name);
+	if (pa->name && pa->var)
+		ret = e_snprintf(tmp, len, "%s=%s", pa->name, pa->var);
+	else
+		ret = e_snprintf(tmp, len, "%s", pa->name ? pa->name : pa->var);
 	if (ret <= 0)
 		goto error;
 	tmp += ret;
@@ -590,9 +774,20 @@
 		len -= ret;
 		field = field->next;
 	}
+
+	if (pa->type) {
+		ret = e_snprintf(tmp, len, ":%s", pa->type);
+		if (ret <= 0)
+			goto error;
+		tmp += ret;
+		len -= ret;
+	}
+
 	return tmp - buf;
 error:
-	die("Failed to synthesize perf probe argument: %s", strerror(-ret));
+	pr_debug("Failed to synthesize perf probe argument: %s",
+		 strerror(-ret));
+	return ret;
 }
 
 /* Compose only probe point (not argument) */
@@ -602,7 +797,11 @@
 	char offs[32] = "", line[32] = "", file[32] = "";
 	int ret, len;
 
-	buf = xzalloc(MAX_CMDLEN);
+	buf = zalloc(MAX_CMDLEN);
+	if (buf == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
 	if (pp->offset) {
 		ret = e_snprintf(offs, 32, "+%lu", pp->offset);
 		if (ret <= 0)
@@ -614,12 +813,12 @@
 			goto error;
 	}
 	if (pp->file) {
-		len = strlen(pp->file) - 32;
+		len = strlen(pp->file) - 31;
 		if (len < 0)
 			len = 0;
 		tmp = strchr(pp->file + len, '/');
 		if (!tmp)
-			tmp = pp->file + len - 1;
+			tmp = pp->file + len;
 		ret = e_snprintf(file, 32, "@%s", tmp + 1);
 		if (ret <= 0)
 			goto error;
@@ -636,7 +835,11 @@
 
 	return buf;
 error:
-	die("Failed to synthesize perf probe point: %s", strerror(-ret));
+	pr_debug("Failed to synthesize perf probe point: %s",
+		 strerror(-ret));
+	if (buf)
+		free(buf);
+	return NULL;
 }
 
 #if 0
@@ -727,6 +930,13 @@
 		buf += ret;
 		buflen -= ret;
 	}
+	/* Print argument type */
+	if (arg->type) {
+		ret = e_snprintf(buf, buflen, ":%s", arg->type);
+		if (ret <= 0)
+			return ret;
+		buf += ret;
+	}
 
 	return buf - tmp;
 }
@@ -737,7 +947,10 @@
 	char *buf;
 	int i, len, ret;
 
-	buf = xzalloc(MAX_CMDLEN);
+	buf = zalloc(MAX_CMDLEN);
+	if (buf == NULL)
+		return NULL;
+
 	len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s+%lu",
 			 tp->retprobe ? 'r' : 'p',
 			 tev->group, tev->event,
@@ -759,29 +972,44 @@
 	return NULL;
 }
 
-void convert_to_perf_probe_event(struct kprobe_trace_event *tev,
-				 struct perf_probe_event *pev)
+int convert_to_perf_probe_event(struct kprobe_trace_event *tev,
+				struct perf_probe_event *pev)
 {
-	char buf[64];
-	int i;
+	char buf[64] = "";
+	int i, ret;
 
 	/* Convert event/group name */
-	pev->event = xstrdup(tev->event);
-	pev->group = xstrdup(tev->group);
+	pev->event = strdup(tev->event);
+	pev->group = strdup(tev->group);
+	if (pev->event == NULL || pev->group == NULL)
+		return -ENOMEM;
 
 	/* Convert trace_point to probe_point */
-	convert_to_perf_probe_point(&tev->point, &pev->point);
+	ret = convert_to_perf_probe_point(&tev->point, &pev->point);
+	if (ret < 0)
+		return ret;
 
 	/* Convert trace_arg to probe_arg */
 	pev->nargs = tev->nargs;
-	pev->args = xzalloc(sizeof(struct perf_probe_arg) * pev->nargs);
-	for (i = 0; i < tev->nargs; i++)
+	pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs);
+	if (pev->args == NULL)
+		return -ENOMEM;
+	for (i = 0; i < tev->nargs && ret >= 0; i++) {
 		if (tev->args[i].name)
-			pev->args[i].name = xstrdup(tev->args[i].name);
+			pev->args[i].name = strdup(tev->args[i].name);
 		else {
-			synthesize_kprobe_trace_arg(&tev->args[i], buf, 64);
-			pev->args[i].name = xstrdup(buf);
+			ret = synthesize_kprobe_trace_arg(&tev->args[i],
+							  buf, 64);
+			pev->args[i].name = strdup(buf);
 		}
+		if (pev->args[i].name == NULL && ret >= 0)
+			ret = -ENOMEM;
+	}
+
+	if (ret < 0)
+		clear_perf_probe_event(pev);
+
+	return ret;
 }
 
 void clear_perf_probe_event(struct perf_probe_event *pev)
@@ -803,6 +1031,10 @@
 	for (i = 0; i < pev->nargs; i++) {
 		if (pev->args[i].name)
 			free(pev->args[i].name);
+		if (pev->args[i].var)
+			free(pev->args[i].var);
+		if (pev->args[i].type)
+			free(pev->args[i].type);
 		field = pev->args[i].field;
 		while (field) {
 			next = field->next;
@@ -833,6 +1065,8 @@
 			free(tev->args[i].name);
 		if (tev->args[i].value)
 			free(tev->args[i].value);
+		if (tev->args[i].type)
+			free(tev->args[i].type);
 		ref = tev->args[i].ref;
 		while (ref) {
 			next = ref->next;
@@ -848,24 +1082,31 @@
 static int open_kprobe_events(bool readwrite)
 {
 	char buf[PATH_MAX];
+	const char *__debugfs;
 	int ret;
 
-	ret = e_snprintf(buf, PATH_MAX, "%s/../kprobe_events", debugfs_path);
-	if (ret < 0)
-		die("Failed to make kprobe_events path.");
+	__debugfs = debugfs_find_mountpoint();
+	if (__debugfs == NULL) {
+		pr_warning("Debugfs is not mounted.\n");
+		return -ENOENT;
+	}
 
-	if (readwrite && !probe_event_dry_run)
-		ret = open(buf, O_RDWR, O_APPEND);
-	else
-		ret = open(buf, O_RDONLY, 0);
+	ret = e_snprintf(buf, PATH_MAX, "%stracing/kprobe_events", __debugfs);
+	if (ret >= 0) {
+		pr_debug("Opening %s write=%d\n", buf, readwrite);
+		if (readwrite && !probe_event_dry_run)
+			ret = open(buf, O_RDWR, O_APPEND);
+		else
+			ret = open(buf, O_RDONLY, 0);
+	}
 
 	if (ret < 0) {
 		if (errno == ENOENT)
-			die("kprobe_events file does not exist -"
-			    " please rebuild with CONFIG_KPROBE_EVENT.");
+			pr_warning("kprobe_events file does not exist - please"
+				 " rebuild kernel with CONFIG_KPROBE_EVENT.\n");
 		else
-			die("Could not open kprobe_events file: %s",
-			    strerror(errno));
+			pr_warning("Failed to open kprobe_events file: %s\n",
+				   strerror(errno));
 	}
 	return ret;
 }
@@ -891,8 +1132,11 @@
 		if (p[idx] == '\n')
 			p[idx] = '\0';
 		ret = strlist__add(sl, buf);
-		if (ret < 0)
-			die("strlist__add failed: %s", strerror(-ret));
+		if (ret < 0) {
+			pr_debug("strlist__add failed: %s\n", strerror(-ret));
+			strlist__delete(sl);
+			return NULL;
+		}
 	}
 	fclose(fp);
 
@@ -900,7 +1144,7 @@
 }
 
 /* Show an event */
-static void show_perf_probe_event(struct perf_probe_event *pev)
+static int show_perf_probe_event(struct perf_probe_event *pev)
 {
 	int i, ret;
 	char buf[128];
@@ -908,52 +1152,71 @@
 
 	/* Synthesize only event probe point */
 	place = synthesize_perf_probe_point(&pev->point);
+	if (!place)
+		return -EINVAL;
 
 	ret = e_snprintf(buf, 128, "%s:%s", pev->group, pev->event);
 	if (ret < 0)
-		die("Failed to copy event: %s", strerror(-ret));
+		return ret;
+
 	printf("  %-20s (on %s", buf, place);
 
 	if (pev->nargs > 0) {
 		printf(" with");
 		for (i = 0; i < pev->nargs; i++) {
-			synthesize_perf_probe_arg(&pev->args[i], buf, 128);
+			ret = synthesize_perf_probe_arg(&pev->args[i],
+							buf, 128);
+			if (ret < 0)
+				break;
 			printf(" %s", buf);
 		}
 	}
 	printf(")\n");
 	free(place);
+	return ret;
 }
 
 /* List up current perf-probe events */
-void show_perf_probe_events(void)
+int show_perf_probe_events(void)
 {
-	int fd;
+	int fd, ret;
 	struct kprobe_trace_event tev;
 	struct perf_probe_event pev;
 	struct strlist *rawlist;
 	struct str_node *ent;
 
 	setup_pager();
-	init_vmlinux();
+	ret = init_vmlinux();
+	if (ret < 0)
+		return ret;
 
 	memset(&tev, 0, sizeof(tev));
 	memset(&pev, 0, sizeof(pev));
 
 	fd = open_kprobe_events(false);
+	if (fd < 0)
+		return fd;
+
 	rawlist = get_kprobe_trace_command_rawlist(fd);
 	close(fd);
+	if (!rawlist)
+		return -ENOENT;
 
 	strlist__for_each(ent, rawlist) {
-		parse_kprobe_trace_command(ent->s, &tev);
-		convert_to_perf_probe_event(&tev, &pev);
-		/* Show an event */
-		show_perf_probe_event(&pev);
+		ret = parse_kprobe_trace_command(ent->s, &tev);
+		if (ret >= 0) {
+			ret = convert_to_perf_probe_event(&tev, &pev);
+			if (ret >= 0)
+				ret = show_perf_probe_event(&pev);
+		}
 		clear_perf_probe_event(&pev);
 		clear_kprobe_trace_event(&tev);
+		if (ret < 0)
+			break;
 	}
-
 	strlist__delete(rawlist);
+
+	return ret;
 }
 
 /* Get current perf-probe event names */
@@ -963,86 +1226,116 @@
 	struct strlist *sl, *rawlist;
 	struct str_node *ent;
 	struct kprobe_trace_event tev;
+	int ret = 0;
 
 	memset(&tev, 0, sizeof(tev));
 
 	rawlist = get_kprobe_trace_command_rawlist(fd);
 	sl = strlist__new(true, NULL);
 	strlist__for_each(ent, rawlist) {
-		parse_kprobe_trace_command(ent->s, &tev);
+		ret = parse_kprobe_trace_command(ent->s, &tev);
+		if (ret < 0)
+			break;
 		if (include_group) {
-			if (e_snprintf(buf, 128, "%s:%s", tev.group,
-				       tev.event) < 0)
-				die("Failed to copy group:event name.");
-			strlist__add(sl, buf);
+			ret = e_snprintf(buf, 128, "%s:%s", tev.group,
+					tev.event);
+			if (ret >= 0)
+				ret = strlist__add(sl, buf);
 		} else
-			strlist__add(sl, tev.event);
+			ret = strlist__add(sl, tev.event);
 		clear_kprobe_trace_event(&tev);
+		if (ret < 0)
+			break;
 	}
-
 	strlist__delete(rawlist);
 
+	if (ret < 0) {
+		strlist__delete(sl);
+		return NULL;
+	}
 	return sl;
 }
 
-static void write_kprobe_trace_event(int fd, struct kprobe_trace_event *tev)
+static int write_kprobe_trace_event(int fd, struct kprobe_trace_event *tev)
 {
 	int ret;
 	char *buf = synthesize_kprobe_trace_command(tev);
 
+	if (!buf) {
+		pr_debug("Failed to synthesize kprobe trace event.\n");
+		return -EINVAL;
+	}
+
 	pr_debug("Writing event: %s\n", buf);
 	if (!probe_event_dry_run) {
 		ret = write(fd, buf, strlen(buf));
 		if (ret <= 0)
-			die("Failed to write event: %s", strerror(errno));
+			pr_warning("Failed to write event: %s\n",
+				   strerror(errno));
 	}
 	free(buf);
+	return ret;
 }
 
-static void get_new_event_name(char *buf, size_t len, const char *base,
-			       struct strlist *namelist, bool allow_suffix)
+static int get_new_event_name(char *buf, size_t len, const char *base,
+			      struct strlist *namelist, bool allow_suffix)
 {
 	int i, ret;
 
 	/* Try no suffix */
 	ret = e_snprintf(buf, len, "%s", base);
-	if (ret < 0)
-		die("snprintf() failed: %s", strerror(-ret));
+	if (ret < 0) {
+		pr_debug("snprintf() failed: %s\n", strerror(-ret));
+		return ret;
+	}
 	if (!strlist__has_entry(namelist, buf))
-		return;
+		return 0;
 
 	if (!allow_suffix) {
 		pr_warning("Error: event \"%s\" already exists. "
 			   "(Use -f to force duplicates.)\n", base);
-		die("Can't add new event.");
+		return -EEXIST;
 	}
 
 	/* Try to add suffix */
 	for (i = 1; i < MAX_EVENT_INDEX; i++) {
 		ret = e_snprintf(buf, len, "%s_%d", base, i);
-		if (ret < 0)
-			die("snprintf() failed: %s", strerror(-ret));
+		if (ret < 0) {
+			pr_debug("snprintf() failed: %s\n", strerror(-ret));
+			return ret;
+		}
 		if (!strlist__has_entry(namelist, buf))
 			break;
 	}
-	if (i == MAX_EVENT_INDEX)
-		die("Too many events are on the same function.");
+	if (i == MAX_EVENT_INDEX) {
+		pr_warning("Too many events are on the same function.\n");
+		ret = -ERANGE;
+	}
+
+	return ret;
 }
 
-static void __add_kprobe_trace_events(struct perf_probe_event *pev,
-				      struct kprobe_trace_event *tevs,
-				      int ntevs, bool allow_suffix)
+static int __add_kprobe_trace_events(struct perf_probe_event *pev,
+				     struct kprobe_trace_event *tevs,
+				     int ntevs, bool allow_suffix)
 {
-	int i, fd;
+	int i, fd, ret;
 	struct kprobe_trace_event *tev = NULL;
 	char buf[64];
 	const char *event, *group;
 	struct strlist *namelist;
 
 	fd = open_kprobe_events(true);
+	if (fd < 0)
+		return fd;
 	/* Get current event names */
 	namelist = get_kprobe_trace_event_names(fd, false);
+	if (!namelist) {
+		pr_debug("Failed to get current event list.\n");
+		return -EIO;
+	}
 
+	ret = 0;
 	printf("Add new event%s\n", (ntevs > 1) ? "s:" : ":");
 	for (i = 0; i < ntevs; i++) {
 		tev = &tevs[i];
@@ -1059,12 +1352,21 @@
 			group = PERFPROBE_GROUP;
 
 		/* Get an unused new event name */
-		get_new_event_name(buf, 64, event, namelist, allow_suffix);
+		ret = get_new_event_name(buf, 64, event,
+					 namelist, allow_suffix);
+		if (ret < 0)
+			break;
 		event = buf;
 
-		tev->event = xstrdup(event);
-		tev->group = xstrdup(group);
-		write_kprobe_trace_event(fd, tev);
+		tev->event = strdup(event);
+		tev->group = strdup(group);
+		if (tev->event == NULL || tev->group == NULL) {
+			ret = -ENOMEM;
+			break;
+		}
+		ret = write_kprobe_trace_event(fd, tev);
+		if (ret < 0)
+			break;
 		/* Add added event name to namelist */
 		strlist__add(namelist, event);
 
@@ -1086,49 +1388,90 @@
 		 */
 		allow_suffix = true;
 	}
-	/* Show how to use the event. */
-	printf("\nYou can now use it on all perf tools, such as:\n\n");
-	printf("\tperf record -e %s:%s -a sleep 1\n\n", tev->group, tev->event);
+
+	if (ret >= 0) {
+		/* Show how to use the event. */
+		printf("\nYou can now use it on all perf tools, such as:\n\n");
+		printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group,
+			 tev->event);
+	}
 
 	strlist__delete(namelist);
 	close(fd);
+	return ret;
 }
 
 static int convert_to_kprobe_trace_events(struct perf_probe_event *pev,
 					  struct kprobe_trace_event **tevs)
 {
 	struct symbol *sym;
-	int ntevs = 0, i;
+	int ret = 0, i;
 	struct kprobe_trace_event *tev;
 
 	/* Convert perf_probe_event with debuginfo */
-	ntevs = try_to_find_kprobe_trace_events(pev, tevs);
-	if (ntevs > 0)
-		return ntevs;
+	ret = try_to_find_kprobe_trace_events(pev, tevs);
+	if (ret != 0)
+		return ret;
 
 	/* Allocate trace event buffer */
-	ntevs = 1;
-	tev = *tevs = xzalloc(sizeof(struct kprobe_trace_event));
+	tev = *tevs = zalloc(sizeof(struct kprobe_trace_event));
+	if (tev == NULL)
+		return -ENOMEM;
 
 	/* Copy parameters */
-	tev->point.symbol = xstrdup(pev->point.function);
+	tev->point.symbol = strdup(pev->point.function);
+	if (tev->point.symbol == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
 	tev->point.offset = pev->point.offset;
 	tev->nargs = pev->nargs;
 	if (tev->nargs) {
-		tev->args = xzalloc(sizeof(struct kprobe_trace_arg)
-				    * tev->nargs);
-		for (i = 0; i < tev->nargs; i++)
-			tev->args[i].value = xstrdup(pev->args[i].name);
+		tev->args = zalloc(sizeof(struct kprobe_trace_arg)
+				   * tev->nargs);
+		if (tev->args == NULL) {
+			ret = -ENOMEM;
+			goto error;
+		}
+		for (i = 0; i < tev->nargs; i++) {
+			if (pev->args[i].name) {
+				tev->args[i].name = strdup(pev->args[i].name);
+				if (tev->args[i].name == NULL) {
+					ret = -ENOMEM;
+					goto error;
+				}
+			}
+			tev->args[i].value = strdup(pev->args[i].var);
+			if (tev->args[i].value == NULL) {
+				ret = -ENOMEM;
+				goto error;
+			}
+			if (pev->args[i].type) {
+				tev->args[i].type = strdup(pev->args[i].type);
+				if (tev->args[i].type == NULL) {
+					ret = -ENOMEM;
+					goto error;
+				}
+			}
+		}
 	}
 
 	/* Currently just checking function name from symbol map */
 	sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION],
 				       tev->point.symbol, NULL);
-	if (!sym)
-		die("Kernel symbol \'%s\' not found - probe not added.",
-		    tev->point.symbol);
+	if (!sym) {
+		pr_warning("Kernel symbol \'%s\' not found.\n",
+			   tev->point.symbol);
+		ret = -ENOENT;
+		goto error;
+	}
 
-	return ntevs;
+	return 1;
+error:
+	clear_kprobe_trace_event(tev);
+	free(tev);
+	*tevs = NULL;
+	return ret;
 }
 
 struct __event_package {
@@ -1137,96 +1480,137 @@
 	int				ntevs;
 };
 
-void add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
-			   bool force_add)
+int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
+			  bool force_add)
 {
-	int i;
+	int i, j, ret;
 	struct __event_package *pkgs;
 
-	pkgs = xzalloc(sizeof(struct __event_package) * npevs);
+	pkgs = zalloc(sizeof(struct __event_package) * npevs);
+	if (pkgs == NULL)
+		return -ENOMEM;
 
 	/* Init vmlinux path */
-	init_vmlinux();
+	ret = init_vmlinux();
+	if (ret < 0)
+		return ret;
 
 	/* Loop 1: convert all events */
 	for (i = 0; i < npevs; i++) {
 		pkgs[i].pev = &pevs[i];
 		/* Convert with or without debuginfo */
-		pkgs[i].ntevs = convert_to_kprobe_trace_events(pkgs[i].pev,
-							       &pkgs[i].tevs);
+		ret  = convert_to_kprobe_trace_events(pkgs[i].pev,
+						      &pkgs[i].tevs);
+		if (ret < 0)
+			goto end;
+		pkgs[i].ntevs = ret;
 	}
 
 	/* Loop 2: add all events */
+	for (i = 0; i < npevs && ret >= 0; i++)
+		ret = __add_kprobe_trace_events(pkgs[i].pev, pkgs[i].tevs,
+						pkgs[i].ntevs, force_add);
+end:
+	/* Loop 3: cleanup trace events  */
 	for (i = 0; i < npevs; i++)
-		__add_kprobe_trace_events(pkgs[i].pev, pkgs[i].tevs,
-					  pkgs[i].ntevs, force_add);
-	/* TODO: cleanup all trace events? */
+		for (j = 0; j < pkgs[i].ntevs; j++)
+			clear_kprobe_trace_event(&pkgs[i].tevs[j]);
+
+	return ret;
 }
 
-static void __del_trace_kprobe_event(int fd, struct str_node *ent)
+static int __del_trace_kprobe_event(int fd, struct str_node *ent)
 {
 	char *p;
 	char buf[128];
 	int ret;
 
 	/* Convert from perf-probe event to trace-kprobe event */
-	if (e_snprintf(buf, 128, "-:%s", ent->s) < 0)
-		die("Failed to copy event.");
+	ret = e_snprintf(buf, 128, "-:%s", ent->s);
+	if (ret < 0)
+		goto error;
+
 	p = strchr(buf + 2, ':');
-	if (!p)
-		die("Internal error: %s should have ':' but not.", ent->s);
+	if (!p) {
+		pr_debug("Internal error: %s should have ':' but not.\n",
+			 ent->s);
+		ret = -ENOTSUP;
+		goto error;
+	}
 	*p = '/';
 
 	pr_debug("Writing event: %s\n", buf);
 	ret = write(fd, buf, strlen(buf));
-	if (ret <= 0)
-		die("Failed to write event: %s", strerror(errno));
+	if (ret < 0)
+		goto error;
+
 	printf("Remove event: %s\n", ent->s);
+	return 0;
+error:
+	pr_warning("Failed to delete event: %s\n", strerror(-ret));
+	return ret;
 }
 
-static void del_trace_kprobe_event(int fd, const char *group,
-				   const char *event, struct strlist *namelist)
+static int del_trace_kprobe_event(int fd, const char *group,
+				  const char *event, struct strlist *namelist)
 {
 	char buf[128];
 	struct str_node *ent, *n;
-	int found = 0;
+	int found = 0, ret = 0;
 
-	if (e_snprintf(buf, 128, "%s:%s", group, event) < 0)
-		die("Failed to copy event.");
+	ret = e_snprintf(buf, 128, "%s:%s", group, event);
+	if (ret < 0) {
+		pr_err("Failed to copy event.");
+		return ret;
+	}
 
 	if (strpbrk(buf, "*?")) { /* Glob-exp */
 		strlist__for_each_safe(ent, n, namelist)
 			if (strglobmatch(ent->s, buf)) {
 				found++;
-				__del_trace_kprobe_event(fd, ent);
+				ret = __del_trace_kprobe_event(fd, ent);
+				if (ret < 0)
+					break;
 				strlist__remove(namelist, ent);
 			}
 	} else {
 		ent = strlist__find(namelist, buf);
 		if (ent) {
 			found++;
-			__del_trace_kprobe_event(fd, ent);
-			strlist__remove(namelist, ent);
+			ret = __del_trace_kprobe_event(fd, ent);
+			if (ret >= 0)
+				strlist__remove(namelist, ent);
 		}
 	}
-	if (found == 0)
-		pr_info("Info: event \"%s\" does not exist, could not remove it.\n", buf);
+	if (found == 0 && ret >= 0)
+		pr_info("Info: Event \"%s\" does not exist.\n", buf);
+
+	return ret;
 }
 
-void del_perf_probe_events(struct strlist *dellist)
+int del_perf_probe_events(struct strlist *dellist)
 {
-	int fd;
+	int fd, ret = 0;
 	const char *group, *event;
 	char *p, *str;
 	struct str_node *ent;
 	struct strlist *namelist;
 
 	fd = open_kprobe_events(true);
+	if (fd < 0)
+		return fd;
+
 	/* Get current event names */
 	namelist = get_kprobe_trace_event_names(fd, true);
+	if (namelist == NULL)
+		return -EINVAL;
 
 	strlist__for_each(ent, dellist) {
-		str = xstrdup(ent->s);
+		str = strdup(ent->s);
+		if (str == NULL) {
+			ret = -ENOMEM;
+			break;
+		}
 		pr_debug("Parsing: %s\n", str);
 		p = strchr(str, ':');
 		if (p) {
@@ -1238,10 +1622,14 @@
 			event = str;
 		}
 		pr_debug("Group: %s, Event: %s\n", group, event);
-		del_trace_kprobe_event(fd, group, event, namelist);
+		ret = del_trace_kprobe_event(fd, group, event, namelist);
 		free(str);
+		if (ret < 0)
+			break;
 	}
 	strlist__delete(namelist);
 	close(fd);
+
+	return ret;
 }
 
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 9d99fc2..e7ff0d0 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -23,6 +23,7 @@
 struct kprobe_trace_arg {
 	char				*name;	/* Argument name */
 	char				*value;	/* Base value */
+	char				*type;	/* Type name */
 	struct kprobe_trace_arg_ref	*ref;	/* Referencing offset */
 };
 
@@ -55,6 +56,8 @@
 /* Perf probe probing argument */
 struct perf_probe_arg {
 	char				*name;	/* Argument name */
+	char				*var;	/* Variable name */
+	char				*type;	/* Type name */
 	struct perf_probe_arg_field	*field;	/* Structure fields */
 };
 
@@ -71,25 +74,25 @@
 /* Line number container */
 struct line_node {
 	struct list_head	list;
-	unsigned int		line;
+	int			line;
 };
 
 /* Line range */
 struct line_range {
 	char			*file;		/* File name */
 	char			*function;	/* Function name */
-	unsigned int		start;		/* Start line number */
-	unsigned int		end;		/* End line number */
+	int			start;		/* Start line number */
+	int			end;		/* End line number */
 	int			offset;		/* Start line offset */
 	char			*path;		/* Real path name */
 	struct list_head	line_list;	/* Visible lines */
 };
 
 /* Command string to events */
-extern void parse_perf_probe_command(const char *cmd,
-				     struct perf_probe_event *pev);
-extern void parse_kprobe_trace_command(const char *cmd,
-				       struct kprobe_trace_event *tev);
+extern int parse_perf_probe_command(const char *cmd,
+				    struct perf_probe_event *pev);
+extern int parse_kprobe_trace_command(const char *cmd,
+				      struct kprobe_trace_event *tev);
 
 /* Events to command string */
 extern char *synthesize_perf_probe_command(struct perf_probe_event *pev);
@@ -101,22 +104,22 @@
 extern bool perf_probe_event_need_dwarf(struct perf_probe_event *pev);
 
 /* Convert from kprobe_trace_event to perf_probe_event */
-extern void convert_to_perf_probe_event(struct kprobe_trace_event *tev,
-					struct perf_probe_event *pev);
+extern int convert_to_perf_probe_event(struct kprobe_trace_event *tev,
+				       struct perf_probe_event *pev);
 
 /* Release event contents */
 extern void clear_perf_probe_event(struct perf_probe_event *pev);
 extern void clear_kprobe_trace_event(struct kprobe_trace_event *tev);
 
 /* Command string to line-range */
-extern void parse_line_range_desc(const char *cmd, struct line_range *lr);
+extern int parse_line_range_desc(const char *cmd, struct line_range *lr);
 
 
-extern void add_perf_probe_events(struct perf_probe_event *pevs, int ntevs,
-				  bool force_add);
-extern void del_perf_probe_events(struct strlist *dellist);
-extern void show_perf_probe_events(void);
-extern void show_line_range(struct line_range *lr);
+extern int add_perf_probe_events(struct perf_probe_event *pevs, int ntevs,
+				 bool force_add);
+extern int del_perf_probe_events(struct strlist *dellist);
+extern int show_perf_probe_events(void);
+extern int show_line_range(struct line_range *lr);
 
 
 /* Maximum index number of event-name postfix */
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index a851377..3e79775 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -84,6 +84,9 @@
 #define arch_regs_table x86_32_regs_table
 #endif
 
+/* Kprobe tracer basic type is up to u64 */
+#define MAX_BASIC_TYPE_BITS	64
+
 /* Return architecture dependent register string (for kprobe-tracer) */
 static const char *get_arch_regstr(unsigned int n)
 {
@@ -108,7 +111,7 @@
 /* Line number list operations */
 
 /* Add a line to line number list */
-static void line_list__add_line(struct list_head *head, unsigned int line)
+static int line_list__add_line(struct list_head *head, int line)
 {
 	struct line_node *ln;
 	struct list_head *p;
@@ -119,20 +122,23 @@
 			p = &ln->list;
 			goto found;
 		} else if (ln->line == line)	/* Already exist */
-			return ;
+			return 1;
 	}
 	/* List is empty, or the smallest entry */
 	p = head;
 found:
 	pr_debug("line list: add a line %u\n", line);
-	ln = xzalloc(sizeof(struct line_node));
+	ln = zalloc(sizeof(struct line_node));
+	if (ln == NULL)
+		return -ENOMEM;
 	ln->line = line;
 	INIT_LIST_HEAD(&ln->list);
 	list_add(&ln->list, p);
+	return 0;
 }
 
 /* Check if the line in line number list */
-static int line_list__has_line(struct list_head *head, unsigned int line)
+static int line_list__has_line(struct list_head *head, int line)
 {
 	struct line_node *ln;
 
@@ -193,19 +199,7 @@
 {
 	const char *name;
 	name = dwarf_diename(dw_die);
-	DIE_IF(name == NULL);
-	return strcmp(tname, name);
-}
-
-/* Get entry pc(or low pc, 1st entry of ranges)  of the die */
-static Dwarf_Addr die_get_entrypc(Dwarf_Die *dw_die)
-{
-	Dwarf_Addr epc;
-	int ret;
-
-	ret = dwarf_entrypc(dw_die, &epc);
-	DIE_IF(ret == -1);
-	return epc;
+	return name ? strcmp(tname, name) : -1;
 }
 
 /* Get type die, but skip qualifiers and typedef */
@@ -230,6 +224,58 @@
 	return die_mem;
 }
 
+static bool die_is_signed_type(Dwarf_Die *tp_die)
+{
+	Dwarf_Attribute attr;
+	Dwarf_Word ret;
+
+	if (dwarf_attr(tp_die, DW_AT_encoding, &attr) == NULL ||
+	    dwarf_formudata(&attr, &ret) != 0)
+		return false;
+
+	return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
+		ret == DW_ATE_signed_fixed);
+}
+
+static int die_get_byte_size(Dwarf_Die *tp_die)
+{
+	Dwarf_Attribute attr;
+	Dwarf_Word ret;
+
+	if (dwarf_attr(tp_die, DW_AT_byte_size, &attr) == NULL ||
+	    dwarf_formudata(&attr, &ret) != 0)
+		return 0;
+
+	return (int)ret;
+}
+
+/* Get data_member_location offset */
+static int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
+{
+	Dwarf_Attribute attr;
+	Dwarf_Op *expr;
+	size_t nexpr;
+	int ret;
+
+	if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL)
+		return -ENOENT;
+
+	if (dwarf_formudata(&attr, offs) != 0) {
+		/* DW_AT_data_member_location should be DW_OP_plus_uconst */
+		ret = dwarf_getlocation(&attr, &expr, &nexpr);
+		if (ret < 0 || nexpr == 0)
+			return -ENOENT;
+
+		if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) {
+			pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n",
+				 expr[0].atom, nexpr);
+			return -ENOTSUP;
+		}
+		*offs = (Dwarf_Word)expr[0].number;
+	}
+	return 0;
+}
+
 /* Return values for die_find callbacks */
 enum {
 	DIE_FIND_CB_FOUND = 0,		/* End of Search */
@@ -362,7 +408,7 @@
  */
 
 /* Show a location */
-static void convert_location(Dwarf_Op *op, struct probe_finder *pf)
+static int convert_location(Dwarf_Op *op, struct probe_finder *pf)
 {
 	unsigned int regn;
 	Dwarf_Word offs = 0;
@@ -370,11 +416,13 @@
 	const char *regs;
 	struct kprobe_trace_arg *tvar = pf->tvar;
 
-	/* TODO: support CFA */
 	/* If this is based on frame buffer, set the offset */
 	if (op->atom == DW_OP_fbreg) {
-		if (pf->fb_ops == NULL)
-			die("The attribute of frame base is not supported.\n");
+		if (pf->fb_ops == NULL) {
+			pr_warning("The attribute of frame base is not "
+				   "supported.\n");
+			return -ENOTSUP;
+		}
 		ref = true;
 		offs = op->number;
 		op = &pf->fb_ops[0];
@@ -392,84 +440,155 @@
 		ref = true;
 	} else if (op->atom == DW_OP_regx) {
 		regn = op->number;
-	} else
-		die("DW_OP %d is not supported.", op->atom);
+	} else {
+		pr_warning("DW_OP %x is not supported.\n", op->atom);
+		return -ENOTSUP;
+	}
 
 	regs = get_arch_regstr(regn);
-	if (!regs)
-		die("%u exceeds max register number.", regn);
+	if (!regs) {
+		pr_warning("%u exceeds max register number.\n", regn);
+		return -ERANGE;
+	}
 
-	tvar->value = xstrdup(regs);
+	tvar->value = strdup(regs);
+	if (tvar->value == NULL)
+		return -ENOMEM;
+
 	if (ref) {
-		tvar->ref = xzalloc(sizeof(struct kprobe_trace_arg_ref));
+		tvar->ref = zalloc(sizeof(struct kprobe_trace_arg_ref));
+		if (tvar->ref == NULL)
+			return -ENOMEM;
 		tvar->ref->offset = (long)offs;
 	}
+	return 0;
 }
 
-static void convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
+static int convert_variable_type(Dwarf_Die *vr_die,
+				 struct kprobe_trace_arg *targ)
+{
+	Dwarf_Die type;
+	char buf[16];
+	int ret;
+
+	if (die_get_real_type(vr_die, &type) == NULL) {
+		pr_warning("Failed to get a type information of %s.\n",
+			   dwarf_diename(vr_die));
+		return -ENOENT;
+	}
+
+	ret = die_get_byte_size(&type) * 8;
+	if (ret) {
+		/* Check the bitwidth */
+		if (ret > MAX_BASIC_TYPE_BITS) {
+			pr_info("%s exceeds max-bitwidth."
+				" Cut down to %d bits.\n",
+				dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
+			ret = MAX_BASIC_TYPE_BITS;
+		}
+
+		ret = snprintf(buf, 16, "%c%d",
+			       die_is_signed_type(&type) ? 's' : 'u', ret);
+		if (ret < 0 || ret >= 16) {
+			if (ret >= 16)
+				ret = -E2BIG;
+			pr_warning("Failed to convert variable type: %s\n",
+				   strerror(-ret));
+			return ret;
+		}
+		targ->type = strdup(buf);
+		if (targ->type == NULL)
+			return -ENOMEM;
+	}
+	return 0;
+}
+
+static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
 				    struct perf_probe_arg_field *field,
-				    struct kprobe_trace_arg_ref **ref_ptr)
+				    struct kprobe_trace_arg_ref **ref_ptr,
+				    Dwarf_Die *die_mem)
 {
 	struct kprobe_trace_arg_ref *ref = *ref_ptr;
-	Dwarf_Attribute attr;
-	Dwarf_Die member;
 	Dwarf_Die type;
 	Dwarf_Word offs;
+	int ret;
 
 	pr_debug("converting %s in %s\n", field->name, varname);
-	if (die_get_real_type(vr_die, &type) == NULL)
-		die("Failed to get a type information of %s.", varname);
+	if (die_get_real_type(vr_die, &type) == NULL) {
+		pr_warning("Failed to get the type of %s.\n", varname);
+		return -ENOENT;
+	}
 
 	/* Check the pointer and dereference */
 	if (dwarf_tag(&type) == DW_TAG_pointer_type) {
-		if (!field->ref)
-			die("Semantic error: %s must be referred by '->'",
-			    field->name);
+		if (!field->ref) {
+			pr_err("Semantic error: %s must be referred by '->'\n",
+			       field->name);
+			return -EINVAL;
+		}
 		/* Get the type pointed by this pointer */
-		if (die_get_real_type(&type, &type) == NULL)
-			die("Failed to get a type information of %s.", varname);
-
+		if (die_get_real_type(&type, &type) == NULL) {
+			pr_warning("Failed to get the type of %s.\n", varname);
+			return -ENOENT;
+		}
 		/* Verify it is a data structure  */
-		if (dwarf_tag(&type) != DW_TAG_structure_type)
-			die("%s is not a data structure.", varname);
+		if (dwarf_tag(&type) != DW_TAG_structure_type) {
+			pr_warning("%s is not a data structure.\n", varname);
+			return -EINVAL;
+		}
 
-		ref = xzalloc(sizeof(struct kprobe_trace_arg_ref));
+		ref = zalloc(sizeof(struct kprobe_trace_arg_ref));
+		if (ref == NULL)
+			return -ENOMEM;
 		if (*ref_ptr)
 			(*ref_ptr)->next = ref;
 		else
 			*ref_ptr = ref;
 	} else {
 		/* Verify it is a data structure  */
-		if (dwarf_tag(&type) != DW_TAG_structure_type)
-			die("%s is not a data structure.", varname);
-
-		if (field->ref)
-			die("Semantic error: %s must be referred by '.'",
-			    field->name);
-		if (!ref)
-			die("Structure on a register is not supported yet.");
+		if (dwarf_tag(&type) != DW_TAG_structure_type) {
+			pr_warning("%s is not a data structure.\n", varname);
+			return -EINVAL;
+		}
+		if (field->ref) {
+			pr_err("Semantic error: %s must be referred by '.'\n",
+			       field->name);
+			return -EINVAL;
+		}
+		if (!ref) {
+			pr_warning("Structure on a register is not "
+				   "supported yet.\n");
+			return -ENOTSUP;
+		}
 	}
 
-	if (die_find_member(&type, field->name, &member) == NULL)
-		die("%s(tyep:%s) has no member %s.", varname,
-		    dwarf_diename(&type), field->name);
+	if (die_find_member(&type, field->name, die_mem) == NULL) {
+		pr_warning("%s(tyep:%s) has no member %s.\n", varname,
+			   dwarf_diename(&type), field->name);
+		return -EINVAL;
+	}
 
 	/* Get the offset of the field */
-	if (dwarf_attr(&member, DW_AT_data_member_location, &attr) == NULL ||
-	    dwarf_formudata(&attr, &offs) != 0)
-		die("Failed to get the offset of %s.", field->name);
+	ret = die_get_data_member_location(die_mem, &offs);
+	if (ret < 0) {
+		pr_warning("Failed to get the offset of %s.\n", field->name);
+		return ret;
+	}
 	ref->offset += (long)offs;
 
 	/* Converting next field */
 	if (field->next)
-		convert_variable_fields(&member, field->name, field->next,
-					&ref);
+		return convert_variable_fields(die_mem, field->name,
+					field->next, &ref, die_mem);
+	else
+		return 0;
 }
 
 /* Show a variables in kprobe event format */
-static void convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
+static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
 {
 	Dwarf_Attribute attr;
+	Dwarf_Die die_mem;
 	Dwarf_Op *expr;
 	size_t nexpr;
 	int ret;
@@ -481,44 +600,74 @@
 	if (ret <= 0 || nexpr == 0)
 		goto error;
 
-	convert_location(expr, pf);
-
-	if (pf->pvar->field)
-		convert_variable_fields(vr_die, pf->pvar->name,
-					pf->pvar->field, &pf->tvar->ref);
+	ret = convert_location(expr, pf);
+	if (ret == 0 && pf->pvar->field) {
+		ret = convert_variable_fields(vr_die, pf->pvar->var,
+					      pf->pvar->field, &pf->tvar->ref,
+					      &die_mem);
+		vr_die = &die_mem;
+	}
+	if (ret == 0) {
+		if (pf->pvar->type) {
+			pf->tvar->type = strdup(pf->pvar->type);
+			if (pf->tvar->type == NULL)
+				ret = -ENOMEM;
+		} else
+			ret = convert_variable_type(vr_die, pf->tvar);
+	}
 	/* *expr will be cached in libdw. Don't free it. */
-	return ;
+	return ret;
 error:
 	/* TODO: Support const_value */
-	die("Failed to find the location of %s at this address.\n"
-	    " Perhaps, it has been optimized out.", pf->pvar->name);
+	pr_err("Failed to find the location of %s at this address.\n"
+	       " Perhaps, it has been optimized out.\n", pf->pvar->var);
+	return -ENOENT;
 }
 
 /* Find a variable in a subprogram die */
-static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
+static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
 {
 	Dwarf_Die vr_die;
-	char buf[128];
+	char buf[32], *ptr;
+	int ret;
 
-	/* TODO: Support struct members and arrays */
-	if (!is_c_varname(pf->pvar->name)) {
-		/* Copy raw parameters */
-		pf->tvar->value = xstrdup(pf->pvar->name);
-	} else {
-		synthesize_perf_probe_arg(pf->pvar, buf, 128);
-		pf->tvar->name = xstrdup(buf);
-		pr_debug("Searching '%s' variable in context.\n",
-			 pf->pvar->name);
-		/* Search child die for local variables and parameters. */
-		if (!die_find_variable(sp_die, pf->pvar->name, &vr_die))
-			die("Failed to find '%s' in this function.",
-			    pf->pvar->name);
-		convert_variable(&vr_die, pf);
+	/* TODO: Support arrays */
+	if (pf->pvar->name)
+		pf->tvar->name = strdup(pf->pvar->name);
+	else {
+		ret = synthesize_perf_probe_arg(pf->pvar, buf, 32);
+		if (ret < 0)
+			return ret;
+		ptr = strchr(buf, ':');	/* Change type separator to _ */
+		if (ptr)
+			*ptr = '_';
+		pf->tvar->name = strdup(buf);
 	}
+	if (pf->tvar->name == NULL)
+		return -ENOMEM;
+
+	if (!is_c_varname(pf->pvar->var)) {
+		/* Copy raw parameters */
+		pf->tvar->value = strdup(pf->pvar->var);
+		if (pf->tvar->value == NULL)
+			return -ENOMEM;
+		else
+			return 0;
+	}
+
+	pr_debug("Searching '%s' variable in context.\n",
+		 pf->pvar->var);
+	/* Search child die for local variables and parameters. */
+	if (!die_find_variable(sp_die, pf->pvar->var, &vr_die)) {
+		pr_warning("Failed to find '%s' in this function.\n",
+			   pf->pvar->var);
+		return -ENOENT;
+	}
+	return convert_variable(&vr_die, pf);
 }
 
 /* Show a probe point to output buffer */
-static void convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
+static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
 {
 	struct kprobe_trace_event *tev;
 	Dwarf_Addr eaddr;
@@ -528,23 +677,34 @@
 	Dwarf_Attribute fb_attr;
 	size_t nops;
 
-	if (pf->ntevs == MAX_PROBES)
-		die("Too many( > %d) probe point found.\n", MAX_PROBES);
+	if (pf->ntevs == MAX_PROBES) {
+		pr_warning("Too many( > %d) probe point found.\n", MAX_PROBES);
+		return -ERANGE;
+	}
 	tev = &pf->tevs[pf->ntevs++];
 
 	/* If no real subprogram, find a real one */
 	if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) {
 		sp_die = die_find_real_subprogram(&pf->cu_die,
 						 pf->addr, &die_mem);
-		if (!sp_die)
-			die("Probe point is not found in subprograms.");
+		if (!sp_die) {
+			pr_warning("Failed to find probe point in any "
+				   "functions.\n");
+			return -ENOENT;
+		}
 	}
 
 	/* Copy the name of probe point */
 	name = dwarf_diename(sp_die);
 	if (name) {
-		dwarf_entrypc(sp_die, &eaddr);
-		tev->point.symbol = xstrdup(name);
+		if (dwarf_entrypc(sp_die, &eaddr) != 0) {
+			pr_warning("Failed to get entry pc of %s\n",
+				   dwarf_diename(sp_die));
+			return -ENOENT;
+		}
+		tev->point.symbol = strdup(name);
+		if (tev->point.symbol == NULL)
+			return -ENOMEM;
 		tev->point.offset = (unsigned long)(pf->addr - eaddr);
 	} else
 		/* This function has no name. */
@@ -556,55 +716,74 @@
 	/* Get the frame base attribute/ops */
 	dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr);
 	ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
-	if (ret <= 0 || nops == 0)
+	if (ret <= 0 || nops == 0) {
 		pf->fb_ops = NULL;
+	} else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
+		   pf->cfi != NULL) {
+		Dwarf_Frame *frame;
+		if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
+		    dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
+			pr_warning("Failed to get CFA on 0x%jx\n",
+				   (uintmax_t)pf->addr);
+			return -ENOENT;
+		}
+	}
 
 	/* Find each argument */
-	/* TODO: use dwarf_cfi_addrframe */
 	tev->nargs = pf->pev->nargs;
-	tev->args = xzalloc(sizeof(struct kprobe_trace_arg) * tev->nargs);
+	tev->args = zalloc(sizeof(struct kprobe_trace_arg) * tev->nargs);
+	if (tev->args == NULL)
+		return -ENOMEM;
 	for (i = 0; i < pf->pev->nargs; i++) {
 		pf->pvar = &pf->pev->args[i];
 		pf->tvar = &tev->args[i];
-		find_variable(sp_die, pf);
+		ret = find_variable(sp_die, pf);
+		if (ret != 0)
+			return ret;
 	}
 
 	/* *pf->fb_ops will be cached in libdw. Don't free it. */
 	pf->fb_ops = NULL;
+	return 0;
 }
 
 /* Find probe point from its line number */
-static void find_probe_point_by_line(struct probe_finder *pf)
+static int find_probe_point_by_line(struct probe_finder *pf)
 {
 	Dwarf_Lines *lines;
 	Dwarf_Line *line;
 	size_t nlines, i;
 	Dwarf_Addr addr;
 	int lineno;
-	int ret;
+	int ret = 0;
 
-	ret = dwarf_getsrclines(&pf->cu_die, &lines, &nlines);
-	DIE_IF(ret != 0);
+	if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
+		pr_warning("No source lines found in this CU.\n");
+		return -ENOENT;
+	}
 
-	for (i = 0; i < nlines; i++) {
+	for (i = 0; i < nlines && ret == 0; i++) {
 		line = dwarf_onesrcline(lines, i);
-		dwarf_lineno(line, &lineno);
-		if (lineno != pf->lno)
+		if (dwarf_lineno(line, &lineno) != 0 ||
+		    lineno != pf->lno)
 			continue;
 
 		/* TODO: Get fileno from line, but how? */
 		if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
 			continue;
 
-		ret = dwarf_lineaddr(line, &addr);
-		DIE_IF(ret != 0);
+		if (dwarf_lineaddr(line, &addr) != 0) {
+			pr_warning("Failed to get the address of the line.\n");
+			return -ENOENT;
+		}
 		pr_debug("Probe line found: line[%d]:%d addr:0x%jx\n",
 			 (int)i, lineno, (uintmax_t)addr);
 		pf->addr = addr;
 
-		convert_probe_point(NULL, pf);
+		ret = convert_probe_point(NULL, pf);
 		/* Continuing, because target line might be inlined. */
 	}
+	return ret;
 }
 
 /* Find lines which match lazy pattern */
@@ -612,15 +791,27 @@
 				 const char *fname, const char *pat)
 {
 	char *fbuf, *p1, *p2;
-	int fd, line, nlines = 0;
+	int fd, ret, line, nlines = 0;
 	struct stat st;
 
 	fd = open(fname, O_RDONLY);
-	if (fd < 0)
-		die("failed to open %s", fname);
-	DIE_IF(fstat(fd, &st) < 0);
+	if (fd < 0) {
+		pr_warning("Failed to open %s: %s\n", fname, strerror(-fd));
+		return fd;
+	}
+
+	ret = fstat(fd, &st);
+	if (ret < 0) {
+		pr_warning("Failed to get the size of %s: %s\n",
+			   fname, strerror(errno));
+		return ret;
+	}
 	fbuf = xmalloc(st.st_size + 2);
-	DIE_IF(read(fd, fbuf, st.st_size) < 0);
+	ret = read(fd, fbuf, st.st_size);
+	if (ret < 0) {
+		pr_warning("Failed to read %s: %s\n", fname, strerror(errno));
+		return ret;
+	}
 	close(fd);
 	fbuf[st.st_size] = '\n';	/* Dummy line */
 	fbuf[st.st_size + 1] = '\0';
@@ -640,7 +831,7 @@
 }
 
 /* Find probe points from lazy pattern  */
-static void find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
+static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
 {
 	Dwarf_Lines *lines;
 	Dwarf_Line *line;
@@ -648,31 +839,40 @@
 	Dwarf_Addr addr;
 	Dwarf_Die die_mem;
 	int lineno;
-	int ret;
+	int ret = 0;
 
 	if (list_empty(&pf->lcache)) {
 		/* Matching lazy line pattern */
 		ret = find_lazy_match_lines(&pf->lcache, pf->fname,
 					    pf->pev->point.lazy_line);
-		if (ret <= 0)
-			die("No matched lines found in %s.", pf->fname);
+		if (ret == 0) {
+			pr_debug("No matched lines found in %s.\n", pf->fname);
+			return 0;
+		} else if (ret < 0)
+			return ret;
 	}
 
-	ret = dwarf_getsrclines(&pf->cu_die, &lines, &nlines);
-	DIE_IF(ret != 0);
-	for (i = 0; i < nlines; i++) {
+	if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
+		pr_warning("No source lines found in this CU.\n");
+		return -ENOENT;
+	}
+
+	for (i = 0; i < nlines && ret >= 0; i++) {
 		line = dwarf_onesrcline(lines, i);
 
-		dwarf_lineno(line, &lineno);
-		if (!line_list__has_line(&pf->lcache, lineno))
+		if (dwarf_lineno(line, &lineno) != 0 ||
+		    !line_list__has_line(&pf->lcache, lineno))
 			continue;
 
 		/* TODO: Get fileno from line, but how? */
 		if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
 			continue;
 
-		ret = dwarf_lineaddr(line, &addr);
-		DIE_IF(ret != 0);
+		if (dwarf_lineaddr(line, &addr) != 0) {
+			pr_debug("Failed to get the address of line %d.\n",
+				 lineno);
+			continue;
+		}
 		if (sp_die) {
 			/* Address filtering 1: does sp_die include addr? */
 			if (!dwarf_haspc(sp_die, addr))
@@ -686,27 +886,42 @@
 			 (int)i, lineno, (unsigned long long)addr);
 		pf->addr = addr;
 
-		convert_probe_point(sp_die, pf);
+		ret = convert_probe_point(sp_die, pf);
 		/* Continuing, because target line might be inlined. */
 	}
 	/* TODO: deallocate lines, but how? */
+	return ret;
 }
 
+/* Callback parameter with return value */
+struct dwarf_callback_param {
+	void *data;
+	int retval;
+};
+
 static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
 {
-	struct probe_finder *pf = (struct probe_finder *)data;
+	struct dwarf_callback_param *param = data;
+	struct probe_finder *pf = param->data;
 	struct perf_probe_point *pp = &pf->pev->point;
+	Dwarf_Addr addr;
 
 	if (pp->lazy_line)
-		find_probe_point_lazy(in_die, pf);
+		param->retval = find_probe_point_lazy(in_die, pf);
 	else {
 		/* Get probe address */
-		pf->addr = die_get_entrypc(in_die);
+		if (dwarf_entrypc(in_die, &addr) != 0) {
+			pr_warning("Failed to get entry pc of %s.\n",
+				   dwarf_diename(in_die));
+			param->retval = -ENOENT;
+			return DWARF_CB_ABORT;
+		}
+		pf->addr = addr;
 		pf->addr += pp->offset;
 		pr_debug("found inline addr: 0x%jx\n",
 			 (uintmax_t)pf->addr);
 
-		convert_probe_point(in_die, pf);
+		param->retval = convert_probe_point(in_die, pf);
 	}
 
 	return DWARF_CB_OK;
@@ -715,39 +930,53 @@
 /* Search function from function name */
 static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
 {
-	struct probe_finder *pf = (struct probe_finder *)data;
+	struct dwarf_callback_param *param = data;
+	struct probe_finder *pf = param->data;
 	struct perf_probe_point *pp = &pf->pev->point;
 
 	/* Check tag and diename */
 	if (dwarf_tag(sp_die) != DW_TAG_subprogram ||
 	    die_compare_name(sp_die, pp->function) != 0)
-		return 0;
+		return DWARF_CB_OK;
 
 	pf->fname = dwarf_decl_file(sp_die);
 	if (pp->line) { /* Function relative line */
 		dwarf_decl_line(sp_die, &pf->lno);
 		pf->lno += pp->line;
-		find_probe_point_by_line(pf);
+		param->retval = find_probe_point_by_line(pf);
 	} else if (!dwarf_func_inline(sp_die)) {
 		/* Real function */
 		if (pp->lazy_line)
-			find_probe_point_lazy(sp_die, pf);
+			param->retval = find_probe_point_lazy(sp_die, pf);
 		else {
-			pf->addr = die_get_entrypc(sp_die);
+			if (dwarf_entrypc(sp_die, &pf->addr) != 0) {
+				pr_warning("Failed to get entry pc of %s.\n",
+					   dwarf_diename(sp_die));
+				param->retval = -ENOENT;
+				return DWARF_CB_ABORT;
+			}
 			pf->addr += pp->offset;
 			/* TODO: Check the address in this function */
-			convert_probe_point(sp_die, pf);
+			param->retval = convert_probe_point(sp_die, pf);
 		}
-	} else
+	} else {
+		struct dwarf_callback_param _param = {.data = (void *)pf,
+						      .retval = 0};
 		/* Inlined function: search instances */
-		dwarf_func_inline_instances(sp_die, probe_point_inline_cb, pf);
+		dwarf_func_inline_instances(sp_die, probe_point_inline_cb,
+					    &_param);
+		param->retval = _param.retval;
+	}
 
-	return 1; /* Exit; no same symbol in this CU. */
+	return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */
 }
 
-static void find_probe_point_by_func(struct probe_finder *pf)
+static int find_probe_point_by_func(struct probe_finder *pf)
 {
-	dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, pf, 0);
+	struct dwarf_callback_param _param = {.data = (void *)pf,
+					      .retval = 0};
+	dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0);
+	return _param.retval;
 }
 
 /* Find kprobe_trace_events specified by perf_probe_event from debuginfo */
@@ -760,19 +989,29 @@
 	size_t cuhl;
 	Dwarf_Die *diep;
 	Dwarf *dbg;
+	int ret = 0;
 
-	pf.tevs = xzalloc(sizeof(struct kprobe_trace_event) * MAX_PROBES);
+	pf.tevs = zalloc(sizeof(struct kprobe_trace_event) * MAX_PROBES);
+	if (pf.tevs == NULL)
+		return -ENOMEM;
 	*tevs = pf.tevs;
 	pf.ntevs = 0;
 
 	dbg = dwarf_begin(fd, DWARF_C_READ);
-	if (!dbg)
-		return -ENOENT;
+	if (!dbg) {
+		pr_warning("No dwarf info found in the vmlinux - "
+			"please rebuild with CONFIG_DEBUG_INFO=y.\n");
+		return -EBADF;
+	}
+
+	/* Get the call frame information from this dwarf */
+	pf.cfi = dwarf_getcfi(dbg);
 
 	off = 0;
 	line_list__init(&pf.lcache);
 	/* Loop on CUs (Compilation Unit) */
-	while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
+	while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) &&
+	       ret >= 0) {
 		/* Get the DIE(Debugging Information Entry) of this CU */
 		diep = dwarf_offdie(dbg, off + cuhl, &pf.cu_die);
 		if (!diep)
@@ -786,12 +1025,12 @@
 
 		if (!pp->file || pf.fname) {
 			if (pp->function)
-				find_probe_point_by_func(&pf);
+				ret = find_probe_point_by_func(&pf);
 			else if (pp->lazy_line)
-				find_probe_point_lazy(NULL, &pf);
+				ret = find_probe_point_lazy(NULL, &pf);
 			else {
 				pf.lno = pp->line;
-				find_probe_point_by_line(&pf);
+				ret = find_probe_point_by_line(&pf);
 			}
 		}
 		off = noff;
@@ -799,7 +1038,7 @@
 	line_list__free(&pf.lcache);
 	dwarf_end(dbg);
 
-	return pf.ntevs;
+	return (ret < 0) ? ret : pf.ntevs;
 }
 
 /* Reverse search */
@@ -812,10 +1051,11 @@
 	Dwarf_Addr laddr, eaddr;
 	const char *tmp;
 	int lineno, ret = 0;
+	bool found = false;
 
 	dbg = dwarf_begin(fd, DWARF_C_READ);
 	if (!dbg)
-		return -ENOENT;
+		return -EBADF;
 
 	/* Find cu die */
 	if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr, &cudie)) {
@@ -826,82 +1066,135 @@
 	/* Find a corresponding line */
 	line = dwarf_getsrc_die(&cudie, (Dwarf_Addr)addr);
 	if (line) {
-		dwarf_lineaddr(line, &laddr);
-		if ((Dwarf_Addr)addr == laddr) {
-			dwarf_lineno(line, &lineno);
-			ppt->line = lineno;
-
+		if (dwarf_lineaddr(line, &laddr) == 0 &&
+		    (Dwarf_Addr)addr == laddr &&
+		    dwarf_lineno(line, &lineno) == 0) {
 			tmp = dwarf_linesrc(line, NULL, NULL);
-			DIE_IF(!tmp);
-			ppt->file = xstrdup(tmp);
-			ret = 1;
+			if (tmp) {
+				ppt->line = lineno;
+				ppt->file = strdup(tmp);
+				if (ppt->file == NULL) {
+					ret = -ENOMEM;
+					goto end;
+				}
+				found = true;
+			}
 		}
 	}
 
 	/* Find a corresponding function */
 	if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) {
 		tmp = dwarf_diename(&spdie);
-		if (!tmp)
+		if (!tmp || dwarf_entrypc(&spdie, &eaddr) != 0)
 			goto end;
 
-		dwarf_entrypc(&spdie, &eaddr);
-		if (!lineno) {
-			/* We don't have a line number, let's use offset */
-			ppt->function = xstrdup(tmp);
-			ppt->offset = addr - (unsigned long)eaddr;
-			ret = 1;
+		if (ppt->line) {
+			if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr,
+						&indie)) {
+				/* addr in an inline function */
+				tmp = dwarf_diename(&indie);
+				if (!tmp)
+					goto end;
+				ret = dwarf_decl_line(&indie, &lineno);
+			} else {
+				if (eaddr == addr) {	/* Function entry */
+					lineno = ppt->line;
+					ret = 0;
+				} else
+					ret = dwarf_decl_line(&spdie, &lineno);
+			}
+			if (ret == 0) {
+				/* Make a relative line number */
+				ppt->line -= lineno;
+				goto found;
+			}
+		}
+		/* We don't have a line number, let's use offset */
+		ppt->offset = addr - (unsigned long)eaddr;
+found:
+		ppt->function = strdup(tmp);
+		if (ppt->function == NULL) {
+			ret = -ENOMEM;
 			goto end;
 		}
-		if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr, &indie)) {
-			/* addr in an inline function */
-			tmp = dwarf_diename(&indie);
-			if (!tmp)
-				goto end;
-			dwarf_decl_line(&indie, &lineno);
-		} else {
-			if (eaddr == addr)	/* No offset: function entry */
-				lineno = ppt->line;
-			else
-				dwarf_decl_line(&spdie, &lineno);
-		}
-		ppt->function = xstrdup(tmp);
-		ppt->line -= lineno;	/* Make a relative line number */
+		found = true;
 	}
 
 end:
 	dwarf_end(dbg);
+	if (ret >= 0)
+		ret = found ? 1 : 0;
 	return ret;
 }
 
+/* Add a line and store the src path */
+static int line_range_add_line(const char *src, unsigned int lineno,
+			       struct line_range *lr)
+{
+	/* Copy real path */
+	if (!lr->path) {
+		lr->path = strdup(src);
+		if (lr->path == NULL)
+			return -ENOMEM;
+	}
+	return line_list__add_line(&lr->line_list, lineno);
+}
+
+/* Search function declaration lines */
+static int line_range_funcdecl_cb(Dwarf_Die *sp_die, void *data)
+{
+	struct dwarf_callback_param *param = data;
+	struct line_finder *lf = param->data;
+	const char *src;
+	int lineno;
+
+	src = dwarf_decl_file(sp_die);
+	if (src && strtailcmp(src, lf->fname) != 0)
+		return DWARF_CB_OK;
+
+	if (dwarf_decl_line(sp_die, &lineno) != 0 ||
+	    (lf->lno_s > lineno || lf->lno_e < lineno))
+		return DWARF_CB_OK;
+
+	param->retval = line_range_add_line(src, lineno, lf->lr);
+	return DWARF_CB_OK;
+}
+
+static int find_line_range_func_decl_lines(struct line_finder *lf)
+{
+	struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
+	dwarf_getfuncs(&lf->cu_die, line_range_funcdecl_cb, &param, 0);
+	return param.retval;
+}
 
 /* Find line range from its line number */
-static void find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
+static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
 {
 	Dwarf_Lines *lines;
 	Dwarf_Line *line;
 	size_t nlines, i;
 	Dwarf_Addr addr;
-	int lineno;
-	int ret;
+	int lineno, ret = 0;
 	const char *src;
 	Dwarf_Die die_mem;
 
 	line_list__init(&lf->lr->line_list);
-	ret = dwarf_getsrclines(&lf->cu_die, &lines, &nlines);
-	DIE_IF(ret != 0);
+	if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) {
+		pr_warning("No source lines found in this CU.\n");
+		return -ENOENT;
+	}
 
+	/* Search probable lines on lines list */
 	for (i = 0; i < nlines; i++) {
 		line = dwarf_onesrcline(lines, i);
-		ret = dwarf_lineno(line, &lineno);
-		DIE_IF(ret != 0);
-		if (lf->lno_s > lineno || lf->lno_e < lineno)
+		if (dwarf_lineno(line, &lineno) != 0 ||
+		    (lf->lno_s > lineno || lf->lno_e < lineno))
 			continue;
 
 		if (sp_die) {
 			/* Address filtering 1: does sp_die include addr? */
-			ret = dwarf_lineaddr(line, &addr);
-			DIE_IF(ret != 0);
-			if (!dwarf_haspc(sp_die, addr))
+			if (dwarf_lineaddr(line, &addr) != 0 ||
+			    !dwarf_haspc(sp_die, addr))
 				continue;
 
 			/* Address filtering 2: No child include addr? */
@@ -914,30 +1207,49 @@
 		if (strtailcmp(src, lf->fname) != 0)
 			continue;
 
-		/* Copy real path */
-		if (!lf->lr->path)
-			lf->lr->path = xstrdup(src);
-		line_list__add_line(&lf->lr->line_list, (unsigned int)lineno);
+		ret = line_range_add_line(src, lineno, lf->lr);
+		if (ret < 0)
+			return ret;
 	}
+
+	/*
+	 * Dwarf lines doesn't include function declarations. We have to
+	 * check functions list or given function.
+	 */
+	if (sp_die) {
+		src = dwarf_decl_file(sp_die);
+		if (src && dwarf_decl_line(sp_die, &lineno) == 0 &&
+		    (lf->lno_s <= lineno && lf->lno_e >= lineno))
+			ret = line_range_add_line(src, lineno, lf->lr);
+	} else
+		ret = find_line_range_func_decl_lines(lf);
+
 	/* Update status */
-	if (!list_empty(&lf->lr->line_list))
-		lf->found = 1;
+	if (ret >= 0)
+		if (!list_empty(&lf->lr->line_list))
+			ret = lf->found = 1;
+		else
+			ret = 0;	/* Lines are not found */
 	else {
 		free(lf->lr->path);
 		lf->lr->path = NULL;
 	}
+	return ret;
 }
 
 static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
 {
-	find_line_range_by_line(in_die, (struct line_finder *)data);
+	struct dwarf_callback_param *param = data;
+
+	param->retval = find_line_range_by_line(in_die, param->data);
 	return DWARF_CB_ABORT;	/* No need to find other instances */
 }
 
 /* Search function from function name */
 static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
 {
-	struct line_finder *lf = (struct line_finder *)data;
+	struct dwarf_callback_param *param = data;
+	struct line_finder *lf = param->data;
 	struct line_range *lr = lf->lr;
 
 	if (dwarf_tag(sp_die) == DW_TAG_subprogram &&
@@ -946,44 +1258,55 @@
 		dwarf_decl_line(sp_die, &lr->offset);
 		pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
 		lf->lno_s = lr->offset + lr->start;
-		if (!lr->end)
+		if (lf->lno_s < 0)	/* Overflow */
+			lf->lno_s = INT_MAX;
+		lf->lno_e = lr->offset + lr->end;
+		if (lf->lno_e < 0)	/* Overflow */
 			lf->lno_e = INT_MAX;
-		else
-			lf->lno_e = lr->offset + lr->end;
+		pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e);
 		lr->start = lf->lno_s;
 		lr->end = lf->lno_e;
-		if (dwarf_func_inline(sp_die))
+		if (dwarf_func_inline(sp_die)) {
+			struct dwarf_callback_param _param;
+			_param.data = (void *)lf;
+			_param.retval = 0;
 			dwarf_func_inline_instances(sp_die,
-						    line_range_inline_cb, lf);
-		else
-			find_line_range_by_line(sp_die, lf);
-		return 1;
+						    line_range_inline_cb,
+						    &_param);
+			param->retval = _param.retval;
+		} else
+			param->retval = find_line_range_by_line(sp_die, lf);
+		return DWARF_CB_ABORT;
 	}
-	return 0;
+	return DWARF_CB_OK;
 }
 
-static void find_line_range_by_func(struct line_finder *lf)
+static int find_line_range_by_func(struct line_finder *lf)
 {
-	dwarf_getfuncs(&lf->cu_die, line_range_search_cb, lf, 0);
+	struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
+	dwarf_getfuncs(&lf->cu_die, line_range_search_cb, &param, 0);
+	return param.retval;
 }
 
 int find_line_range(int fd, struct line_range *lr)
 {
 	struct line_finder lf = {.lr = lr, .found = 0};
-	int ret;
+	int ret = 0;
 	Dwarf_Off off = 0, noff;
 	size_t cuhl;
 	Dwarf_Die *diep;
 	Dwarf *dbg;
 
 	dbg = dwarf_begin(fd, DWARF_C_READ);
-	if (!dbg)
-		return -ENOENT;
+	if (!dbg) {
+		pr_warning("No dwarf info found in the vmlinux - "
+			"please rebuild with CONFIG_DEBUG_INFO=y.\n");
+		return -EBADF;
+	}
 
 	/* Loop on CUs (Compilation Unit) */
-	while (!lf.found) {
-		ret = dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL);
-		if (ret != 0)
+	while (!lf.found && ret >= 0) {
+		if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0)
 			break;
 
 		/* Get the DIE(Debugging Information Entry) of this CU */
@@ -999,20 +1322,18 @@
 
 		if (!lr->file || lf.fname) {
 			if (lr->function)
-				find_line_range_by_func(&lf);
+				ret = find_line_range_by_func(&lf);
 			else {
 				lf.lno_s = lr->start;
-				if (!lr->end)
-					lf.lno_e = INT_MAX;
-				else
-					lf.lno_e = lr->end;
-				find_line_range_by_line(NULL, &lf);
+				lf.lno_e = lr->end;
+				ret = find_line_range_by_line(NULL, &lf);
 			}
 		}
 		off = noff;
 	}
 	pr_debug("path: %lx\n", (unsigned long)lr->path);
 	dwarf_end(dbg);
-	return lf.found;
+
+	return (ret < 0) ? ret : lf.found;
 }
 
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 2a27132..310ce89 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -42,6 +42,7 @@
 	struct list_head	lcache;		/* Line cache for lazy match */
 
 	/* For variable searching */
+	Dwarf_CFI		*cfi;		/* Call Frame Information */
 	Dwarf_Op		*fb_ops;	/* Frame base attribute */
 	struct perf_probe_arg	*pvar;		/* Current target variable */
 	struct kprobe_trace_arg	*tvar;		/* Current result variable */
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 9d24d4b..da30b30 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -30,38 +30,38 @@
 				       size_t size, unsigned int width);
 
 struct sort_entry sort_thread = {
-	.header = "Command:  Pid",
-	.cmp	= sort__thread_cmp,
-	.snprintf = hist_entry__thread_snprintf,
-	.width	= &threads__col_width,
+	.se_header	= "Command:  Pid",
+	.se_cmp		= sort__thread_cmp,
+	.se_snprintf	= hist_entry__thread_snprintf,
+	.se_width	= &threads__col_width,
 };
 
 struct sort_entry sort_comm = {
-	.header		= "Command",
-	.cmp		= sort__comm_cmp,
-	.collapse	= sort__comm_collapse,
-	.snprintf	= hist_entry__comm_snprintf,
-	.width		= &comms__col_width,
+	.se_header	= "Command",
+	.se_cmp		= sort__comm_cmp,
+	.se_collapse	= sort__comm_collapse,
+	.se_snprintf	= hist_entry__comm_snprintf,
+	.se_width	= &comms__col_width,
 };
 
 struct sort_entry sort_dso = {
-	.header = "Shared Object",
-	.cmp	= sort__dso_cmp,
-	.snprintf = hist_entry__dso_snprintf,
-	.width	= &dsos__col_width,
+	.se_header	= "Shared Object",
+	.se_cmp		= sort__dso_cmp,
+	.se_snprintf	= hist_entry__dso_snprintf,
+	.se_width	= &dsos__col_width,
 };
 
 struct sort_entry sort_sym = {
-	.header = "Symbol",
-	.cmp	= sort__sym_cmp,
-	.snprintf = hist_entry__sym_snprintf,
+	.se_header	= "Symbol",
+	.se_cmp		= sort__sym_cmp,
+	.se_snprintf	= hist_entry__sym_snprintf,
 };
 
 struct sort_entry sort_parent = {
-	.header = "Parent symbol",
-	.cmp	= sort__parent_cmp,
-	.snprintf = hist_entry__parent_snprintf,
-	.width	= &parent_symbol__col_width,
+	.se_header	= "Parent symbol",
+	.se_cmp		= sort__parent_cmp,
+	.se_snprintf	= hist_entry__parent_snprintf,
+	.se_width	= &parent_symbol__col_width,
 };
 
 struct sort_dimension {
@@ -255,7 +255,7 @@
 		if (strncasecmp(tok, sd->name, strlen(tok)))
 			continue;
 
-		if (sd->entry->collapse)
+		if (sd->entry->se_collapse)
 			sort__need_collapse = 1;
 
 		if (sd->entry == &sort_parent) {
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 6d7b4be..1d857aa 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -78,13 +78,13 @@
 struct sort_entry {
 	struct list_head list;
 
-	const char *header;
+	const char *se_header;
 
-	int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
-	int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
-	int	(*snprintf)(struct hist_entry *self, char *bf, size_t size,
-			    unsigned int width);
-	unsigned int *width;
+	int64_t (*se_cmp)(struct hist_entry *, struct hist_entry *);
+	int64_t (*se_collapse)(struct hist_entry *, struct hist_entry *);
+	int	(*se_snprintf)(struct hist_entry *self, char *bf, size_t size,
+			       unsigned int width);
+	unsigned int *se_width;
 	bool	elide;
 };