commit d310b6b9fb6a6310f566a854538a05f269a27080
parent f042e1f5454c68291e03d96be8a4e2f19cbdf1b3
Author: Russ Cox <rsc@swtch.com>
Date: Sat, 28 Jun 2008 21:37:44 -0400
libvx32/Linux: switch to vx32_getcontext
Diffstat:
5 files changed, 65 insertions(+), 11 deletions(-)
diff --git a/src/libvx32/Makefrag b/src/libvx32/Makefrag
@@ -8,6 +8,10 @@ ifeq ($(OS),darwin)
VX32_RUN := $(VX32_RUN) darwin-asm.o
endif
+ifeq ($(OS),linux)
+VX32_RUN := $(VX32_RUN) linux-asm.o
+endif
+
VX32_OBJS = \
$(addprefix libvx32/, \
chunk.o \
diff --git a/src/libvx32/emu.c b/src/libvx32/emu.c
@@ -1801,9 +1801,9 @@ int vxproc_run(struct vxproc *vxp)
emu->trapenv = &env;
if(vx32_getcontext(&env)){
#else
- sigjmp_buf env;
+ mcontext_t env;
emu->trapenv = &env;
- if(sigsetjmp(env, 1)){
+ if(vx32_getcontext(&env)){
#endif
if(vx32_debugxlate) vxprint("VX trap %x err %x va %08x "
"veip %08x veflags %08x\n",
diff --git a/src/libvx32/linux-asm.S b/src/libvx32/linux-asm.S
@@ -0,0 +1,51 @@
+// Context routines for Linux
+
+// vx32_getcontext(struct mcontext_t *ss);
+// see /usr/include/sys/ucontext.h for layout.
+// notice that we don't set the floating-point state.
+// notice also that unlike the linux getcontext,
+// we *do* copy the segment registers
+
+.globl vx32_getcontext
+vx32_getcontext:
+ movl 4(%esp), %eax
+
+ movl %ecx, 40(%eax)
+ movl $0, %ecx
+ movw %gs, %cx
+ movl %ecx, 0(%eax)
+ movw %fs, %cx
+ movl %ecx, 4(%eax)
+ movw %es, %cx
+ movl %ecx, 8(%eax)
+ movw %ds, %cx
+ movl %ecx, 12(%eax)
+ movl %edi, 16(%eax)
+ movl %esi, 20(%eax)
+ movl %ebp, 24(%eax)
+ /* 28(%eax) is esp */
+ movl %ebx, 32(%eax)
+ movl %edx, 36(%eax)
+ /* 40(%eax) is ecx, saved above */
+ movl $1, 44(%eax) /* eax */
+ movl $0, 48(%eax) /* trapno */
+ movl $0, 52(%eax) /* err */
+ /* 56(%eax) is eip */
+ movw %cs, %cx
+ movl %ecx, 60(%eax)
+ pushfl
+ popl 64(%eax)
+ /* 68(%eax) is another esp */
+ movw %ss, %cx
+ movl %ecx, 72(%eax)
+
+ movl 0(%esp), %ecx /* %eip */
+ movl %ecx, 56(%eax)
+ leal 4(%esp), %ecx /* %esp */
+ movl %ecx, 28(%eax)
+ movl %ecx, 68(%eax)
+
+ movl 40(%eax), %ecx /* restore %ecx */
+ movl $0, %eax
+ ret
+
diff --git a/src/libvx32/linux.c b/src/libvx32/linux.c
@@ -1,10 +1,12 @@
// Code specific to x86 hosts running Linux.
+#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <assert.h>
#include <ucontext.h>
+#include <sys/ucontext.h>
#include <asm/ldt.h>
#include "vx32.h"
@@ -319,14 +321,8 @@ int vx32_sighandler(int signo, siginfo_t *si, void *v)
return 0;
emu->cpu.traperr = ctx->err;
emu->cpu.trapva = ctx->cr2;
-
- /*
- * Linux helpfully reset the floating point state
- * before entering the signal hander, so change it back.
- */
- if(ctx->fpstate)
- fprestore(ctx->fpstate);
- siglongjmp(*emu->trapenv, 1);
+ memmove(mc->gregs, emu->trapenv->gregs, 19*4);
+ return 1;
}
// The signal handler is confused; so are we.
diff --git a/src/libvx32/vx32impl.h b/src/libvx32/vx32impl.h
@@ -119,6 +119,9 @@ typedef struct vxentry {
struct i386_thread_state;
int vx32_getcontext(struct i386_thread_state*);
#endif
+#ifdef __linux__
+int vx32_getcontext(mcontext_t*);
+#endif
// Emulation state for vx32-to-x86 translation.
// This is the header for a variable-length structure;
@@ -156,7 +159,7 @@ struct vxemu {
uint32_t saved_trap; // trap to trigger after single-step
int nsinglestep;
-#if defined(__FreeBSD__)
+#if defined(__FreeBSD__) || defined(__linux__)
mcontext_t *trapenv;
#elif defined(__APPLE__)
struct i386_thread_state *trapenv;