#include "core_asm.h" // asm stuff
#include "tool.h" // tool stuff
-#include "core_arch.h" // arch-specific stuff; eg. x86/arch.h
+#include "core_arch.h" // arch-specific stuff, eg. x86/core_arch.h
+#include "core_platform.h" // platform-specific stuff,
+ // eg. x86-linux/core_platform.h
#include "valgrind.h"
anywhere else, except that we can make some assertions about
the proxy and machine state here. */
vg_assert(px->state == PXS_RunSyscall);
- vg_assert(px->tst->arch.m_eax == -VKI_ERESTARTSYS);
+ vg_assert(PLATFORM_SYSCALL_RET(px->tst->arch) == -VKI_ERESTARTSYS);
} else if (sys_after <= eip && eip <= sys_done) {
/* We're after the syscall. Either it was interrupted by the
signal, or the syscall completed normally. In either case
vg_assert(px->state == PXS_RunSyscall ||
px->state == PXS_SysDone);
px->state = PXS_SysDone;
- px->tst->arch.m_eax = eax;
+ PLATFORM_SYSCALL_RET(px->tst->arch) = eax;
}
px_printf(" signalled in state %s\n", pxs_name(px->state));
*/
reply.u.syscallno = tst->syscallno;
- tst->arch.m_eax = -VKI_ERESTARTSYS;
+ PLATFORM_SYSCALL_RET(tst->arch) = -VKI_ERESTARTSYS;
px->state = PXS_IntReply;
break;
*/
px_printf("RunSyscall in SigACK: rejecting syscall %d with ERESTARTSYS\n",
reply.u.syscallno);
- tst->arch.m_eax = -VKI_ERESTARTSYS;
+ PLATFORM_SYSCALL_RET(tst->arch) = -VKI_ERESTARTSYS;
} else {
Int syscallno = tst->syscallno;
px->state = PXS_RunSyscall;
/* If we're interrupted before we get to the syscall
itself, we want the syscall restarted. */
- tst->arch.m_eax = -VKI_ERESTARTSYS;
+ PLATFORM_SYSCALL_RET(tst->arch) = -VKI_ERESTARTSYS;
/* set our process group ID to match parent */
if (VG_(getpgrp)() != VG_(main_pgrp))
case PX_RunSyscall:
if (VG_(clo_trace_syscalls))
VG_(message)(Vg_DebugMsg, "sys_wait_results: got PX_RunSyscall for TID %d: syscall %d result %d",
- res.tid, tst->syscallno, tst->arch.m_eax);
+ res.tid, tst->syscallno,
+ PLATFORM_SYSCALL_RET(tst->arch));
if (tst->status != VgTs_WaitSys)
VG_(printf)("tid %d in status %d\n",
req.request = PX_RunSyscall;
- tst->syscallno = tst->arch.m_eax;
- tst->arch.m_eax = -VKI_ERESTARTSYS;
+ tst->syscallno = PLATFORM_SYSCALL_NUM(tst->arch);
+ PLATFORM_SYSCALL_RET(tst->arch) = -VKI_ERESTARTSYS;
res = VG_(write)(proxy->topx, &req, sizeof(req));
return;
if (VG_(threads)[tid].status == VgTs_Sleeping
- && VG_(threads)[tid].arch.m_eax == __NR_nanosleep) {
+ && PLATFORM_SYSCALL_NUM(VG_(threads)[tid].arch) == __NR_nanosleep) {
/* We interrupted a nanosleep(). The right thing to do is to
write the unused time to nanosleep's second param, but that's
too much effort ... we just say that 1 nanosecond was not
used, and return EINTR. */
- rem = (struct vki_timespec *)VG_(threads)[tid].arch.m_ecx; /* arg2 */
+ rem = (struct vki_timespec*)PLATFORM_SYSCALL_ARG2(VG_(threads)[tid].arch);
if (rem != NULL) {
rem->tv_sec = 0;
rem->tv_nsec = 1;
vg_assert(VG_(is_valid_tid)(tid));
vg_assert(VG_(threads)[tid].status == VgTs_Runnable);
- syscall_no = VG_(threads)[tid].arch.m_eax; /* syscall number */
+ syscall_no = PLATFORM_SYSCALL_NUM(VG_(threads)[tid].arch);
/* Special-case nanosleep because we can. But should we?
if (0 && syscall_no == __NR_nanosleep) {
UInt t_now, t_awaken;
struct vki_timespec* req;
- req = (struct vki_timespec*)VG_(threads)[tid].arch.m_ebx; /* arg1 */
+ req = (struct vki_timespec*)PLATFORM_SYSCALL_ARG1(VG_(threads)[tid].arch);
if (req->tv_sec < 0 || req->tv_nsec < 0 || req->tv_nsec >= 1000000000) {
SET_SYSCALL_RETVAL(tid, -VKI_EINVAL);
__libc_freeres does some invalid frees which crash
the unprotected malloc/free system. */
- if (VG_(threads)[tid].arch.m_eax == __NR_exit
- || VG_(threads)[tid].arch.m_eax == __NR_exit_group
+ if (PLATFORM_SYSCALL_NUM(VG_(threads)[tid].arch) == __NR_exit
+ || PLATFORM_SYSCALL_NUM(VG_(threads)[tid].arch) == __NR_exit_group
) {
/* If __NR_exit, remember the supplied argument. */
- *exitcode = VG_(threads)[tid].arch.m_ebx; /* syscall arg1 */
+ *exitcode = PLATFORM_SYSCALL_ARG1(VG_(threads)[tid].arch);
/* Only run __libc_freeres if the tool says it's ok and
it hasn't been overridden with --run-libc-freeres=no
}
/* We've dealt with __NR_exit at this point. */
- vg_assert(VG_(threads)[tid].arch.m_eax != __NR_exit &&
- VG_(threads)[tid].arch.m_eax != __NR_exit_group);
+ vg_assert(PLATFORM_SYSCALL_NUM(VG_(threads)[tid].arch) != __NR_exit &&
+ PLATFORM_SYSCALL_NUM(VG_(threads)[tid].arch) != __NR_exit_group);
/* Trap syscalls to __NR_sched_yield and just have this
thread yield instead. Not essential, just an
optimisation. */
- if (VG_(threads)[tid].arch.m_eax == __NR_sched_yield) {
+ if (PLATFORM_SYSCALL_NUM(VG_(threads)[tid].arch) == __NR_sched_yield) {
SET_SYSCALL_RETVAL(tid, 0); /* syscall returns with success */
goto stage1; /* find a new thread to run */
}
Addr m_esp;
vg_assert(VG_(is_valid_tid)(tid));
- ss = (vki_kstack_t*)(VG_(threads)[tid].arch.m_ebx);
- oss = (vki_kstack_t*)(VG_(threads)[tid].arch.m_ecx);
+ ss = (vki_kstack_t*)(PLATFORM_SYSCALL_ARG1(VG_(threads)[tid].arch));
+ oss = (vki_kstack_t*)(PLATFORM_SYSCALL_ARG2(VG_(threads)[tid].arch));
m_esp = VG_(threads)[tid].arch.m_esp;
if (VG_(clo_trace_signals))
vg_assert(is_correct_sigmask());
vg_assert(VG_(is_valid_tid)(tid));
- signo = VG_(threads)[tid].arch.m_ebx; /* int sigNo */
- new_act = (vki_ksigaction*)(VG_(threads)[tid].arch.m_ecx);
- old_act = (vki_ksigaction*)(VG_(threads)[tid].arch.m_edx);
+ signo = PLATFORM_SYSCALL_ARG1(VG_(threads)[tid].arch);
+ new_act = (vki_ksigaction*)PLATFORM_SYSCALL_ARG2(VG_(threads)[tid].arch);
+ old_act = (vki_ksigaction*)PLATFORM_SYSCALL_ARG3(VG_(threads)[tid].arch);
if (VG_(clo_trace_signals))
VG_(message)(Vg_DebugExtraMsg,
if (tst->status == VgTs_WaitSys) {
/* blocked in a syscall; we assume it should be interrupted */
- if (tst->arch.m_eax == -VKI_ERESTARTSYS)
- tst->arch.m_eax = -VKI_EINTR;
+ if (PLATFORM_SYSCALL_RET(tst->arch) == -VKI_ERESTARTSYS)
+ PLATFORM_SYSCALL_RET(tst->arch) = -VKI_EINTR;
}
VG_(proxy_sigack)(tid, &tst->sig_mask);
#define POSTALIAS(new, old) \
POST(new) __attribute__((alias(STR(after_##old))))
-#define SYSNO (tst->arch.m_eax) /* in PRE(x) */
-#define res (tst->arch.m_eax) /* in POST(x) */
-#define arg1 (tst->arch.m_ebx)
-#define arg2 (tst->arch.m_ecx)
-#define arg3 (tst->arch.m_edx)
-#define arg4 (tst->arch.m_esi)
-#define arg5 (tst->arch.m_edi)
-#define arg6 (tst->arch.m_ebp)
+#define SYSNO PLATFORM_SYSCALL_NUM(tst->arch) // in PRE(x)
+#define res PLATFORM_SYSCALL_RET(tst->arch) // in POST(x)
+#define arg1 PLATFORM_SYSCALL_ARG1(tst->arch)
+#define arg2 PLATFORM_SYSCALL_ARG2(tst->arch)
+#define arg3 PLATFORM_SYSCALL_ARG3(tst->arch)
+#define arg4 PLATFORM_SYSCALL_ARG4(tst->arch)
+#define arg5 PLATFORM_SYSCALL_ARG5(tst->arch)
+#define arg6 PLATFORM_SYSCALL_ARG6(tst->arch)
PRE(exit_group)
{
AM_CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O -fomit-frame-pointer -g
noinst_HEADERS = \
+ core_platform.h \
vki_unistd.h
--- /dev/null
+
+/*--------------------------------------------------------------------*/
+/*--- x86-Linux-specific stuff for the core. ---*/
+/*--- x86-linux/core_platform.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, an extensible x86 protected-mode
+ emulator for monitoring program execution on x86-Unixes.
+
+ Copyright (C) 2000-2004 Nicholas Nethercote
+ njn25@cam.ac.uk
+
+ 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 __X86_LINUX_CORE_PLATFORM_H
+#define __X86_LINUX_CORE_PLATFORM_H
+
+//#include "core_platform_asm.h" // platform-specific asm stuff
+//#include "platform_arch.h" // platform-specific tool stuff
+
+/* ---------------------------------------------------------------------
+ Interesting registers
+ ------------------------------------------------------------------ */
+
+// Accessors for the arch_thread_t
+#define PLATFORM_SYSCALL_NUM(regs) ((regs).m_eax)
+#define PLATFORM_SYSCALL_RET(regs) ((regs).m_eax)
+#define PLATFORM_SYSCALL_ARG1(regs) ((regs).m_ebx)
+#define PLATFORM_SYSCALL_ARG2(regs) ((regs).m_ecx)
+#define PLATFORM_SYSCALL_ARG3(regs) ((regs).m_edx)
+#define PLATFORM_SYSCALL_ARG4(regs) ((regs).m_esi)
+#define PLATFORM_SYSCALL_ARG5(regs) ((regs).m_edi)
+#define PLATFORM_SYSCALL_ARG6(regs) ((regs).m_ebp)
+
+#define PLATFORM_PRE_SYSCALL_RESULT(regs, val) ((regs).m_eax = (val))
+
+// Interesting register numbers
+#define R_SYSCALL_NUM R_EAX
+#define R_SYSCALL_ARG1 R_EBX
+#define R_SYSCALL_RET R_EAX
+
+#endif // __X86_LINUX_CORE_PLATFORM_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
-/*--- Arch-specific stuff for the core. x86/core_arch.h ---*/
+/*--- x86-specific stuff for the core. x86/core_arch.h ---*/
/*--------------------------------------------------------------------*/
/*