tracing/probes: Add fetch{,_size} member into deref fetch method
authorHyeoncheol Lee <cheol.lee@lge.com>
Mon, 1 Jul 2013 04:44:32 +0000 (13:44 +0900)
committerSteven Rostedt <rostedt@goodmis.org>
Thu, 2 Jan 2014 21:17:42 +0000 (16:17 -0500)
The deref fetch methods access a memory region but it assumes that
it's a kernel memory since uprobes does not support them.

Add ->fetch and ->fetch_size member in order to provide a proper
access methods for supporting uprobes.

Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Acked-by: Oleg Nesterov <oleg@redhat.com>
Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: zhangwei(Jovi) <jovi.zhangwei@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Signed-off-by: Hyeoncheol Lee <cheol.lee@lge.com>
[namhyung@kernel.org: Split original patch into pieces as requested]
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
kernel/trace/trace_probe.c

index a31ad47..8d7231d 100644 (file)
@@ -184,6 +184,8 @@ __kprobes void FETCH_FUNC_NAME(memory, string_size)(struct pt_regs *regs,
 struct deref_fetch_param {
        struct fetch_param      orig;
        long                    offset;
+       fetch_func_t            fetch;
+       fetch_func_t            fetch_size;
 };
 
 #define DEFINE_FETCH_deref(type)                                       \
@@ -195,13 +197,26 @@ __kprobes void FETCH_FUNC_NAME(deref, type)(struct pt_regs *regs, \
        call_fetch(&dprm->orig, regs, &addr);                           \
        if (addr) {                                                     \
                addr += dprm->offset;                                   \
-               fetch_memory_##type(regs, (void *)addr, dest);          \
+               dprm->fetch(regs, (void *)addr, dest);                  \
        } else                                                          \
                *(type *)dest = 0;                                      \
 }
 DEFINE_BASIC_FETCH_FUNCS(deref)
 DEFINE_FETCH_deref(string)
-DEFINE_FETCH_deref(string_size)
+
+__kprobes void FETCH_FUNC_NAME(deref, string_size)(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 && dprm->fetch_size) {
+               addr += dprm->offset;
+               dprm->fetch_size(regs, (void *)addr, dest);
+       } else
+               *(string_size *)dest = 0;
+}
 
 static __kprobes void update_deref_fetch_param(struct deref_fetch_param *data)
 {
@@ -477,6 +492,9 @@ static int parse_probe_arg(char *arg, const struct fetch_type *t,
                                return -ENOMEM;
 
                        dprm->offset = offset;
+                       dprm->fetch = t->fetch[FETCH_MTD_memory];
+                       dprm->fetch_size = get_fetch_size_function(t,
+                                                       dprm->fetch, ftbl);
                        ret = parse_probe_arg(arg, t2, &dprm->orig, is_return,
                                                        is_kprobe);
                        if (ret)