mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-12 22:24:53 +00:00
- Broke part of m_scheduler off into a new module m_threadstate. It contains ThreadState, VG_(threads)[] and some basic operations on the thread table. All simple stuff, the complex stuff stays in m_scheduler. This avoids lots of circular dependencies between m_scheduler and other modules. - Managed to finally remove core.h and tool.h, double hurrah! - Introduced pub_tool_basics.h and pub_core_basics.h, one of which is include by every single C file. - Lots of little cleanups and changes related to the above. - I even did a small amount of documentation updating. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3944
164 lines
5.2 KiB
C
164 lines
5.2 KiB
C
|
|
/*--------------------------------------------------------------------*/
|
|
/*--- 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 "pub_core_basics.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.
|
|
------------------------------------------------------------------ */
|
|
|
|
static UWord do_syscall_WRK (
|
|
UWord syscall_no,
|
|
UWord a1, UWord a2, UWord a3,
|
|
UWord a4, UWord a5, UWord 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 ---*/
|
|
/*--------------------------------------------------------------------*/
|