]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/ia64/kernel/ptrace.c
Merge master.kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[linux-2.6-omap-h63xx.git] / arch / ia64 / kernel / ptrace.c
index bbb8bc7c0552cdb860a466df3e302698b35da58c..3f8918782e0c992721a1758c1f83e2446f5261fe 100644 (file)
@@ -6,7 +6,6 @@
  *
  * Derived from the x86 and Alpha versions.
  */
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -254,7 +253,7 @@ get_rnat (struct task_struct *task, struct switch_stack *sw,
        long num_regs, nbits;
        struct pt_regs *pt;
 
-       pt = ia64_task_regs(task);
+       pt = task_pt_regs(task);
        kbsp = (unsigned long *) sw->ar_bspstore;
        ubspstore = (unsigned long *) pt->ar_bspstore;
 
@@ -314,7 +313,7 @@ put_rnat (struct task_struct *task, struct switch_stack *sw,
        struct pt_regs *pt;
        unsigned long cfm, *urbs_kargs;
 
-       pt = ia64_task_regs(task);
+       pt = task_pt_regs(task);
        kbsp = (unsigned long *) sw->ar_bspstore;
        ubspstore = (unsigned long *) pt->ar_bspstore;
 
@@ -407,7 +406,7 @@ ia64_peek (struct task_struct *child, struct switch_stack *child_stack,
 
        urbs_end = (long *) user_rbs_end;
        laddr = (unsigned long *) addr;
-       child_regs = ia64_task_regs(child);
+       child_regs = task_pt_regs(child);
        bspstore = (unsigned long *) child_regs->ar_bspstore;
        krbs = (unsigned long *) child + IA64_RBS_OFFSET/8;
        if (on_kernel_rbs(addr, (unsigned long) bspstore,
@@ -467,7 +466,7 @@ ia64_poke (struct task_struct *child, struct switch_stack *child_stack,
        struct pt_regs *child_regs;
 
        laddr = (unsigned long *) addr;
-       child_regs = ia64_task_regs(child);
+       child_regs = task_pt_regs(child);
        bspstore = (unsigned long *) child_regs->ar_bspstore;
        krbs = (unsigned long *) child + IA64_RBS_OFFSET/8;
        if (on_kernel_rbs(addr, (unsigned long) bspstore,
@@ -567,7 +566,7 @@ thread_matches (struct task_struct *thread, unsigned long addr)
                 */
                return 0;
 
-       thread_regs = ia64_task_regs(thread);
+       thread_regs = task_pt_regs(thread);
        thread_rbs_end = ia64_get_user_rbs_end(thread, thread_regs, NULL);
        if (!on_kernel_rbs(addr, thread_regs->ar_bspstore, thread_rbs_end))
                return 0;
@@ -587,8 +586,9 @@ thread_matches (struct task_struct *thread, unsigned long addr)
 static struct task_struct *
 find_thread_for_addr (struct task_struct *child, unsigned long addr)
 {
-       struct task_struct *g, *p;
+       struct task_struct *p;
        struct mm_struct *mm;
+       struct list_head *this, *next;
        int mm_users;
 
        if (!(mm = get_task_mm(child)))
@@ -600,28 +600,21 @@ find_thread_for_addr (struct task_struct *child, unsigned long addr)
                goto out;               /* not multi-threaded */
 
        /*
-        * First, traverse the child's thread-list.  Good for scalability with
-        * NPTL-threads.
+        * Traverse the current process' children list.  Every task that
+        * one attaches to becomes a child.  And it is only attached children
+        * of the debugger that are of interest (ptrace_check_attach checks
+        * for this).
         */
-       p = child;
-       do {
-               if (thread_matches(p, addr)) {
-                       child = p;
-                       goto out;
-               }
-               if (mm_users-- <= 1)
-                       goto out;
-       } while ((p = next_thread(p)) != child);
-
-       do_each_thread(g, p) {
-               if (child->mm != mm)
+       list_for_each_safe(this, next, &current->children) {
+               p = list_entry(this, struct task_struct, sibling);
+               if (p->tgid != child->tgid)
                        continue;
-
                if (thread_matches(p, addr)) {
                        child = p;
                        goto out;
                }
-       } while_each_thread(g, p);
+       }
+
   out:
        mmput(mm);
        return child;
@@ -633,7 +626,7 @@ find_thread_for_addr (struct task_struct *child, unsigned long addr)
 inline void
 ia64_flush_fph (struct task_struct *task)
 {
-       struct ia64_psr *psr = ia64_psr(ia64_task_regs(task));
+       struct ia64_psr *psr = ia64_psr(task_pt_regs(task));
 
        /*
         * Prevent migrating this task while
@@ -659,7 +652,7 @@ ia64_flush_fph (struct task_struct *task)
 void
 ia64_sync_fph (struct task_struct *task)
 {
-       struct ia64_psr *psr = ia64_psr(ia64_task_regs(task));
+       struct ia64_psr *psr = ia64_psr(task_pt_regs(task));
 
        ia64_flush_fph(task);
        if (!(task->thread.flags & IA64_THREAD_FPH_VALID)) {
@@ -800,7 +793,7 @@ access_uarea (struct task_struct *child, unsigned long addr,
                                          + offsetof(struct pt_regs, reg)))
 
 
-       pt = ia64_task_regs(child);
+       pt = task_pt_regs(child);
        sw = (struct switch_stack *) (child->thread.ksp + 16);
 
        if ((addr & 0x7) != 0) {
@@ -1126,7 +1119,7 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
        if (!access_ok(VERIFY_WRITE, ppr, sizeof(struct pt_all_user_regs)))
                return -EIO;
 
-       pt = ia64_task_regs(child);
+       pt = task_pt_regs(child);
        sw = (struct switch_stack *) (child->thread.ksp + 16);
        unw_init_from_blocked_task(&info, child);
        if (unw_unwind_to_user(&info) < 0) {
@@ -1271,7 +1264,7 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
        if (!access_ok(VERIFY_READ, ppr, sizeof(struct pt_all_user_regs)))
                return -EIO;
 
-       pt = ia64_task_regs(child);
+       pt = task_pt_regs(child);
        sw = (struct switch_stack *) (child->thread.ksp + 16);
        unw_init_from_blocked_task(&info, child);
        if (unw_unwind_to_user(&info) < 0) {
@@ -1409,9 +1402,10 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
 void
 ptrace_disable (struct task_struct *child)
 {
-       struct ia64_psr *child_psr = ia64_psr(ia64_task_regs(child));
+       struct ia64_psr *child_psr = ia64_psr(task_pt_regs(child));
 
        /* make sure the single step/taken-branch trap bits are not set: */
+       clear_tsk_thread_flag(child, TIF_SINGLESTEP);
        child_psr->ss = 0;
        child_psr->tb = 0;
 }
@@ -1428,14 +1422,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data)
        lock_kernel();
        ret = -EPERM;
        if (request == PTRACE_TRACEME) {
-               /* are we already being traced? */
-               if (current->ptrace & PT_PTRACED)
-                       goto out;
-               ret = security_ptrace(current->parent, current);
-               if (ret)
-                       goto out;
-               current->ptrace |= PT_PTRACED;
-               ret = 0;
+               ret = ptrace_traceme();
                goto out;
        }
 
@@ -1469,7 +1456,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data)
        if (ret < 0)
                goto out_tsk;
 
-       pt = ia64_task_regs(child);
+       pt = task_pt_regs(child);
        sw = (struct switch_stack *) (child->thread.ksp + 16);
 
        switch (request) {
@@ -1539,6 +1526,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data)
                 * Make sure the single step/taken-branch trap bits
                 * are not set:
                 */
+               clear_tsk_thread_flag(child, TIF_SINGLESTEP);
                ia64_psr(pt)->ss = 0;
                ia64_psr(pt)->tb = 0;
 
@@ -1570,6 +1558,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data)
                        goto out_tsk;
 
                clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+               set_tsk_thread_flag(child, TIF_SINGLESTEP);
                if (request == PTRACE_SINGLESTEP) {
                        ia64_psr(pt)->ss = 1;
                } else {
@@ -1609,13 +1598,9 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data)
 }
 
 
-void
+static void
 syscall_trace (void)
 {
-       if (!test_thread_flag(TIF_SYSCALL_TRACE))
-               return;
-       if (!(current->ptrace & PT_PTRACED))
-               return;
        /*
         * The 0x80 provides a way for the tracing parent to
         * distinguish between a syscall stop and SIGTRAP delivery.
@@ -1657,7 +1642,7 @@ syscall_trace_enter (long arg0, long arg1, long arg2, long arg3,
                        arch = AUDIT_ARCH_IA64;
                }
 
-               audit_syscall_entry(current, arch, syscall, arg0, arg1, arg2, arg3);
+               audit_syscall_entry(arch, syscall, arg0, arg1, arg2, arg3);
        }
 
 }
@@ -1669,10 +1654,17 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3,
                     long arg4, long arg5, long arg6, long arg7,
                     struct pt_regs regs)
 {
-       if (unlikely(current->audit_context))
-               audit_syscall_exit(current, AUDITSC_RESULT(regs.r10), regs.r8);
+       if (unlikely(current->audit_context)) {
+               int success = AUDITSC_RESULT(regs.r10);
+               long result = regs.r8;
+
+               if (success != AUDITSC_SUCCESS)
+                       result = -result;
+               audit_syscall_exit(success, result);
+       }
 
-       if (test_thread_flag(TIF_SYSCALL_TRACE)
+       if ((test_thread_flag(TIF_SYSCALL_TRACE)
+           || test_thread_flag(TIF_SINGLESTEP))
            && (current->ptrace & PT_PTRACED))
                syscall_trace();
 }