From: Nicholas Nethercote Date: Fri, 17 Jun 2005 21:31:45 +0000 (+0000) Subject: Moved the basic syscall stuff out of m_libcbase.c into a new module X-Git-Tag: svn/VALGRIND_3_0_0~396 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=cfbf606ac57873bc5c62b8ff8b3e570034048cbc;p=thirdparty%2Fvalgrind.git Moved the basic syscall stuff out of m_libcbase.c into a new module m_syscall.c. Plus some associated cleanups. Moved VG_(sigreturn) into m_signals.c and made it local. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3922 --- diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am index 213de7761a..c9d65249ba 100644 --- a/coregrind/Makefile.am +++ b/coregrind/Makefile.am @@ -114,6 +114,7 @@ stage2_SOURCES = \ m_signals.c \ m_skiplist.c \ m_stacktrace.c \ + m_syscall.c \ m_threadmodel.c \ m_tooliface.c \ m_translate.c \ diff --git a/coregrind/core.h b/coregrind/core.h index ba956aa7f1..febb40dd32 100644 --- a/coregrind/core.h +++ b/coregrind/core.h @@ -63,12 +63,6 @@ A synonym for exit. */ #define VG_USERREQ__LIBC_FREERES_DONE 0x3029 -/* --------------------------------------------------------------------- - Exports of vg_syscall.S - ------------------------------------------------------------------ */ - -extern void VG_(sigreturn)(void); - /* --------------------------------------------------------------------- Exports of vg_helpers.S ------------------------------------------------------------------ */ diff --git a/coregrind/m_aspacemgr/aspacemgr.c b/coregrind/m_aspacemgr/aspacemgr.c index def6a4180d..a1eaf4447f 100644 --- a/coregrind/m_aspacemgr/aspacemgr.c +++ b/coregrind/m_aspacemgr/aspacemgr.c @@ -40,6 +40,7 @@ #include "pub_core_libcproc.h" #include "pub_core_mallocfree.h" #include "pub_core_options.h" +#include "pub_core_syscall.h" #include "pub_core_syscalls.h" #include "pub_core_tooliface.h" #include "pub_core_transtab.h" diff --git a/coregrind/m_libcassert.c b/coregrind/m_libcassert.c index dea4f053f9..d5825bdd21 100644 --- a/coregrind/m_libcassert.c +++ b/coregrind/m_libcassert.c @@ -35,6 +35,7 @@ #include "pub_core_libcproc.h" #include "pub_core_main.h" #include "pub_core_stacktrace.h" +#include "pub_core_syscall.h" #include "pub_core_tooliface.h" #include "vki_unistd.h" diff --git a/coregrind/m_libcbase.c b/coregrind/m_libcbase.c index 25884b5dd4..1ab10d37d8 100644 --- a/coregrind/m_libcbase.c +++ b/coregrind/m_libcbase.c @@ -471,95 +471,6 @@ void VG_(ssort)( void* base, SizeT nmemb, SizeT size, #undef SORT } -/* --------------------------------------------------------------------- - A function for doing syscalls. - ------------------------------------------------------------------ */ - -#if defined(VGP_x86_linux) -extern UInt do_syscall_x86_linux_WRK ( - UInt syscall_no, - UInt a1, UInt a2, UInt a3, - UInt a4, UInt a5, UInt a6 - ); -asm( -"do_syscall_x86_linux_WRK:\n" -" push %esi\n" -" push %edi\n" -" push %ebx\n" -" push %ebp\n" -" movl 16+ 4(%esp),%eax\n" -" movl 16+ 8(%esp),%ebx\n" -" movl 16+12(%esp),%ecx\n" -" movl 16+16(%esp),%edx\n" -" movl 16+20(%esp),%esi\n" -" movl 16+24(%esp),%edi\n" -" movl 16+28(%esp),%ebp\n" -" int $0x80\n" -" popl %ebp\n" -" popl %ebx\n" -" popl %edi\n" -" popl %esi\n" -" ret\n" -); -#endif - - -#if defined(VGP_amd64_linux) -/* Perform a Linux syscall with the "syscall" instruction. - - Incoming args (syscall number + up to 6 args) come in %rdi, %rsi, - %rdx, %rcx, %r8, %r9, and the last one on the stack (ie. the C - calling convention). - - They are passed to the syscall in the regs %rdi, %rsi, %rdx, %r10, - %r8, %r9 (yes, really %r10, not %rcx), ie. the kernel's syscall - calling convention. - - %rax holds the syscall number and gets the return value. %rcx and - %r11 are clobbered by the syscall; no matter, they are caller-save - (the syscall clobbers no callee-save regs, so we don't have to do - any register saving/restoring). -*/ -extern ULong do_syscall_amd64_linux_WRK ( - ULong syscall_no, - ULong a1, ULong a2, ULong a3, - ULong a4, ULong a5, ULong a6 - ); -asm( -"do_syscall_amd64_linux_WRK:\n" - /* Convert function calling convention --> syscall calling - convention */ -" movq %rdi, %rax\n" -" movq %rsi, %rdi\n" -" movq %rdx, %rsi\n" -" movq %rcx, %rdx\n" -" movq %r8, %r10\n" -" movq %r9, %r8\n" -" movq 8(%rsp), %r9\n" /* last arg from stack */ -" syscall\n" -" ret\n" -); -#endif - - -SysRes VG_(do_syscall) ( UWord sysno, UWord a1, UWord a2, UWord a3, - UWord a4, UWord a5, UWord a6 ) -{ - SysRes res; - -#if defined(VGP_x86_linux) - UInt eax = do_syscall_x86_linux_WRK(sysno,a1,a2,a3,a4,a5,a6); - res = VG_(mk_SysRes_x86_linux)( eax ); -#elif defined(VGP_amd64_linux) - ULong rax = do_syscall_amd64_linux_WRK(sysno,a1,a2,a3,a4,a5,a6); - res = VG_(mk_SysRes_amd64_linux)( rax ); -#else -# error VG_(do_syscall): unimplemented on this platform -#endif - - return res; -} - /*--------------------------------------------------------------------*/ /*--- end ---*/ /*--------------------------------------------------------------------*/ diff --git a/coregrind/m_libcfile.c b/coregrind/m_libcfile.c index 3a044f5ec1..aa217b2ed9 100644 --- a/coregrind/m_libcfile.c +++ b/coregrind/m_libcfile.c @@ -34,6 +34,7 @@ #include "pub_core_libcfile.h" #include "pub_core_mallocfree.h" #include "pub_core_options.h" +#include "pub_core_syscall.h" #include "vki_unistd.h" /* --------------------------------------------------------------------- diff --git a/coregrind/m_libcmman.c b/coregrind/m_libcmman.c index fc5e44f24d..d3c66f1b03 100644 --- a/coregrind/m_libcmman.c +++ b/coregrind/m_libcmman.c @@ -35,6 +35,7 @@ #include "pub_core_libcmman.h" #include "pub_core_libcprint.h" #include "pub_core_libcproc.h" +#include "pub_core_syscall.h" #include "vki_unistd.h" SysRes VG_(mmap_native)(void *start, SizeT length, UInt prot, UInt flags, diff --git a/coregrind/m_libcproc.c b/coregrind/m_libcproc.c index 021ff4eb8c..bb6997cdbb 100644 --- a/coregrind/m_libcproc.c +++ b/coregrind/m_libcproc.c @@ -34,6 +34,7 @@ #include "pub_core_libcprint.h" #include "pub_core_libcproc.h" #include "pub_core_mallocfree.h" +#include "pub_core_syscall.h" #include "vki_unistd.h" /* --------------------------------------------------------------------- diff --git a/coregrind/m_libcsignal.c b/coregrind/m_libcsignal.c index 3e1beccf97..b62e4887d7 100644 --- a/coregrind/m_libcsignal.c +++ b/coregrind/m_libcsignal.c @@ -32,6 +32,7 @@ #include "pub_core_libcbase.h" #include "pub_core_libcassert.h" #include "pub_core_libcsignal.h" +#include "pub_core_syscall.h" #include "vki_unistd.h" /* sigemptyset, sigfullset, sigaddset and sigdelset return 0 on diff --git a/coregrind/m_scheduler/scheduler.c b/coregrind/m_scheduler/scheduler.c index 49b07e015d..4aa625fd83 100644 --- a/coregrind/m_scheduler/scheduler.c +++ b/coregrind/m_scheduler/scheduler.c @@ -77,6 +77,7 @@ #include "pub_core_scheduler.h" #include "pub_core_signals.h" #include "pub_core_stacktrace.h" +#include "pub_core_syscall.h" #include "pub_core_syscalls.h" #include "pub_core_tooliface.h" #include "pub_core_translate.h" diff --git a/coregrind/m_signals.c b/coregrind/m_signals.c index e67debb0c1..34ceaf30ff 100644 --- a/coregrind/m_signals.c +++ b/coregrind/m_signals.c @@ -96,8 +96,10 @@ #include "pub_core_signals.h" #include "pub_core_sigframe.h" #include "pub_core_stacktrace.h" +#include "pub_core_syscall.h" #include "pub_core_syscalls.h" #include "pub_core_tooliface.h" +#include "vki_unistd.h" /* Define to give more sanity checking for signals. */ @@ -131,7 +133,7 @@ typedef struct SigQueue { # define VGP_UCONTEXT_SYSCALL_NUM(uc) ((uc)->uc_mcontext.eax) # define VGP_UCONTEXT_SYSCALL_SYSRES(uc) \ /* Convert the value in uc_mcontext.eax into a SysRes. */ \ - VG_(mk_SysRes_x86_linux)( (uc)->uc_mcontext.eax ) + VG_(mk_SysRes)( (uc)->uc_mcontext.eax ) #elif defined(VGP_amd64_linux) # define VGP_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_mcontext.rip) @@ -140,7 +142,7 @@ typedef struct SigQueue { # define VGP_UCONTEXT_SYSCALL_NUM(uc) ((uc)->uc_mcontext.rax) # define VGP_UCONTEXT_SYSCALL_SYSRES(uc) \ /* Convert the value in uc_mcontext.rax into a SysRes. */ \ - VG_(mk_SysRes_amd64_linux)( (uc)->uc_mcontext.rax ) + VG_(mk_SysRes)( (uc)->uc_mcontext.rax ) #elif defined(VGP_arm_linux) # define VGP_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_mcontext.arm_pc) @@ -379,6 +381,30 @@ void calculate_SKSS_from_SCSS ( SKSS* dst ) After a possible SCSS change, update SKSS and the kernel itself. ------------------------------------------------------------------ */ +// We need two levels of macro-expansion here to convert __NR_rt_sigreturn +// to a number before converting it to a string... sigh. +extern void my_sigreturn(void); + +#if defined(VGP_x86_linux) +# define _MYSIG(name) \ + "my_sigreturn:\n" \ + " movl $" #name ", %eax\n" \ + " int $0x80\n" +#elif defined(VGP_amd64_linux) +# define _MYSIG(name) \ + "my_sigreturn:\n" \ + " movq $" #name ", %rax\n" \ + " syscall\n" +#else +# error Unknown platform +#endif + +#define MYSIG(name) _MYSIG(name) +asm( + MYSIG(__NR_rt_sigreturn) +); + + static void handle_SCSS_change ( Bool force_update ) { Int res, sig; @@ -409,7 +435,7 @@ static void handle_SCSS_change ( Bool force_update ) ksa.ksa_handler = skss.skss_per_sig[sig].skss_handler; ksa.sa_flags = skss.skss_per_sig[sig].skss_flags; - ksa.sa_restorer = VG_(sigreturn); + ksa.sa_restorer = my_sigreturn; /* block all signals in handler */ VG_(sigfillset)( &ksa.sa_mask ); @@ -437,7 +463,7 @@ static void handle_SCSS_change ( Bool force_update ) vg_assert(ksa_old.sa_flags == skss_old.skss_per_sig[sig].skss_flags); vg_assert(ksa_old.sa_restorer - == VG_(sigreturn)); + == my_sigreturn); VG_(sigaddset)( &ksa_old.sa_mask, VKI_SIGKILL ); VG_(sigaddset)( &ksa_old.sa_mask, VKI_SIGSTOP ); vg_assert(VG_(isfullsigset)( &ksa_old.sa_mask )); diff --git a/coregrind/m_syscall.c b/coregrind/m_syscall.c new file mode 100644 index 0000000000..3a24fb73c6 --- /dev/null +++ b/coregrind/m_syscall.c @@ -0,0 +1,163 @@ + +/*--------------------------------------------------------------------*/ +/*--- Doing syscalls. m_syscall.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#include "core.h" +#include "pub_core_syscall.h" + +/* --------------------------------------------------------------------- + Building syscall return values. + ------------------------------------------------------------------ */ + +/* Make a SysRes value from an syscall return value. This is + Linux-specific. + + From: + http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/unix/sysv/ + linux/i386/sysdep.h? + rev=1.28&content-type=text/x-cvsweb-markup&cvsroot=glibc + + Linux uses a negative return value to indicate syscall errors, + unlike most Unices, which use the condition codes' carry flag. + + Since version 2.1 the return value of a system call might be + negative even if the call succeeded. E.g., the 'lseek' system call + might return a large offset. Therefore we must not anymore test + for < 0, but test for a real error by making sure the value in %eax + is a real error number. Linus said he will make sure the no + syscall returns a value in -1 .. -4095 as a valid result so we can + safely test with -4095. +*/ +SysRes VG_(mk_SysRes) ( UWord val ) { + SysRes res; +#if defined(VGP_x86_linux) + res.isError = val >= -4095 && val <= -1; + res.val = res.isError ? -val : val; +#elif defined(VGP_amd64_linux) + res.isError = val >= -4095 && val <= -1; + res.val = res.isError ? -val : val; +#else +# error Unknown platform +#endif + return res; +} + +SysRes VG_(mk_SysRes_Error) ( UWord val ) { + SysRes r = { val, True }; + return r; +} + +SysRes VG_(mk_SysRes_Success) ( UWord val ) { + SysRes r = { val, False }; + return r; +} + + +/* --------------------------------------------------------------------- + A function for doing syscalls. + ------------------------------------------------------------------ */ + +extern UInt do_syscall_WRK ( + UInt syscall_no, + UInt a1, UInt a2, UInt a3, + UInt a4, UInt a5, UInt a6 + ); +#if defined(VGP_x86_linux) +/* Incoming args (syscall number + up to 6 args) come on the stack. + (ie. the C calling convention). + + The syscall number goes in %eax. The args are passed to the syscall in + the regs %ebx, %ecx, %edx, %esi, %edi, %ebp, ie. the kernel's syscall + calling convention. + + %eax gets the return value. Not sure which registers the kernel + clobbers, so we preserve all the callee-save regs (%esi, %edi, %ebx, + %ebp). +*/ +asm( +"do_syscall_WRK:\n" +" push %esi\n" +" push %edi\n" +" push %ebx\n" +" push %ebp\n" +" movl 16+ 4(%esp),%eax\n" +" movl 16+ 8(%esp),%ebx\n" +" movl 16+12(%esp),%ecx\n" +" movl 16+16(%esp),%edx\n" +" movl 16+20(%esp),%esi\n" +" movl 16+24(%esp),%edi\n" +" movl 16+28(%esp),%ebp\n" +" int $0x80\n" +" popl %ebp\n" +" popl %ebx\n" +" popl %edi\n" +" popl %esi\n" +" ret\n" +); +#elif defined(VGP_amd64_linux) +/* Incoming args (syscall number + up to 6 args) come in %rdi, %rsi, + %rdx, %rcx, %r8, %r9, and the last one on the stack (ie. the C + calling convention). + + The syscall number goes in %rax. The args are passed to the syscall in + the regs %rdi, %rsi, %rdx, %r10, %r8, %r9 (yes, really %r10, not %rcx), + ie. the kernel's syscall calling convention. + + %rax gets the return value. %rcx and %r11 are clobbered by the syscall; + no matter, they are caller-save (the syscall clobbers no callee-save + regs, so we don't have to do any register saving/restoring). +*/ +asm( +"do_syscall_WRK:\n" + /* Convert function calling convention --> syscall calling + convention */ +" movq %rdi, %rax\n" +" movq %rsi, %rdi\n" +" movq %rdx, %rsi\n" +" movq %rcx, %rdx\n" +" movq %r8, %r10\n" +" movq %r9, %r8\n" +" movq 8(%rsp), %r9\n" /* last arg from stack */ +" syscall\n" +" ret\n" +); +#else +# error Unknown platform +#endif + +SysRes VG_(do_syscall) ( UWord sysno, UWord a1, UWord a2, UWord a3, + UWord a4, UWord a5, UWord a6 ) +{ + UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6); + return VG_(mk_SysRes)( val ); +} + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff --git a/coregrind/m_syscalls/syscall-amd64-linux.S b/coregrind/m_syscalls/syscall-amd64-linux.S index 419772a9f0..d2cb0e479e 100644 --- a/coregrind/m_syscalls/syscall-amd64-linux.S +++ b/coregrind/m_syscalls/syscall-amd64-linux.S @@ -33,12 +33,6 @@ #include "libvex_guest_offsets.h" -/*----------------------------------------------------------------*/ -.globl VG_(sigreturn) -VG_(sigreturn): - movq $__NR_rt_sigreturn, %rax - syscall - /*----------------------------------------------------------------*/ /* Perform a syscall for the client. This will run a syscall diff --git a/coregrind/m_syscalls/syscall-arm-linux.S b/coregrind/m_syscalls/syscall-arm-linux.S index 03370d477f..e06a1174a1 100644 --- a/coregrind/m_syscalls/syscall-arm-linux.S +++ b/coregrind/m_syscalls/syscall-arm-linux.S @@ -33,6 +33,8 @@ # XXX: must reinstate comments also -- see x86-linux/syscall.S +# XXX: this is now all way out of date... + .globl VG_(do_syscall) VG_(do_syscall): swi @@ -41,10 +43,6 @@ VG_(do_syscall): VG_(clone): swi -.globl VG_(sigreturn) -VG_(sigreturn): - swi - # ToDo XXX: Assembler did not like this... #/* Let the linker know we don't need an executable stack */ #.section .note.GNU-stack,"",@progbits diff --git a/coregrind/m_syscalls/syscall-x86-linux.S b/coregrind/m_syscalls/syscall-x86-linux.S index 81fb6abc13..bf37f33bd3 100644 --- a/coregrind/m_syscalls/syscall-x86-linux.S +++ b/coregrind/m_syscalls/syscall-x86-linux.S @@ -33,12 +33,6 @@ #include "libvex_guest_offsets.h" -/*----------------------------------------------------------------*/ -.globl VG_(sigreturn) -VG_(sigreturn): - movl $__NR_rt_sigreturn, %eax - int $0x80 - /*----------------------------------------------------------------*/ /* Perform a syscall for the client. This will run a syscall diff --git a/coregrind/m_syscalls/syscalls-amd64-linux.c b/coregrind/m_syscalls/syscalls-amd64-linux.c index 8d17b423cf..09af69f290 100644 --- a/coregrind/m_syscalls/syscalls-amd64-linux.c +++ b/coregrind/m_syscalls/syscalls-amd64-linux.c @@ -41,6 +41,7 @@ #include "pub_core_libcsignal.h" #include "pub_core_sigframe.h" #include "pub_core_signals.h" +#include "pub_core_syscall.h" #include "pub_core_syscalls.h" #include "pub_core_tooliface.h" @@ -420,7 +421,7 @@ static SysRes do_clone ( ThreadId ptid, start_thread_NORETURN, stack, flags, &VG_(threads)[ctid], child_tidptr, parent_tidptr, NULL ); - res = VG_(mk_SysRes_amd64_linux)( rax ); + res = VG_(mk_SysRes)( rax ); VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL); @@ -655,9 +656,7 @@ PRE(sys_rt_sigreturn) denote either success or failure, we must set up so that the driver logic copies it back unchanged. Also, note %RAX is of the guest registers written by VG_(sigframe_destroy). */ - SET_STATUS_from_SysRes( - VG_(mk_SysRes_amd64_linux)( tst->arch.vex.guest_RAX ) - ); + SET_STATUS_from_SysRes( VG_(mk_SysRes)( tst->arch.vex.guest_RAX ) ); /* Check to see if some any signals arose as a result of this. */ *flags |= SfPollAfter; diff --git a/coregrind/m_syscalls/syscalls-generic.c b/coregrind/m_syscalls/syscalls-generic.c index 57309a6e44..16eb7c09f1 100644 --- a/coregrind/m_syscalls/syscalls-generic.c +++ b/coregrind/m_syscalls/syscalls-generic.c @@ -44,6 +44,7 @@ #include "pub_core_tooliface.h" #include "pub_core_options.h" #include "pub_core_signals.h" +#include "pub_core_syscall.h" #include "pub_core_syscalls.h" #include "priv_types_n_macros.h" diff --git a/coregrind/m_syscalls/syscalls-linux.c b/coregrind/m_syscalls/syscalls-linux.c index cff344619b..fdf281210b 100644 --- a/coregrind/m_syscalls/syscalls-linux.c +++ b/coregrind/m_syscalls/syscalls-linux.c @@ -40,6 +40,7 @@ #include "pub_core_tooliface.h" #include "pub_core_options.h" #include "pub_core_signals.h" +#include "pub_core_syscall.h" #include "priv_types_n_macros.h" #include "priv_syscalls-generic.h" diff --git a/coregrind/m_syscalls/syscalls-main.c b/coregrind/m_syscalls/syscalls-main.c index 619a8d678d..3af41c029b 100644 --- a/coregrind/m_syscalls/syscalls-main.c +++ b/coregrind/m_syscalls/syscalls-main.c @@ -39,6 +39,7 @@ #include "pub_core_tooliface.h" #include "pub_core_options.h" #include "pub_core_signals.h" +#include "pub_core_syscall.h" #include "pub_core_syscalls.h" #include "priv_types_n_macros.h" diff --git a/coregrind/m_syscalls/syscalls-x86-linux.c b/coregrind/m_syscalls/syscalls-x86-linux.c index dacfcfc4af..37dfd9b6cf 100644 --- a/coregrind/m_syscalls/syscalls-x86-linux.c +++ b/coregrind/m_syscalls/syscalls-x86-linux.c @@ -47,6 +47,7 @@ #include "pub_core_mallocfree.h" #include "pub_core_sigframe.h" #include "pub_core_signals.h" +#include "pub_core_syscall.h" #include "pub_core_syscalls.h" #include "pub_core_tooliface.h" @@ -443,7 +444,7 @@ static SysRes do_clone ( ThreadId ptid, start_thread_NORETURN, stack, flags, &VG_(threads)[ctid], child_tidptr, parent_tidptr, NULL ); - res = VG_(mk_SysRes_x86_linux)( eax ); + res = VG_(mk_SysRes)( eax ); VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL); @@ -1142,9 +1143,7 @@ PRE(sys_sigreturn) denote either success or failure, we must set up so that the driver logic copies it back unchanged. Also, note %EAX is of the guest registers written by VG_(sigframe_destroy). */ - SET_STATUS_from_SysRes( - VG_(mk_SysRes_x86_linux)( tst->arch.vex.guest_EAX ) - ); + SET_STATUS_from_SysRes( VG_(mk_SysRes)( tst->arch.vex.guest_EAX ) ); /* Check to see if some any signals arose as a result of this. */ *flags |= SfPollAfter; @@ -1175,9 +1174,7 @@ PRE(sys_rt_sigreturn) denote either success or failure, we must set up so that the driver logic copies it back unchanged. Also, note %EAX is of the guest registers written by VG_(sigframe_destroy). */ - SET_STATUS_from_SysRes( - VG_(mk_SysRes_x86_linux)( tst->arch.vex.guest_EAX ) - ); + SET_STATUS_from_SysRes( VG_(mk_SysRes)( tst->arch.vex.guest_EAX ) ); /* Check to see if some any signals arose as a result of this. */ *flags |= SfPollAfter; diff --git a/coregrind/pub_core_libcbase.h b/coregrind/pub_core_libcbase.h index b7289dee19..5c20e8b79b 100644 --- a/coregrind/pub_core_libcbase.h +++ b/coregrind/pub_core_libcbase.h @@ -39,89 +39,6 @@ #include "pub_tool_libcbase.h" -/* --------------------------------------------------------------------- - Fundamental functions for doing syscalls on this platform. - ------------------------------------------------------------------ */ - -/* Do a syscall on this platform, with 6 args, and return the result - in canonical format in a SysRes value. */ - -// We use a full prototype for VG_(do_syscall) rather than "..." to ensure -// that all arguments get converted to a UWord appropriately. Not doing so -// can cause problems when passing 32-bit integers on 64-bit platforms, -// because the top 32-bits might not be zeroed appropriately, eg. as would -// happen with the 6th arg on AMD64 which is passed on the stack. - -extern SysRes VG_(do_syscall) ( UWord sysno, - UWord, UWord, UWord, - UWord, UWord, UWord ); - -/* Macros make life easier. */ - -#define vgPlain_do_syscall0(s) VG_(do_syscall)((s),0,0,0,0,0,0) -#define vgPlain_do_syscall1(s,a) VG_(do_syscall)((s),(a),0,0,0,0,0) -#define vgPlain_do_syscall2(s,a,b) VG_(do_syscall)((s),(a),(b),0,0,0,0) -#define vgPlain_do_syscall3(s,a,b,c) VG_(do_syscall)((s),(a),(b),(c),0,0,0) -#define vgPlain_do_syscall4(s,a,b,c,d) VG_(do_syscall)((s),(a),(b),\ - (c),(d),0,0) -#define vgPlain_do_syscall5(s,a,b,c,d,e) VG_(do_syscall)((s),(a),(b),\ - (c),(d),(e),0) -#define vgPlain_do_syscall6(s,a,b,c,d,e,f) VG_(do_syscall)((s),(a),(b),\ - (c),(d),(e),(f)) - - -/* Build SysRes values -- occasionally useful. */ - -static inline SysRes VG_(mk_SysRes_Error) ( UWord err ) { - SysRes r = { err, True }; - return r; -} - -static inline SysRes VG_(mk_SysRes_Success) ( UWord err ) { - SysRes r = { err, False }; - return r; -} - - -/* This is absolutely the wrong place for these, but I can't figure - out anywhere else for them to go. */ - -/* Make a SysRes value from an %eax syscall return value on - x86-linux. - - From: - http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/unix/sysv/ - linux/i386/sysdep.h? - rev=1.28&content-type=text/x-cvsweb-markup&cvsroot=glibc - - Linux uses a negative return value to indicate syscall errors, - unlike most Unices, which use the condition codes' carry flag. - - Since version 2.1 the return value of a system call might be - negative even if the call succeeded. E.g., the 'lseek' system call - might return a large offset. Therefore we must not anymore test - for < 0, but test for a real error by making sure the value in %eax - is a real error number. Linus said he will make sure the no - syscall returns a value in -1 .. -4095 as a valid result so we can - safely test with -4095. -*/ -static inline SysRes VG_(mk_SysRes_x86_linux) ( Int eax ) { - SysRes res; - res.isError = eax >= -4095 && eax <= -1; - res.val = res.isError ? -eax : eax; - return res; -} - -/* Similarly .. */ -static inline SysRes VG_(mk_SysRes_amd64_linux) ( Long rax ) { - SysRes res; - res.isError = rax >= -4095 && rax <= -1; - res.val = res.isError ? -rax : rax; - return res; -} - - - #endif // __PUB_CORE_LIBCBASE_H /*--------------------------------------------------------------------*/ diff --git a/coregrind/pub_core_syscall.h b/coregrind/pub_core_syscall.h new file mode 100644 index 0000000000..17c3f55e4c --- /dev/null +++ b/coregrind/pub_core_syscall.h @@ -0,0 +1,83 @@ + +/*--------------------------------------------------------------------*/ +/*--- Doing system calls. pub_core_syscall.h ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#ifndef __PUB_CORE_SYSCALL_H +#define __PUB_CORE_SYSCALL_H + +//-------------------------------------------------------------------- +// PURPOSE: This module contains the code for actually executing syscalls. +//-------------------------------------------------------------------- + +/* Do a syscall on this platform, with 6 args, and return the result + in canonical format in a SysRes value. */ + +// We use a full prototype for VG_(do_syscall) rather than "..." to ensure +// that all arguments get converted to a UWord appropriately. Not doing so +// can cause problems when passing 32-bit integers on 64-bit platforms, +// because the top 32-bits might not be zeroed appropriately, eg. as would +// happen with the 6th arg on AMD64 which is passed on the stack. + +extern SysRes VG_(do_syscall) ( UWord sysno, + UWord, UWord, UWord, + UWord, UWord, UWord ); + +/* Macros make life easier. */ + +#define vgPlain_do_syscall0(s) VG_(do_syscall)((s),0,0,0,0,0,0) +#define vgPlain_do_syscall1(s,a) VG_(do_syscall)((s),(a),0,0,0,0,0) +#define vgPlain_do_syscall2(s,a,b) VG_(do_syscall)((s),(a),(b),0,0,0,0) +#define vgPlain_do_syscall3(s,a,b,c) VG_(do_syscall)((s),(a),(b),(c),0,0,0) +#define vgPlain_do_syscall4(s,a,b,c,d) VG_(do_syscall)((s),(a),(b),\ + (c),(d),0,0) +#define vgPlain_do_syscall5(s,a,b,c,d,e) VG_(do_syscall)((s),(a),(b),\ + (c),(d),(e),0) +#define vgPlain_do_syscall6(s,a,b,c,d,e,f) VG_(do_syscall)((s),(a),(b),\ + (c),(d),(e),(f)) + +extern SysRes VG_(mk_SysRes) ( UWord val ); +extern SysRes VG_(mk_SysRes_Error) ( UWord val ); +extern SysRes VG_(mk_SysRes_Success) ( UWord val ); + +// The _WRK function is handwritten assembly. It has some very magic +// properties. See comments at the top of +// VG_(fixup_guest_state_after_syscall_interrupted) below for details. +extern +void VG_(do_syscall_for_client_WRK)( Int syscallno, + void* guest_state, + const vki_sigset_t *syscall_mask, + const vki_sigset_t *restore_mask, + Int nsigwords ); + +#endif // __PUB_CORE_SYSCALL_H + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ +