aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_probe.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trace/trace_probe.c')
-rw-r--r--kernel/trace/trace_probe.c36
1 files changed, 23 insertions, 13 deletions
diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c
index dfd096031305..333cda6d2633 100644
--- a/kernel/trace/trace_probe.c
+++ b/kernel/trace/trace_probe.c
@@ -157,14 +157,13 @@ int traceprobe_split_symbol_offset(char *symbol, long *offset)
#define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long))
static int parse_probe_vars(char *arg, const struct fetch_type *t,
- struct fetch_insn *code, bool is_return,
- bool is_kprobe)
+ struct fetch_insn *code, unsigned int flags)
{
int ret = 0;
unsigned long param;
if (strcmp(arg, "retval") == 0) {
- if (is_return)
+ if (flags & TPARG_FL_RETURN)
code->op = FETCH_OP_RETVAL;
else
ret = -EINVAL;
@@ -173,7 +172,8 @@ static int parse_probe_vars(char *arg, const struct fetch_type *t,
code->op = FETCH_OP_STACKP;
} else if (isdigit(arg[5])) {
ret = kstrtoul(arg + 5, 10, &param);
- if (ret || (is_kprobe && param > PARAM_MAX_STACK))
+ if (ret || ((flags & TPARG_FL_KERNEL) &&
+ param > PARAM_MAX_STACK))
ret = -EINVAL;
else {
code->op = FETCH_OP_STACK;
@@ -183,6 +183,18 @@ static int parse_probe_vars(char *arg, const struct fetch_type *t,
ret = -EINVAL;
} else if (strcmp(arg, "comm") == 0) {
code->op = FETCH_OP_COMM;
+#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
+ } else if (((flags & TPARG_FL_MASK) ==
+ (TPARG_FL_KERNEL | TPARG_FL_FENTRY)) &&
+ strncmp(arg, "arg", 3) == 0) {
+ if (!isdigit(arg[3]))
+ return -EINVAL;
+ ret = kstrtoul(arg + 3, 10, &param);
+ if (ret || !param || param > PARAM_MAX_STACK)
+ return -EINVAL;
+ code->op = FETCH_OP_ARG;
+ code->param = (unsigned int)param - 1;
+#endif
} else
ret = -EINVAL;
@@ -193,7 +205,7 @@ static int parse_probe_vars(char *arg, const struct fetch_type *t,
static int
parse_probe_arg(char *arg, const struct fetch_type *type,
struct fetch_insn **pcode, struct fetch_insn *end,
- bool is_return, bool is_kprobe)
+ unsigned int flags)
{
struct fetch_insn *code = *pcode;
unsigned long param;
@@ -203,8 +215,7 @@ parse_probe_arg(char *arg, const struct fetch_type *type,
switch (arg[0]) {
case '$':
- ret = parse_probe_vars(arg + 1, type, code,
- is_return, is_kprobe);
+ ret = parse_probe_vars(arg + 1, type, code, flags);
break;
case '%': /* named register */
@@ -226,7 +237,7 @@ parse_probe_arg(char *arg, const struct fetch_type *type,
code->immediate = param;
} else if (arg[1] == '+') {
/* kprobes don't support file offsets */
- if (is_kprobe)
+ if (flags & TPARG_FL_KERNEL)
return -EINVAL;
ret = kstrtol(arg + 2, 0, &offset);
@@ -237,7 +248,7 @@ parse_probe_arg(char *arg, const struct fetch_type *type,
code->immediate = (unsigned long)offset; // imm64?
} else {
/* uprobes don't support symbols */
- if (!is_kprobe)
+ if (!(flags & TPARG_FL_KERNEL))
return -EINVAL;
ret = traceprobe_split_symbol_offset(arg + 1, &offset);
@@ -278,8 +289,7 @@ parse_probe_arg(char *arg, const struct fetch_type *type,
const struct fetch_type *t2 = find_fetch_type(NULL);
*tmp = '\0';
- ret = parse_probe_arg(arg, t2, &code, end, is_return,
- is_kprobe);
+ ret = parse_probe_arg(arg, t2, &code, end, flags);
if (ret)
break;
if (code->op == FETCH_OP_COMM)
@@ -339,7 +349,7 @@ static int __parse_bitfield_probe_arg(const char *bf,
/* String length checking wrapper */
int traceprobe_parse_probe_arg(char *arg, ssize_t *size,
- struct probe_arg *parg, bool is_return, bool is_kprobe)
+ struct probe_arg *parg, unsigned int flags)
{
struct fetch_insn *code, *scode, *tmp = NULL;
char *t, *t2;
@@ -397,7 +407,7 @@ int traceprobe_parse_probe_arg(char *arg, ssize_t *size,
code[FETCH_INSN_MAX - 1].op = FETCH_OP_END;
ret = parse_probe_arg(arg, parg->type, &code, &code[FETCH_INSN_MAX - 1],
- is_return, is_kprobe);
+ flags);
if (ret)
goto fail;