summaryrefslogtreecommitdiff
path: root/arch/xtensa/kernel/ptrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/xtensa/kernel/ptrace.c')
-rw-r--r--arch/xtensa/kernel/ptrace.c170
1 files changed, 77 insertions, 93 deletions
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c
index e0f583fed06a..e2461968efb2 100644
--- a/arch/xtensa/kernel/ptrace.c
+++ b/arch/xtensa/kernel/ptrace.c
@@ -1,4 +1,3 @@
-// TODO some minor issues
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -24,13 +23,14 @@
#include <linux/security.h>
#include <linux/signal.h>
#include <linux/smp.h>
+#include <linux/tracehook.h>
+#include <linux/uaccess.h>
#include <asm/coprocessor.h>
#include <asm/elf.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/ptrace.h>
-#include <linux/uaccess.h>
void user_enable_single_step(struct task_struct *child)
@@ -52,7 +52,7 @@ void ptrace_disable(struct task_struct *child)
/* Nothing to do.. */
}
-int ptrace_getregs(struct task_struct *child, void __user *uregs)
+static int ptrace_getregs(struct task_struct *child, void __user *uregs)
{
struct pt_regs *regs = task_pt_regs(child);
xtensa_gregset_t __user *gregset = uregs;
@@ -73,12 +73,12 @@ int ptrace_getregs(struct task_struct *child, void __user *uregs)
for (i = 0; i < XCHAL_NUM_AREGS; i++)
__put_user(regs->areg[i],
- gregset->a + ((wb * 4 + i) % XCHAL_NUM_AREGS));
+ gregset->a + ((wb * 4 + i) % XCHAL_NUM_AREGS));
return 0;
}
-int ptrace_setregs(struct task_struct *child, void __user *uregs)
+static int ptrace_setregs(struct task_struct *child, void __user *uregs)
{
struct pt_regs *regs = task_pt_regs(child);
xtensa_gregset_t *gregset = uregs;
@@ -107,7 +107,7 @@ int ptrace_setregs(struct task_struct *child, void __user *uregs)
unsigned long rotws, wmask;
rotws = (((ws | (ws << WSBITS)) >> wb) &
- ((1 << WSBITS) - 1)) & ~1;
+ ((1 << WSBITS) - 1)) & ~1;
wmask = ((rotws ? WSBITS + 1 - ffs(rotws) : 0) << 4) |
(rotws & 0xF) | 1;
regs->windowbase = wb;
@@ -115,19 +115,19 @@ int ptrace_setregs(struct task_struct *child, void __user *uregs)
regs->wmask = wmask;
}
- if (wb != 0 && __copy_from_user(regs->areg + XCHAL_NUM_AREGS - wb * 4,
- gregset->a, wb * 16))
+ if (wb != 0 && __copy_from_user(regs->areg + XCHAL_NUM_AREGS - wb * 4,
+ gregset->a, wb * 16))
return -EFAULT;
if (__copy_from_user(regs->areg, gregset->a + wb * 4,
- (WSBITS - wb) * 16))
+ (WSBITS - wb) * 16))
return -EFAULT;
return 0;
}
-int ptrace_getxregs(struct task_struct *child, void __user *uregs)
+static int ptrace_getxregs(struct task_struct *child, void __user *uregs)
{
struct pt_regs *regs = task_pt_regs(child);
struct thread_info *ti = task_thread_info(child);
@@ -151,7 +151,7 @@ int ptrace_getxregs(struct task_struct *child, void __user *uregs)
return ret ? -EFAULT : 0;
}
-int ptrace_setxregs(struct task_struct *child, void __user *uregs)
+static int ptrace_setxregs(struct task_struct *child, void __user *uregs)
{
struct thread_info *ti = task_thread_info(child);
struct pt_regs *regs = task_pt_regs(child);
@@ -177,7 +177,8 @@ int ptrace_setxregs(struct task_struct *child, void __user *uregs)
return ret ? -EFAULT : 0;
}
-int ptrace_peekusr(struct task_struct *child, long regno, long __user *ret)
+static int ptrace_peekusr(struct task_struct *child, long regno,
+ long __user *ret)
{
struct pt_regs *regs;
unsigned long tmp;
@@ -186,86 +187,87 @@ int ptrace_peekusr(struct task_struct *child, long regno, long __user *ret)
tmp = 0; /* Default return value. */
switch(regno) {
+ case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1:
+ tmp = regs->areg[regno - REG_AR_BASE];
+ break;
- case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1:
- tmp = regs->areg[regno - REG_AR_BASE];
- break;
-
- case REG_A_BASE ... REG_A_BASE + 15:
- tmp = regs->areg[regno - REG_A_BASE];
- break;
+ case REG_A_BASE ... REG_A_BASE + 15:
+ tmp = regs->areg[regno - REG_A_BASE];
+ break;
- case REG_PC:
- tmp = regs->pc;
- break;
+ case REG_PC:
+ tmp = regs->pc;
+ break;
- case REG_PS:
- /* Note: PS.EXCM is not set while user task is running;
- * its being set in regs is for exception handling
- * convenience. */
- tmp = (regs->ps & ~(1 << PS_EXCM_BIT));
- break;
+ case REG_PS:
+ /* Note: PS.EXCM is not set while user task is running;
+ * its being set in regs is for exception handling
+ * convenience.
+ */
+ tmp = (regs->ps & ~(1 << PS_EXCM_BIT));
+ break;
- case REG_WB:
- break; /* tmp = 0 */
+ case REG_WB:
+ break; /* tmp = 0 */
- case REG_WS:
+ case REG_WS:
{
unsigned long wb = regs->windowbase;
unsigned long ws = regs->windowstart;
- tmp = ((ws>>wb) | (ws<<(WSBITS-wb))) & ((1<<WSBITS)-1);
+ tmp = ((ws >> wb) | (ws << (WSBITS - wb))) &
+ ((1 << WSBITS) - 1);
break;
}
- case REG_LBEG:
- tmp = regs->lbeg;
- break;
+ case REG_LBEG:
+ tmp = regs->lbeg;
+ break;
- case REG_LEND:
- tmp = regs->lend;
- break;
+ case REG_LEND:
+ tmp = regs->lend;
+ break;
- case REG_LCOUNT:
- tmp = regs->lcount;
- break;
+ case REG_LCOUNT:
+ tmp = regs->lcount;
+ break;
- case REG_SAR:
- tmp = regs->sar;
- break;
+ case REG_SAR:
+ tmp = regs->sar;
+ break;
- case SYSCALL_NR:
- tmp = regs->syscall;
- break;
+ case SYSCALL_NR:
+ tmp = regs->syscall;
+ break;
- default:
- return -EIO;
+ default:
+ return -EIO;
}
return put_user(tmp, ret);
}
-int ptrace_pokeusr(struct task_struct *child, long regno, long val)
+static int ptrace_pokeusr(struct task_struct *child, long regno, long val)
{
struct pt_regs *regs;
regs = task_pt_regs(child);
switch (regno) {
- case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1:
- regs->areg[regno - REG_AR_BASE] = val;
- break;
+ case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1:
+ regs->areg[regno - REG_AR_BASE] = val;
+ break;
- case REG_A_BASE ... REG_A_BASE + 15:
- regs->areg[regno - REG_A_BASE] = val;
- break;
+ case REG_A_BASE ... REG_A_BASE + 15:
+ regs->areg[regno - REG_A_BASE] = val;
+ break;
- case REG_PC:
- regs->pc = val;
- break;
+ case REG_PC:
+ regs->pc = val;
+ break;
- case SYSCALL_NR:
- regs->syscall = val;
- break;
+ case SYSCALL_NR:
+ regs->syscall = val;
+ break;
- default:
- return -EIO;
+ default:
+ return -EIO;
}
return 0;
}
@@ -467,39 +469,21 @@ long arch_ptrace(struct task_struct *child, long request,
return ret;
}
-void do_syscall_trace(void)
-{
- /*
- * The 0x80 provides a way for the tracing parent to distinguish
- * between a syscall stop and SIGTRAP delivery
- */
- ptrace_notify(SIGTRAP|((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0));
-
- /*
- * 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
- */
- if (current->exit_code) {
- send_sig(current->exit_code, current, 1);
- current->exit_code = 0;
- }
-}
-
-void do_syscall_trace_enter(struct pt_regs *regs)
+unsigned long do_syscall_trace_enter(struct pt_regs *regs)
{
- if (test_thread_flag(TIF_SYSCALL_TRACE)
- && (current->ptrace & PT_PTRACED))
- do_syscall_trace();
+ if (test_thread_flag(TIF_SYSCALL_TRACE) &&
+ tracehook_report_syscall_entry(regs))
+ return -1;
-#if 0
- audit_syscall_entry(...);
-#endif
+ return regs->areg[2];
}
void do_syscall_trace_leave(struct pt_regs *regs)
{
- if ((test_thread_flag(TIF_SYSCALL_TRACE))
- && (current->ptrace & PT_PTRACED))
- do_syscall_trace();
+ int step;
+
+ step = test_thread_flag(TIF_SINGLESTEP);
+
+ if (step || test_thread_flag(TIF_SYSCALL_TRACE))
+ tracehook_report_syscall_exit(regs, step);
}