vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | Refs

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:
src/libvx32/Makefrag | 4++++
src/libvx32/emu.c | 4++--
src/libvx32/linux-asm.S | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
src/libvx32/linux.c | 12++++--------
src/libvx32/vx32impl.h | 5++++-
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;