aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
authorNicolas Pitre <nico@cam.org>2006-01-14 14:30:04 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-01-14 14:30:04 -0500
commit3f471126ee53feb5e9b210ea2f525ed3bb9b7a7f (patch)
tree3f7567343a892d02e758bcd1c07557af43d5aa1b /arch/arm/kernel
parent6c90c872017773cde70a51432cb28f253451b967 (diff)
[ARM] 3262/4: allow ptraced syscalls to be overriden
Patch from Nicolas Pitre This is needed by strace to properly handle the tracing of some system calls. It could be useful for other applications as well. Based on an earlier patch from Daniel Jacobowitz. Signed-off-by: Nicolas Pitre <nico@cam.org> Signed-off-by: Daniel Jacobowitz <dan@debian.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/entry-common.S3
-rw-r--r--arch/arm/kernel/ptrace.c15
2 files changed, 15 insertions, 3 deletions
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 8826d9803aeb..2b92ce85f97f 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -214,11 +214,13 @@ ENTRY(vector_swi)
214 * context switches, and waiting for our parent to respond. 214 * context switches, and waiting for our parent to respond.
215 */ 215 */
216__sys_trace: 216__sys_trace:
217 mov r2, scno
217 add r1, sp, #S_OFF 218 add r1, sp, #S_OFF
218 mov r0, #0 @ trace entry [IP = 0] 219 mov r0, #0 @ trace entry [IP = 0]
219 bl syscall_trace 220 bl syscall_trace
220 221
221 adr lr, __sys_trace_return @ return address 222 adr lr, __sys_trace_return @ return address
223 mov scno, r0 @ syscall number (possibly new)
222 add r1, sp, #S_R0 + S_OFF @ pointer to regs 224 add r1, sp, #S_R0 + S_OFF @ pointer to regs
223 cmp scno, #NR_syscalls @ check upper syscall limit 225 cmp scno, #NR_syscalls @ check upper syscall limit
224 ldmccia r1, {r0 - r3} @ have to reload r0 - r3 226 ldmccia r1, {r0 - r3} @ have to reload r0 - r3
@@ -227,6 +229,7 @@ __sys_trace:
227 229
228__sys_trace_return: 230__sys_trace_return:
229 str r0, [sp, #S_R0 + S_OFF]! @ save returned r0 231 str r0, [sp, #S_R0 + S_OFF]! @ save returned r0
232 mov r2, scno
230 mov r1, sp 233 mov r1, sp
231 mov r0, #1 @ trace exit [IP = 1] 234 mov r0, #1 @ trace exit [IP = 1]
232 bl syscall_trace 235 bl syscall_trace
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index e591f72bcdeb..7b6256bb590e 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -766,6 +766,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
766 (unsigned long __user *) data); 766 (unsigned long __user *) data);
767 break; 767 break;
768 768
769 case PTRACE_SET_SYSCALL:
770 ret = 0;
771 child->ptrace_message = data;
772 break;
773
769 default: 774 default:
770 ret = ptrace_request(child, request, addr, data); 775 ret = ptrace_request(child, request, addr, data);
771 break; 776 break;
@@ -774,14 +779,14 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
774 return ret; 779 return ret;
775} 780}
776 781
777asmlinkage void syscall_trace(int why, struct pt_regs *regs) 782asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
778{ 783{
779 unsigned long ip; 784 unsigned long ip;
780 785
781 if (!test_thread_flag(TIF_SYSCALL_TRACE)) 786 if (!test_thread_flag(TIF_SYSCALL_TRACE))
782 return; 787 return scno;
783 if (!(current->ptrace & PT_PTRACED)) 788 if (!(current->ptrace & PT_PTRACED))
784 return; 789 return scno;
785 790
786 /* 791 /*
787 * Save IP. IP is used to denote syscall entry/exit: 792 * Save IP. IP is used to denote syscall entry/exit:
@@ -790,6 +795,8 @@ asmlinkage void syscall_trace(int why, struct pt_regs *regs)
790 ip = regs->ARM_ip; 795 ip = regs->ARM_ip;
791 regs->ARM_ip = why; 796 regs->ARM_ip = why;
792 797
798 current->ptrace_message = scno;
799
793 /* the 0x80 provides a way for the tracing parent to distinguish 800 /* the 0x80 provides a way for the tracing parent to distinguish
794 between a syscall stop and SIGTRAP delivery */ 801 between a syscall stop and SIGTRAP delivery */
795 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) 802 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
@@ -804,4 +811,6 @@ asmlinkage void syscall_trace(int why, struct pt_regs *regs)
804 current->exit_code = 0; 811 current->exit_code = 0;
805 } 812 }
806 regs->ARM_ip = ip; 813 regs->ARM_ip = ip;
814
815 return current->ptrace_message;
807} 816}