Add possibility to retrieve userspace registers saved before syscall entry
authorVasiliy Ulyanov <v.ulyanov@samsung.com>
Wed, 13 Feb 2013 08:01:38 +0000 (12:01 +0400)
committerVasiliy Ulyanov <v.ulyanov@samsung.com>
Wed, 13 Feb 2013 08:01:38 +0000 (12:01 +0400)
driver/us_proc_inst.c
driver/us_proc_inst.h
kprobe/arch/asm-arm/dbi_kprobes.h
kprobe/arch/asm-x86/dbi_kprobes.h

index dd18a30..575a423 100644 (file)
@@ -1620,26 +1620,42 @@ int dump_backtrace(probe_id_t probe_id, struct task_struct *task,
 }
 EXPORT_SYMBOL_GPL(dump_backtrace);
 
-unsigned long get_ret_addr(struct task_struct *task, struct us_ip *ip)
+struct kretprobe_instance *find_ri(struct task_struct *task, struct us_ip *ip)
 {
-       unsigned long retaddr = 0;
        struct hlist_node *item, *tmp_node;
        struct kretprobe_instance *ri;
 
-       if (ip) {
-               hlist_for_each_safe (item, tmp_node, &ip->retprobe.used_instances) {
-                       ri = hlist_entry (item, struct kretprobe_instance, uflist);
+       if (ip == NULL)
+               return NULL;
 
-                       if (ri->task && ri->task->pid == task->pid &&
-                                       ri->task->tgid == task->tgid)
-                               retaddr = (unsigned long)ri->ret_addr;
-               }
+       hlist_for_each_safe (item, tmp_node, &ip->retprobe.used_instances) {
+               ri = hlist_entry (item, struct kretprobe_instance, uflist);
+
+               if (ri->task && ri->task->pid == task->pid &&
+                               ri->task->tgid == task->tgid)
+                       return ri;
        }
 
-       if (retaddr)
-               return retaddr;
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(find_ri);
+
+unsigned long get_ret_addr(struct task_struct *task, struct us_ip *ip)
+{
+       struct kretprobe_instance *ri = find_ri(task, ip);;
+       if (ri)
+               return (unsigned long)ri->ret_addr;
        else
-               return dbi_get_ret_addr(task_pt_regs(task));
+               dbi_get_ret_addr(task_pt_regs(task));
 }
 EXPORT_SYMBOL_GPL(get_ret_addr);
 
+unsigned long get_entry_sp(struct task_struct *task, struct us_ip *ip)
+{
+       struct kretprobe_instance *ri = find_ri(task, ip);
+       if (ri)
+               return ri->sp;
+       else
+               return dbi_get_stack_ptr(task_pt_regs(task));
+}
+EXPORT_SYMBOL_GPL(get_entry_sp);
index 66ed252..c0e0440 100644 (file)
@@ -77,9 +77,15 @@ extern int dump_to_trace(probe_id_t probe_id, void *addr, const char *buf,
 extern int dump_backtrace(probe_id_t probe_id, struct task_struct *task,
                void *addr, struct pt_regs *regs, unsigned long sz);
 
+/* Finds task's kretprobe_instance object */
+struct kretprobe_instance *find_ri(struct task_struct *task, struct us_ip *ip);
+
 /* Gets current function return address */
 extern unsigned long get_ret_addr(struct task_struct *task, struct us_ip *ip);
 
+/* Gets current function entry stack pointer */
+extern unsigned long get_entry_sp(struct task_struct *task, struct us_ip *ip);
+
 #define user_backtrace(size) \
        do { \
                us_proc_ip_t *ip = __get_cpu_var(gpCurIp); \
index 7c4b0a6..250f823 100644 (file)
@@ -64,6 +64,8 @@ typedef unsigned long kprobe_opcode_t;
 # define KPROBES_TRAMP_SS_BREAK_IDX     UPROBES_TRAMP_SS_BREAK_IDX
 # define KPROBES_TRAMP_RET_BREAK_IDX   UPROBES_TRAMP_RET_BREAK_IDX
 
+#define UREGS_OFFSET 8
+
 static inline unsigned long arch_get_task_pc(struct task_struct *p)
 {
        return task_thread_info(p)->cpu_context.pc;
@@ -74,6 +76,11 @@ static inline void arch_set_task_pc(struct task_struct *p, unsigned long val)
        task_thread_info(p)->cpu_context.pc = val;
 }
 
+static inline struct pt_regs *dbi_get_syscall_uregs(unsigned long sp)
+{
+       return (struct pt_regs *)(sp + UREGS_OFFSET);
+}
+
 static inline unsigned long dbi_get_stack_ptr(struct pt_regs *regs)
 {
        return regs->ARM_sp;
index e08d6b1..75193f8 100644 (file)
@@ -101,6 +101,11 @@ static inline void arch_set_task_pc(struct task_struct *p, unsigned long val)
        p->thread.ip = val;
 }
 
+static inline struct pt_regs *dbi_get_syscall_uregs(unsigned long sp)
+{
+       return NULL; //FIXME currently not implemented for x86
+}
+
 static inline unsigned long dbi_get_stack_ptr(struct pt_regs *regs)
 {
        return regs->EREG(sp);