diff options
Diffstat (limited to 'coregrind/m_syswrap/syswrap-main.c')
-rw-r--r-- | coregrind/m_syswrap/syswrap-main.c | 85 |
1 files changed, 78 insertions, 7 deletions
diff --git a/coregrind/m_syswrap/syswrap-main.c b/coregrind/m_syswrap/syswrap-main.c index 21f0f88d..4d33eb8d 100644 --- a/coregrind/m_syswrap/syswrap-main.c +++ b/coregrind/m_syswrap/syswrap-main.c @@ -60,14 +60,20 @@ /* Useful info which needs to be recorded somewhere: Use of registers in syscalls is: - NUM ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 ARG7 ARG8 RESULT + NUM ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 ARG7 ARG8 RESULT LINUX: - x86 eax ebx ecx edx esi edi ebp n/a n/a eax (== NUM) - amd64 rax rdi rsi rdx r10 r8 r9 n/a n/a rax (== NUM) - ppc32 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1) - ppc64 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1) - arm r7 r0 r1 r2 r3 r4 r5 n/a n/a r0 (== ARG1) - + x86 eax ebx ecx edx esi edi ebp n/a n/a eax (== NUM) + amd64 rax rdi rsi rdx r10 r8 r9 n/a n/a rax (== NUM) + ppc32 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1) + ppc64 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1) + arm r7 r0 r1 r2 r3 r4 r5 n/a n/a r0 (== ARG1) + On s390x the svc instruction is used for system calls. The system call + number is encoded in the instruction (8 bit immediate field). Since Linux + 2.6 it is also allowed to use svc 0 with the system call number in r1. + This was introduced for system calls >255, but works for all. It is + also possible to see the svc 0 together with an EXecute instruction, that + fills in the immediate field. + s390x r1/SVC r2 r3 r4 r5 r6 r7 n/a n/a r2 (== ARG1) AIX: ppc32 r2 r3 r4 r5 r6 r7 r8 r9 r10 r3(res),r4(err) ppc64 r2 r3 r4 r5 r6 r7 r8 r9 r10 r3(res),r4(err) @@ -160,6 +166,9 @@ x86: Success(N) ==> edx:eax = N, cc = 0 Fail(N) ==> edx:eax = N, cc = 1 + s390x: Success(N) ==> r2 = N + Fail(N) ==> r2 = -N + * The post wrapper is called if: - it exists, and @@ -611,6 +620,17 @@ void getSyscallArgsFromGuestState ( /*OUT*/SyscallArgs* canonical, // no canonical->sysno adjustment needed +#elif defined(VGP_s390x_linux) + VexGuestS390XState* gst = (VexGuestS390XState*)gst_vanilla; + canonical->sysno = gst->guest_SYSNO; + canonical->arg1 = gst->guest_r2; + canonical->arg2 = gst->guest_r3; + canonical->arg3 = gst->guest_r4; + canonical->arg4 = gst->guest_r5; + canonical->arg5 = gst->guest_r6; + canonical->arg6 = gst->guest_r7; + canonical->arg7 = 0; + canonical->arg8 = 0; #else # error "getSyscallArgsFromGuestState: unknown arch" #endif @@ -728,6 +748,16 @@ void putSyscallArgsIntoGuestState ( /*IN*/ SyscallArgs* canonical, stack[1] = canonical->arg7; stack[2] = canonical->arg8; +#elif defined(VGP_s390x_linux) + VexGuestS390XState* gst = (VexGuestS390XState*)gst_vanilla; + gst->guest_SYSNO = canonical->sysno; + gst->guest_r2 = canonical->arg1; + gst->guest_r3 = canonical->arg2; + gst->guest_r4 = canonical->arg3; + gst->guest_r5 = canonical->arg4; + gst->guest_r6 = canonical->arg5; + gst->guest_r7 = canonical->arg6; + #else # error "putSyscallArgsIntoGuestState: unknown arch" #endif @@ -842,6 +872,11 @@ void getSyscallStatusFromGuestState ( /*OUT*/SyscallStatus* canonical, ); canonical->what = SsComplete; +# elif defined(VGP_s390x_linux) + VexGuestS390XState* gst = (VexGuestS390XState*)gst_vanilla; + canonical->sres = VG_(mk_SysRes_s390x_linux)( gst->guest_r2 ); + canonical->what = SsComplete; + # else # error "getSyscallStatusFromGuestState: unknown arch" # endif @@ -1016,6 +1051,15 @@ void putSyscallStatusIntoGuestState ( /*IN*/ ThreadId tid, break; } +# elif defined(VGP_s390x_linux) + VexGuestS390XState* gst = (VexGuestS390XState*)gst_vanilla; + vg_assert(canonical->what == SsComplete); + if (sr_isError(canonical->sres)) { + gst->guest_r2 = - (Long)sr_Err(canonical->sres); + } else { + gst->guest_r2 = sr_Res(canonical->sres); + } + # else # error "putSyscallStatusIntoGuestState: unknown arch" # endif @@ -1129,6 +1173,16 @@ void getSyscallArgLayout ( /*OUT*/SyscallArgLayout* layout ) layout->s_arg7 = sizeof(UWord) * 1; layout->s_arg8 = sizeof(UWord) * 2; +#elif defined(VGP_s390x_linux) + layout->o_sysno = OFFSET_s390x_SYSNO; + layout->o_arg1 = OFFSET_s390x_r2; + layout->o_arg2 = OFFSET_s390x_r3; + layout->o_arg3 = OFFSET_s390x_r4; + layout->o_arg4 = OFFSET_s390x_r5; + layout->o_arg5 = OFFSET_s390x_r6; + layout->o_arg6 = OFFSET_s390x_r7; + layout->uu_arg7 = -1; /* impossible value */ + layout->uu_arg8 = -1; /* impossible value */ #else # error "getSyscallLayout: unknown arch" #endif @@ -1957,6 +2011,23 @@ void ML_(fixup_guest_state_to_restart_syscall) ( ThreadArchState* arch ) // DDD: #warning GrP fixme amd64 restart unimplemented vg_assert(0); +#elif defined(VGP_s390x_linux) + arch->vex.guest_IA -= 2; // sizeof(syscall) + + /* Make sure our caller is actually sane, and we're really backing + back over a syscall. + + syscall == 0A <num> + */ + { + UChar *p = (UChar *)arch->vex.guest_IA; + if (p[0] != 0x0A) + VG_(message)(Vg_DebugMsg, + "?! restarting over syscall at %#llx %02x %02x\n", + arch->vex.guest_IA, p[0], p[1]); + + vg_assert(p[0] == 0x0A); + } #else # error "ML_(fixup_guest_state_to_restart_syscall): unknown plat" #endif |