]> git.hungrycats.org Git - linux/commitdiff
ia64: Allow system-call number to be changed during system-call tracing
authorDavid Mosberger <davidm@tiger.hpl.hp.com>
Wed, 31 Dec 2003 15:18:59 +0000 (07:18 -0800)
committerDavid Mosberger <davidm@tiger.hpl.hp.com>
Wed, 31 Dec 2003 15:18:59 +0000 (07:18 -0800)
(both for native and x86 system call tracing).  This is needed
by recent versions of strace and UML likes to do that, too.

arch/ia64/ia32/ia32_entry.S
arch/ia64/kernel/entry.S
arch/ia64/kernel/ivt.S
arch/ia64/kernel/ptrace.c
include/asm-ia64/ia32.h

index 1230fd2b479fa78ed8a067c66026a8e4ff26c0ee..f8b22ce60ff2c294c0772d2482bf173de3d71b4a 100644 (file)
@@ -1,4 +1,5 @@
 #include <asm/asmmacro.h>
+#include <asm/ia32.h>
 #include <asm/offsets.h>
 #include <asm/signal.h>
 #include <asm/thread_info.h>
@@ -141,27 +142,35 @@ GLOBAL_ENTRY(ia32_trace_syscall)
        adds r2=IA64_PT_REGS_R8_OFFSET+16,sp
        ;;
        st8 [r2]=r3                             // initialize return code to -ENOSYS
-       br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch syscall args
-       // Need to reload arguments (they may be changed by the tracing process)
-       adds r2=IA64_PT_REGS_R9_OFFSET+16,sp    // r2 = &pt_regs.r9
+       br.call.sptk.few rp=syscall_trace       // give parent a chance to catch syscall args
+.ret2: // Need to reload arguments (they may be changed by the tracing process)
+       adds r2=IA64_PT_REGS_R1_OFFSET+16,sp    // r2 = &pt_regs.r1
        adds r3=IA64_PT_REGS_R13_OFFSET+16,sp   // r3 = &pt_regs.r13
+       mov r15=IA32_NR_syscalls
+       ;;
+       ld4 r8=[r2],IA64_PT_REGS_R9_OFFSET-IA64_PT_REGS_R1_OFFSET
+       movl r16=ia32_syscall_table
        ;;
        ld4 r33=[r2],8                          // r9 == ecx
        ld4 r37=[r3],16                         // r13 == ebp
+       cmp.ltu.unc p6,p7=r8,r15
        ;;
        ld4 r34=[r2],8                          // r10 == edx
        ld4 r36=[r3],8                          // r15 == edi
+(p6)   shladd r16=r8,3,r16     // force ni_syscall if not valid syscall number
+       ;;
+       ld8 r16=[r16]
        ;;
        ld4 r32=[r2],8                          // r11 == ebx
+       mov b6=r16
        ld4 r35=[r3],8                          // r14 == esi
-       ;;
-.ret2: br.call.sptk.few rp=b6                  // do the syscall
+       br.call.sptk.few rp=b6                  // do the syscall
 .ia32_strace_check_retval:
        cmp.lt p6,p0=r8,r0                      // syscall failed?
        adds r2=IA64_PT_REGS_R8_OFFSET+16,sp    // r2 = &pt_regs.r8
        ;;
        st8.spill [r2]=r8                       // store return value in slot for r8
-       br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch return value
+       br.call.sptk.few rp=syscall_trace       // give parent a chance to catch return value
 .ret4: alloc r2=ar.pfs,0,0,0,0                 // drop the syscall argument frame
        br.cond.sptk.many ia64_leave_kernel
 END(ia32_trace_syscall)
@@ -469,10 +478,6 @@ ia32_syscall_table:
        data8 sys_ni_syscall
        data8 sys_statfs64
        data8 sys_fstatfs64
-       data8 sys_ni_syscall
-       
-       /*
-        *  CAUTION: If any system calls are added beyond this point
-        *      then the check in `arch/ia64/kernel/ivt.S' will have
-        *      to be modified also.  You've been warned.
-        */
+
+       // guard against failures to increase IA32_NR_syscalls
+       .org ia32_syscall_table + 8*IA32_NR_syscalls
index b189495af5d2d5988b12dcaca8e6dc936801e268..27943979a9c149918061844061ea1b49dbf0b220 100644 (file)
@@ -483,34 +483,11 @@ GLOBAL_ENTRY(clone)
        br.ret.sptk.many rp
 END(clone)
 
-       /*
-        * We invoke syscall_trace through this intermediate function to
-        * ensure that the syscall input arguments are not clobbered.  We
-        * also use it to preserve b6, which contains the syscall entry point.
-        */
-GLOBAL_ENTRY(invoke_syscall_trace)
-       .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
-       alloc loc1=ar.pfs,8,3,0,0
-       mov loc0=rp
-       .body
-       mov loc2=b6
-       ;;
-       br.call.sptk.many rp=syscall_trace
-.ret3: mov rp=loc0
-       mov ar.pfs=loc1
-       mov b6=loc2
-       br.ret.sptk.many rp
-END(invoke_syscall_trace)
-
        /*
         * Invoke a system call, but do some tracing before and after the call.
         * We MUST preserve the current register frame throughout this routine
         * because some system calls (such as ia64_execve) directly
         * manipulate ar.pfs.
-        *
-        * Input:
-        *      r15 = syscall number
-        *      b6  = syscall entry point
         */
        .global ia64_strace_leave_kernel
 
@@ -522,21 +499,38 @@ GLOBAL_ENTRY(ia64_trace_syscall)
         */
        nop.m 0
        nop.i 0
-       br.call.sptk.many rp=invoke_syscall_trace // give parent a chance to catch syscall args
+       br.call.sptk.many rp=syscall_trace // give parent a chance to catch syscall args
 }
-.ret6: br.call.sptk.many rp=b6                 // do the syscall
-strace_check_retval:
+       // the syscall number may have changed, so re-load it and re-calculate the
+       // syscall entry-point:
+       adds r15=PT(R15)+16,sp                  // r15 = &pt_regs.r15 (syscall #)
+       ;;
+       ld8 r15=[r15]
+       mov r3=NR_syscalls - 1
+       ;;
+       adds r15=-1024,r15
+       movl r16=sys_call_table
+       ;;
+       shladd r20=r15,3,r16                    // r20 = sys_call_table + 8*(syscall-1024)
+       cmp.leu p6,p7=r15,r3
+       ;;
+(p6)   ld8 r20=[r20]                           // load address of syscall entry point
+(p7)   movl r20=sys_ni_syscall
+       ;;
+       mov b6=r20
+       br.call.sptk.many rp=b6                 // do the syscall
+.strace_check_retval:
        cmp.lt p6,p0=r8,r0                      // syscall failed?
        adds r2=PT(R8)+16,sp                    // r2 = &pt_regs.r8
        adds r3=PT(R10)+16,sp                   // r3 = &pt_regs.r10
        mov r10=0
 (p6)   br.cond.sptk strace_error               // syscall failed ->
        ;;                                      // avoid RAW on r10
-strace_save_retval:
+.strace_save_retval:
 .mem.offset 0,0; st8.spill [r2]=r8             // store return value in slot for r8
 .mem.offset 8,0; st8.spill [r3]=r10            // clear error indication in slot for r10
 ia64_strace_leave_kernel:
-       br.call.sptk.many rp=invoke_syscall_trace // give parent a chance to catch return value
+       br.call.sptk.many rp=syscall_trace // give parent a chance to catch return value
 .rety: br.cond.sptk ia64_leave_syscall
 
 strace_error:
@@ -548,7 +542,7 @@ strace_error:
        ;;
 (p6)   mov r10=-1
 (p6)   mov r8=r9
-       br.cond.sptk strace_save_retval
+       br.cond.sptk .strace_save_retval
 END(ia64_trace_syscall)
 
 GLOBAL_ENTRY(ia64_ret_from_clone)
@@ -573,7 +567,7 @@ GLOBAL_ENTRY(ia64_ret_from_clone)
        ;;
        mov r8=0
        tbit.nz p6,p0=r2,TIF_SYSCALL_TRACE
-(p6)   br.cond.spnt strace_check_retval
+(p6)   br.cond.spnt .strace_check_retval
        ;;                                      // added stop bits to prevent r8 dependency
 END(ia64_ret_from_clone)
        // fall through
index 6a32b97b9e60f050393f08d314c9087bb6052a7f..8aed612cb284fe6fd14b705e3fb933ae754a6244 100644 (file)
@@ -42,6 +42,7 @@
 
 #include <asm/asmmacro.h>
 #include <asm/break.h>
+#include <asm/ia32.h>
 #include <asm/kregs.h>
 #include <asm/offsets.h>
 #include <asm/pgtable.h>
@@ -705,13 +706,14 @@ ENTRY(break_fault)
        movl r2=ia64_ret_from_syscall
        ;;
        shladd r20=r15,3,r16                    // r20 = sys_call_table + 8*(syscall-1024)
-       cmp.geu p0,p7=r3,r15                    // (syscall > 0 && syscall < 1024 + NR_syscalls) ?
+       cmp.leu p6,p7=r15,r3                    // (syscall > 0 && syscall < 1024 + NR_syscalls) ?
        mov rp=r2                               // set the real return addr
        ;;
-(p7)   add r20=(__NR_ni_syscall-1024)*8,r16    // force __NR_ni_syscall
+(p6)   ld8 r20=[r20]                           // load address of syscall entry point
+(p7)   movl r20=sys_ni_syscall
+
        add r2=TI_FLAGS+IA64_TASK_SIZE,r13
        ;;
-       ld8 r20=[r20]                           // load address of syscall entry point
        ld4 r2=[r2]                             // r2 = current_thread_info()->flags
        ;;
        tbit.z p8,p0=r2,TIF_SYSCALL_TRACE
@@ -1513,7 +1515,7 @@ ENTRY(dispatch_to_ia32_handler)
        alloc r15=ar.pfs,0,0,6,0        // must first in an insn group
        ;;
        ld4 r8=[r14],8          // r8 == eax (syscall number)
-       mov r15=270             // number of entries in ia32 system call table
+       mov r15=IA32_NR_syscalls
        ;;
        cmp.ltu.unc p6,p7=r8,r15
        ld4 out1=[r14],8        // r9 == ecx
index 427bc87ae608949a7e03d82a2bfcf2857bae282f..cbcb2b24fe8fc364a7e6f4211605e3860ecc406e 100644 (file)
@@ -1421,7 +1421,9 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data,
        return ret;
 }
 
-void
+/* "asmlinkage" so the input arguments are preserved... */
+
+asmlinkage void
 syscall_trace (void)
 {
        if (!test_thread_flag(TIF_SYSCALL_TRACE))
index 4c8fd32b8b78f29ec86ee5b86e8f516e5c00ff28..da5a1f22c5662977f3f8b05569734e46678d95ee 100644 (file)
@@ -6,7 +6,11 @@
 #include <asm/ptrace.h>
 #include <asm/signal.h>
 
-#ifdef CONFIG_IA32_SUPPORT
+#define IA32_NR_syscalls               270 /* length of syscall table */
+
+#ifndef __ASSEMBLY__
+
+# ifdef CONFIG_IA32_SUPPORT
 
 extern void ia32_cpu_init (void);
 extern void ia32_boot_gdt_init (void);
@@ -15,10 +19,12 @@ extern int ia32_exception (struct pt_regs *regs, unsigned long isr);
 extern int ia32_intercept (struct pt_regs *regs, unsigned long isr);
 extern int ia32_clone_tls (struct task_struct *child, struct pt_regs *childregs);
 
-#endif /* !CONFIG_IA32_SUPPORT */
+# endif /* !CONFIG_IA32_SUPPORT */
 
 /* Declare this unconditionally, so we don't get warnings for unreachable code.  */
 extern int ia32_setup_frame1 (int sig, struct k_sigaction *ka, siginfo_t *info,
                              sigset_t *set, struct pt_regs *regs);
 
+#endif /* !__ASSEMBLY__ */
+
 #endif /* _ASM_IA64_IA32_H */