-#ifdef DEBUG_PTRACE
- printk("%s [%d]: syscall_trace\n", current->comm, current->pid);
-#endif
- if (!test_thread_flag(TIF_SYSCALL_TRACE))
- return;
- if (!(current->ptrace & PT_PTRACED))
- return;
- current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
- ? 0x80 : 0);
- current->state = TASK_STOPPED;
- notify_parent(current, SIGCHLD);
- schedule();
-
- /*
- * this isn't the same as continuing with a signal, but it will do
- * for normal use. strace only continues with a signal if the
- * stopping signal is not SIGTRAP. -brl
- */
-#ifdef DEBUG_PTRACE
- printk("%s [%d]: syscall_trace exit= %x\n", current->comm,
- current->pid, current->exit_code);
-#endif
- if (current->exit_code) {
- send_sig (current->exit_code, current, 1);
- current->exit_code = 0;
+ void __user *uaddr = (void __user *) addr;
+ struct pt_regs *uregs = uaddr;
+ int err = -ENOSYS;
+
+ switch (*request) {
+ case PTRACE_GETREGS64:
+ err = ptrace_layout_access(child, engine,
+ &utrace_sparc64_native_view,
+ sparc64_getregs_layout,
+ 0, offsetof(struct pt_regs, y),
+ uaddr, NULL, 0);
+ if (!err &&
+ (put_user(task_pt_regs(child)->y, &uregs->y) ||
+ put_user(task_pt_regs(child)->fprs, &uregs->fprs)))
+ err = -EFAULT;
+ break;
+
+ case PTRACE_SETREGS64:
+ err = ptrace_layout_access(child, engine,
+ &utrace_sparc64_native_view,
+ sparc64_getregs_layout,
+ 0, offsetof(struct pt_regs, y),
+ uaddr, NULL, 1);
+ if (!err &&
+ (get_user(task_pt_regs(child)->y, &uregs->y) ||
+ get_user(task_pt_regs(child)->fprs, &uregs->fprs)))
+ err = -EFAULT;
+ break;
+
+ case PTRACE_GETFPREGS64:
+ case PTRACE_SETFPREGS64:
+ err = ptrace_regset_access(child, engine,
+ utrace_native_view(current),
+ 2, 0, 34 * sizeof(long), uaddr,
+ (*request == PTRACE_SETFPREGS64));
+ break;
+
+ case PTRACE_SUNDETACH:
+ *request = PTRACE_DETACH;
+ break;
+
+ default:
+ break;
+ };
+ return err;
+}
+
+#ifdef CONFIG_COMPAT
+static const struct ptrace_layout_segment sparc32_getregs_layout[] = {
+ { 0, offsetof(struct pt_regs32, u_regs[0]),
+ 0, GENREG32_PSR * sizeof(u32) },
+ { offsetof(struct pt_regs32, u_regs[0]),
+ offsetof(struct pt_regs32, u_regs[15]),
+ 0, 1 * sizeof(u32) },
+ { offsetof(struct pt_regs32, u_regs[15]), sizeof(struct pt_regs32),
+ -1, 0 },
+ {0, 0, -1, 0}
+};
+
+int arch_compat_ptrace(compat_long_t *request, struct task_struct *child,
+ struct utrace_attached_engine *engine,
+ compat_ulong_t addr, compat_ulong_t data,
+ compat_long_t *retval)
+{
+ void __user *uaddr = (void __user *) (unsigned long) addr;
+ int err = -ENOSYS;
+
+ switch (*request) {
+ case PTRACE_GETREGS:
+ case PTRACE_SETREGS:
+ err = ptrace_layout_access(child, engine,
+ &utrace_sparc32_view,
+ sparc32_getregs_layout,
+ 0, sizeof(struct pt_regs32),
+ uaddr, NULL,
+ (*request ==
+ PTRACE_SETREGS));
+ break;
+
+ case PTRACE_GETFPREGS:
+ case PTRACE_SETFPREGS:
+ err = ptrace_whole_regset(child, engine, addr, 1,
+ (*request == PTRACE_SETFPREGS));
+ break;
+
+ case PTRACE_SUNDETACH:
+ *request = PTRACE_DETACH;
+ break;
+
+ default:
+ break;
+ };
+ return err;
+}
+#endif /* CONFIG_COMPAT */
+#endif /* CONFIG_PTRACE */
+
+asmlinkage void syscall_trace(struct pt_regs *regs, int syscall_exit_p)
+{
+ /* do the secure computing check first */
+ if (!syscall_exit_p)
+ secure_computing(regs->u_regs[UREG_G1]);
+
+ if (unlikely(current->audit_context) && syscall_exit_p) {
+ unsigned long tstate = regs->tstate;
+ int result = AUDITSC_SUCCESS;
+
+ if (unlikely(tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
+ result = AUDITSC_FAILURE;
+
+ audit_syscall_exit(result, regs->u_regs[UREG_I0]);