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 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_syscall.c b/coregrind/m_syscall.c
new file mode 100644
index 0000000..3a24fb7
--- /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 ---*/
+/*--------------------------------------------------------------------*/