diff options
Diffstat (limited to 'kernel/trace/trace_kprobe.c')
| -rw-r--r-- | kernel/trace/trace_kprobe.c | 35 | 
1 files changed, 26 insertions, 9 deletions
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 1b3fa7b854aa..23dba01831f7 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -732,9 +732,10 @@ static int __trace_kprobe_create(int argc, const char *argv[])  	 *  FETCHARG:TYPE : use TYPE instead of unsigned long.  	 */  	struct trace_kprobe *tk = NULL; -	int i, len, ret = 0; +	int i, len, new_argc = 0, ret = 0;  	bool is_return = false;  	char *symbol = NULL, *tmp = NULL; +	const char **new_argv = NULL;  	const char *event = NULL, *group = KPROBE_EVENT_SYSTEM;  	enum probe_print_type ptype;  	int maxactive = 0; @@ -742,7 +743,8 @@ static int __trace_kprobe_create(int argc, const char *argv[])  	void *addr = NULL;  	char buf[MAX_EVENT_NAME_LEN];  	char gbuf[MAX_EVENT_NAME_LEN]; -	unsigned int flags = TPARG_FL_KERNEL; +	char abuf[MAX_BTF_ARGS_LEN]; +	struct traceprobe_parse_context ctx = { .flags = TPARG_FL_KERNEL };  	switch (argv[0][0]) {  	case 'r': @@ -764,7 +766,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])  	if (isdigit(argv[0][1])) {  		if (!is_return) { -			trace_probe_log_err(1, MAXACT_NO_KPROBE); +			trace_probe_log_err(1, BAD_MAXACT_TYPE);  			goto parse_error;  		}  		if (event) @@ -823,10 +825,10 @@ static int __trace_kprobe_create(int argc, const char *argv[])  			goto parse_error;  		}  		if (is_return) -			flags |= TPARG_FL_RETURN; +			ctx.flags |= TPARG_FL_RETURN;  		ret = kprobe_on_func_entry(NULL, symbol, offset); -		if (ret == 0) -			flags |= TPARG_FL_FENTRY; +		if (ret == 0 && !is_return) +			ctx.flags |= TPARG_FL_FENTRY;  		/* Defer the ENOENT case until register kprobe */  		if (ret == -EINVAL && is_return) {  			trace_probe_log_err(0, BAD_RETPROBE); @@ -854,21 +856,35 @@ static int __trace_kprobe_create(int argc, const char *argv[])  		event = buf;  	} +	argc -= 2; argv += 2; +	ctx.funcname = symbol; +	new_argv = traceprobe_expand_meta_args(argc, argv, &new_argc, +					       abuf, MAX_BTF_ARGS_LEN, &ctx); +	if (IS_ERR(new_argv)) { +		ret = PTR_ERR(new_argv); +		new_argv = NULL; +		goto out; +	} +	if (new_argv) { +		argc = new_argc; +		argv = new_argv; +	} +  	/* setup a probe */  	tk = alloc_trace_kprobe(group, event, addr, symbol, offset, maxactive, -			       argc - 2, is_return); +				argc, is_return);  	if (IS_ERR(tk)) {  		ret = PTR_ERR(tk);  		/* This must return -ENOMEM, else there is a bug */  		WARN_ON_ONCE(ret != -ENOMEM);  		goto out;	/* We know tk is not allocated */  	} -	argc -= 2; argv += 2;  	/* parse arguments */  	for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {  		trace_probe_log_set_index(i + 2); -		ret = traceprobe_parse_probe_arg(&tk->tp, i, argv[i], flags); +		ctx.offset = 0; +		ret = traceprobe_parse_probe_arg(&tk->tp, i, argv[i], &ctx);  		if (ret)  			goto error;	/* This can be -ENOMEM */  	} @@ -892,6 +908,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])  out:  	trace_probe_log_clear(); +	kfree(new_argv);  	kfree(symbol);  	return ret;  |