|
@@ -255,12 +255,18 @@ fail:
|
|
|
}
|
|
|
|
|
|
/* Special function : only accept unsigned long */
|
|
|
-static __kprobes void fetch_stack_address(struct pt_regs *regs,
|
|
|
- void *dummy, void *dest)
|
|
|
+static __kprobes void fetch_kernel_stack_address(struct pt_regs *regs,
|
|
|
+ void *dummy, void *dest)
|
|
|
{
|
|
|
*(unsigned long *)dest = kernel_stack_pointer(regs);
|
|
|
}
|
|
|
|
|
|
+static __kprobes void fetch_user_stack_address(struct pt_regs *regs,
|
|
|
+ void *dummy, void *dest)
|
|
|
+{
|
|
|
+ *(unsigned long *)dest = user_stack_pointer(regs);
|
|
|
+}
|
|
|
+
|
|
|
static fetch_func_t get_fetch_size_function(const struct fetch_type *type,
|
|
|
fetch_func_t orig_fn,
|
|
|
const struct fetch_type *ftbl)
|
|
@@ -305,7 +311,8 @@ int traceprobe_split_symbol_offset(char *symbol, unsigned 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_param *f, bool is_return)
|
|
|
+ struct fetch_param *f, bool is_return,
|
|
|
+ bool is_kprobe)
|
|
|
{
|
|
|
int ret = 0;
|
|
|
unsigned long param;
|
|
@@ -317,13 +324,16 @@ static int parse_probe_vars(char *arg, const struct fetch_type *t,
|
|
|
ret = -EINVAL;
|
|
|
} else if (strncmp(arg, "stack", 5) == 0) {
|
|
|
if (arg[5] == '\0') {
|
|
|
- if (strcmp(t->name, DEFAULT_FETCH_TYPE_STR) == 0)
|
|
|
- f->fn = fetch_stack_address;
|
|
|
+ if (strcmp(t->name, DEFAULT_FETCH_TYPE_STR))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (is_kprobe)
|
|
|
+ f->fn = fetch_kernel_stack_address;
|
|
|
else
|
|
|
- ret = -EINVAL;
|
|
|
+ f->fn = fetch_user_stack_address;
|
|
|
} else if (isdigit(arg[5])) {
|
|
|
ret = kstrtoul(arg + 5, 10, ¶m);
|
|
|
- if (ret || param > PARAM_MAX_STACK)
|
|
|
+ if (ret || (is_kprobe && param > PARAM_MAX_STACK))
|
|
|
ret = -EINVAL;
|
|
|
else {
|
|
|
f->fn = t->fetch[FETCH_MTD_stack];
|
|
@@ -350,13 +360,9 @@ static int parse_probe_arg(char *arg, const struct fetch_type *t,
|
|
|
ftbl = is_kprobe ? kprobes_fetch_type_table : uprobes_fetch_type_table;
|
|
|
BUG_ON(ftbl == NULL);
|
|
|
|
|
|
- /* Until uprobe_events supports only reg arguments */
|
|
|
- if (!is_kprobe && arg[0] != '%')
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
switch (arg[0]) {
|
|
|
case '$':
|
|
|
- ret = parse_probe_vars(arg + 1, t, f, is_return);
|
|
|
+ ret = parse_probe_vars(arg + 1, t, f, is_return, is_kprobe);
|
|
|
break;
|
|
|
|
|
|
case '%': /* named register */
|
|
@@ -377,6 +383,10 @@ static int parse_probe_arg(char *arg, const struct fetch_type *t,
|
|
|
f->fn = t->fetch[FETCH_MTD_memory];
|
|
|
f->data = (void *)param;
|
|
|
} else {
|
|
|
+ /* uprobes don't support symbols */
|
|
|
+ if (!is_kprobe)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
ret = traceprobe_split_symbol_offset(arg + 1, &offset);
|
|
|
if (ret)
|
|
|
break;
|