diff --git a/CMakeLists.txt b/CMakeLists.txt index cc4e5c2c..a3b5935b 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,3 +137,8 @@ add_test(test08 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/box86 -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test08 -D TEST_OUTPUT=tmpfile.txt -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref08.txt -P ${CMAKE_SOURCE_DIR}/runTest.cmake ) + +add_test(test09 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/box86 + -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test09 -D TEST_OUTPUT=tmpfile.txt + -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref09.txt + -P ${CMAKE_SOURCE_DIR}/runTest.cmake ) diff --git a/rebuild_wrappers.py b/rebuild_wrappers.py index d68e34c8..45b4f5ca 100755 --- a/rebuild_wrappers.py +++ b/rebuild_wrappers.py @@ -4,7 +4,7 @@ import os import glob import sys -values = ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'L', 'p', 'V'] +values = ['E', 'e', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'L', 'p', 'V'] def splitchar(s): ret = [len(s)] i = 0 @@ -105,7 +105,7 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc); // v = void, i = int32, u = uint32, U/I= (u)int64 // p = pointer, P = callback // f = float, d = double, D = long double, L = fake long double -// V = vaargs, E = current x86emu struct +// V = vaargs, E = current x86emu struct, e = ref to current x86emu struct // 0 = constant 0, 1 = constant 1 // o = stdout // C = unsigned byte c = char @@ -139,8 +139,8 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc); # First part: typedefs for v in gbl: - # E v c w i I C W u U f d D L p V - types = ["x86emu_t*", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "double", "void*", "void*"] + # E e v c w i I C W u U f d D L p V + types = ["x86emu_t*", "x86emu_t**", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "double", "void*", "void*"] if len(values) != len(types): raise NotImplementedError("len(values) = {lenval} != len(types) = {lentypes}".format(lenval=len(values), lentypes=len(types))) @@ -163,6 +163,7 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc); arg = [ "emu, ", # E + "&emu, ", # e "", # v "*(int8_t*)(R_ESP + {p}), ", # c "*(int16_t*)(R_ESP + {p}), ", # w @@ -179,8 +180,8 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc); "*(void**)(R_ESP + {p}), ", # p "(void*)(R_ESP + {p}), " # V ] - # E v c w i I C W u U f d D L p V - deltas = [0, 4, 4, 4, 4, 8, 4, 4, 4, 8, 4, 8, 12, 12, 4, 0] + # E e v c w i I C W u U f d D L p V + deltas = [0, 0, 4, 4, 4, 4, 8, 4, 4, 4, 8, 4, 8, 12, 12, 4, 0] if len(values) != len(arg): raise NotImplementedError("len(values) = {lenval} != len(arg) = {lenarg}".format(lenval=len(values), lenarg=len(arg))) if len(values) != len(deltas): @@ -191,6 +192,7 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc); f.write("void {0}(x86emu_t *emu, uintptr_t fcn) {2} {1} fn = ({1})fcn; ".format(N, W, "{")) vals = [ "\n#error Invalid return type: emulator\n", # E + "\n#error Invalid return type: &emulator\n", # e "fn({0});", # v "R_EAX=fn({0});", # c "R_EAX=fn({0});", # w diff --git a/src/box86context.c b/src/box86context.c index 1b35fc6b..714babfd 100755 --- a/src/box86context.c +++ b/src/box86context.c @@ -41,6 +41,9 @@ void FreeBox86Context(box86context_t** context) { if(!context) return; + + if(--(*context)->forked >= 0) + return; if((*context)->emu) FreeX86Emu(&(*context)->emu); diff --git a/src/box86context.h b/src/box86context.h index 597e5ff7..b2dca98e 100755 --- a/src/box86context.h +++ b/src/box86context.h @@ -60,6 +60,8 @@ typedef struct box86context_s { library_t *sdl2lib; // shortcut to SDL2 library (if loaded) library_t *sdl2mixerlib; library_t *sdl2imagelib; + + int forked; // how many forks... cleanup only when < 0 } box86context_t; box86context_t *NewBox86Context(int argc); diff --git a/src/elfloader.c b/src/elfloader.c index dd298b23..c8374a00 100755 --- a/src/elfloader.c +++ b/src/elfloader.c @@ -169,6 +169,8 @@ int RelocateElfREL(lib_t *maplib, elfheader_t* head, int cnt, Elf32_Rel *rel) printf_log(LOG_DEBUG, "Apply R_386_32 @%p with sym=%s (%p -> %p)\n", p, symname, *(void**)p, (void*)offs); *p = offs; break; + //case R_386_TLS_DTPMOD32: + // try to use _dl_next_tls_modid() ? case R_386_TLS_DTPOFF32: case R_386_JMP_SLOT: offs = FindGlobalSymbol(maplib, symname); @@ -350,6 +352,7 @@ void AddGlobalsSymbols(kh_mapsymbols_t* mapsymbols, elfheader_t* h) if(( (h->SymTab[i].st_info == 18) || (h->SymTab[i].st_info == 17) || (h->SymTab[i].st_info == 34) + || (h->SymTab[i].st_info == 22) || (h->SymTab[i].st_info == 2)) && (h->SymTab[i].st_other==0) && (h->SymTab[i].st_shndx!=0)) { const char * symname = h->StrTab+h->SymTab[i].st_name; @@ -365,6 +368,7 @@ void AddGlobalsSymbols(kh_mapsymbols_t* mapsymbols, elfheader_t* h) if(( (h->DynSym[i].st_info == 18) || (h->DynSym[i].st_info == 17) || (h->DynSym[i].st_info == 34) + || (h->DynSym[i].st_info == 22) || (h->DynSym[i].st_info == 2)) && (h->DynSym[i].st_other==0) && (h->DynSym[i].st_shndx!=0 && h->DynSym[i].st_shndx<62521)) { const char * symname = h->DynStr+h->DynSym[i].st_name; diff --git a/src/wrappedlibc.c b/src/wrappedlibc.c index a2f53aaa..b718f46e 100755 --- a/src/wrappedlibc.c +++ b/src/wrappedlibc.c @@ -92,13 +92,17 @@ sighandler_t EXPORT my_signal(x86emu_t* emu, int signum, sighandler_t handler) } sighandler_t EXPORT my___sysv_signal(x86emu_t* emu, int signum, sighandler_t handler) __attribute__((alias("my_signal"))); sighandler_t EXPORT my_sysv_signal(x86emu_t* emu, int signum, sighandler_t handler) __attribute__((alias("my_signal"))); -pid_t EXPORT my_fork() +pid_t EXPORT my_fork(x86emu_t* emu) { - // should be doable, but the x86emu stack has to be dedup for the child - printf_log(LOG_NONE, "Warning, Ignoring fork()\n"); - return EAGAIN; + #if 1 + emu->quit = 1; + emu->fork = 1; + return 0; + #else + return 0; + #endif } -pid_t EXPORT my___fork() __attribute__((alias("my_fork"))); +pid_t EXPORT my___fork(x86emu_t* emu) __attribute__((alias("my_fork"))); EXPORT void* my__ZGTtnaX (size_t a) { printf("warning _ZGTtnaX called\n"); return NULL; } EXPORT void my__ZGTtdlPv (void* a) { printf("warning _ZGTtdlPv called\n"); } @@ -291,6 +295,13 @@ EXPORT void my_qsort_r(x86emu_t* emu, void* base, size_t nmemb, size_t size, voi FreeCallback(cbemu); } +EXPORT int32_t my_execvp(x86emu_t* emu, void* a, void* b, va_list v) +{ + printf("execvp(%s, %p)\n", (const char*)a, b); + return execvp(a, b); +} +EXPORT int32_t my_execlp(x86emu_t* emu, void* a, void* b, va_list v) __attribute__((alias("my_execvp"))); + #define LIBNAME libc const char* libcName = "libc.so.6"; diff --git a/src/wrappedlibc_private.h b/src/wrappedlibc_private.h index db58379a..6af8e2e0 100755 --- a/src/wrappedlibc_private.h +++ b/src/wrappedlibc_private.h @@ -268,10 +268,10 @@ GO(__errno_location, pFv) // eventfd_write // execl // execle -GO2(execlp, iFppV, execvp) // is that correct? +GOM(execlp, iFEpVV) GO(execv, iFpp) // maybe need to GOM this one, and check if path is an x86 file... // execve // Weak -GO(execvp, iFpp) // same remark as for execv +GOM(execvp, iFEpVV) GOM(exit, vFEi) GOM(_exit, vFEi) // _Exit // Weak @@ -345,8 +345,8 @@ GO(fileno, iFp) GO(fopen, pFpp) GOW(fopen64, pFpp) // fopencookie -GOM(fork, pFE) // Weak -GOM(__fork, pFE) +GOM(fork, iFEv) // Weak +GOM(__fork, iFEv) // __fortify_fail // fpathconf // Weak // __fpending diff --git a/src/wrapper.c b/src/wrapper.c index 710e333f..eafc970e 100644 --- a/src/wrapper.c +++ b/src/wrapper.c @@ -24,6 +24,7 @@ typedef void (*vFu_t)(uint32_t); typedef void (*vFf_t)(float); typedef void (*vFd_t)(double); typedef void (*vFp_t)(void*); +typedef int32_t (*iFE_t)(x86emu_t*); typedef int32_t (*iFv_t)(void); typedef int32_t (*iFi_t)(int32_t); typedef int32_t (*iFu_t)(uint32_t); @@ -622,6 +623,7 @@ void vFu(x86emu_t *emu, uintptr_t fcn) { vFu_t fn = (vFu_t)fcn; fn(*(uint32_t*)( void vFf(x86emu_t *emu, uintptr_t fcn) { vFf_t fn = (vFf_t)fcn; fn(*(float*)(R_ESP + 4)); } void vFd(x86emu_t *emu, uintptr_t fcn) { vFd_t fn = (vFd_t)fcn; fn(*(double*)(R_ESP + 4)); } void vFp(x86emu_t *emu, uintptr_t fcn) { vFp_t fn = (vFp_t)fcn; fn(*(void**)(R_ESP + 4)); } +void iFE(x86emu_t *emu, uintptr_t fcn) { iFE_t fn = (iFE_t)fcn; R_EAX=fn(emu); } void iFv(x86emu_t *emu, uintptr_t fcn) { iFv_t fn = (iFv_t)fcn; R_EAX=fn(); } void iFi(x86emu_t *emu, uintptr_t fcn) { iFi_t fn = (iFi_t)fcn; R_EAX=fn(*(int32_t*)(R_ESP + 4)); } void iFu(x86emu_t *emu, uintptr_t fcn) { iFu_t fn = (iFu_t)fcn; R_EAX=fn(*(uint32_t*)(R_ESP + 4)); } @@ -1213,8 +1215,9 @@ void vFuffiiffiiffiip(x86emu_t *emu, uintptr_t fcn) { vFuffiiffiiffiip_t fn = (v void vFuddiiddiiddiip(x86emu_t *emu, uintptr_t fcn) { vFuddiiddiiddiip_t fn = (vFuddiiddiiddiip_t)fcn; fn(*(uint32_t*)(R_ESP + 4), *(double*)(R_ESP + 8), *(double*)(R_ESP + 16), *(int32_t*)(R_ESP + 24), *(int32_t*)(R_ESP + 28), *(double*)(R_ESP + 32), *(double*)(R_ESP + 40), *(int32_t*)(R_ESP + 48), *(int32_t*)(R_ESP + 52), *(double*)(R_ESP + 56), *(double*)(R_ESP + 64), *(int32_t*)(R_ESP + 72), *(int32_t*)(R_ESP + 76), *(void**)(R_ESP + 80)); } void vFuuiiiiuuiiiiiii(x86emu_t *emu, uintptr_t fcn) { vFuuiiiiuuiiiiiii_t fn = (vFuuiiiiuuiiiiiii_t)fcn; fn(*(uint32_t*)(R_ESP + 4), *(uint32_t*)(R_ESP + 8), *(int32_t*)(R_ESP + 12), *(int32_t*)(R_ESP + 16), *(int32_t*)(R_ESP + 20), *(int32_t*)(R_ESP + 24), *(uint32_t*)(R_ESP + 28), *(uint32_t*)(R_ESP + 32), *(int32_t*)(R_ESP + 36), *(int32_t*)(R_ESP + 40), *(int32_t*)(R_ESP + 44), *(int32_t*)(R_ESP + 48), *(int32_t*)(R_ESP + 52), *(int32_t*)(R_ESP + 56), *(int32_t*)(R_ESP + 60)); } void vFfffffffffffffff(x86emu_t *emu, uintptr_t fcn) { vFfffffffffffffff_t fn = (vFfffffffffffffff_t)fcn; fn(*(float*)(R_ESP + 4), *(float*)(R_ESP + 8), *(float*)(R_ESP + 12), *(float*)(R_ESP + 16), *(float*)(R_ESP + 20), *(float*)(R_ESP + 24), *(float*)(R_ESP + 28), *(float*)(R_ESP + 32), *(float*)(R_ESP + 36), *(float*)(R_ESP + 40), *(float*)(R_ESP + 44), *(float*)(R_ESP + 48), *(float*)(R_ESP + 52), *(float*)(R_ESP + 56), *(float*)(R_ESP + 60)); } -void iFEpvpVV(x86emu_t *emu, uintptr_t fcn) { iFEppVV_t fn = (iFEppVV_t)fcn; R_EAX=fn(emu, *(void**)(R_ESP + 4), *(void**)(R_ESP + 12), (void*)(R_ESP + 16), (void*)(R_ESP + 16)); } -void iFEpvvpVV(x86emu_t *emu, uintptr_t fcn) { iFEppVV_t fn = (iFEppVV_t)fcn; R_EAX=fn(emu, *(void**)(R_ESP + 4), *(void**)(R_ESP + 16), (void*)(R_ESP + 20), (void*)(R_ESP + 20)); } void iFEvpVV(x86emu_t *emu, uintptr_t fcn) { iFEpVV_t fn = (iFEpVV_t)fcn; R_EAX=fn(emu, *(void**)(R_ESP + 8), (void*)(R_ESP + 12), (void*)(R_ESP + 12)); } +void iFEv(x86emu_t *emu, uintptr_t fcn) { iFE_t fn = (iFE_t)fcn; R_EAX=fn(emu); } void pFEv(x86emu_t *emu, uintptr_t fcn) { pFE_t fn = (pFE_t)fcn; R_EAX=(uintptr_t)fn(emu); } void iFEpuvvpVV(x86emu_t *emu, uintptr_t fcn) { iFEpupVV_t fn = (iFEpupVV_t)fcn; R_EAX=fn(emu, *(void**)(R_ESP + 4), *(uint32_t*)(R_ESP + 8), *(void**)(R_ESP + 20), (void*)(R_ESP + 24), (void*)(R_ESP + 24)); } +void iFEpvpVV(x86emu_t *emu, uintptr_t fcn) { iFEppVV_t fn = (iFEppVV_t)fcn; R_EAX=fn(emu, *(void**)(R_ESP + 4), *(void**)(R_ESP + 12), (void*)(R_ESP + 16), (void*)(R_ESP + 16)); } +void iFEpvvpVV(x86emu_t *emu, uintptr_t fcn) { iFEppVV_t fn = (iFEppVV_t)fcn; R_EAX=fn(emu, *(void**)(R_ESP + 4), *(void**)(R_ESP + 16), (void*)(R_ESP + 20), (void*)(R_ESP + 20)); } diff --git a/src/wrapper.h b/src/wrapper.h index 74249c46..32f283fb 100644 --- a/src/wrapper.h +++ b/src/wrapper.h @@ -14,7 +14,7 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc); // v = void, i = int32, u = uint32, U/I= (u)int64 // p = pointer, P = callback // f = float, d = double, D = long double, L = fake long double -// V = vaargs, E = current x86emu struct +// V = vaargs, E = current x86emu struct, e = ref to current x86emu struct // 0 = constant 0, 1 = constant 1 // o = stdout // C = unsigned byte c = char @@ -29,6 +29,7 @@ void vFu(x86emu_t *emu, uintptr_t fnc); void vFf(x86emu_t *emu, uintptr_t fnc); void vFd(x86emu_t *emu, uintptr_t fnc); void vFp(x86emu_t *emu, uintptr_t fnc); +void iFE(x86emu_t *emu, uintptr_t fnc); void iFv(x86emu_t *emu, uintptr_t fnc); void iFi(x86emu_t *emu, uintptr_t fnc); void iFu(x86emu_t *emu, uintptr_t fnc); @@ -620,10 +621,11 @@ void vFuffiiffiiffiip(x86emu_t *emu, uintptr_t fnc); void vFuddiiddiiddiip(x86emu_t *emu, uintptr_t fnc); void vFuuiiiiuuiiiiiii(x86emu_t *emu, uintptr_t fnc); void vFfffffffffffffff(x86emu_t *emu, uintptr_t fnc); -void iFEpvpVV(x86emu_t *emu, uintptr_t fnc); -void iFEpvvpVV(x86emu_t *emu, uintptr_t fnc); void iFEvpVV(x86emu_t *emu, uintptr_t fnc); +void iFEv(x86emu_t *emu, uintptr_t fnc); void pFEv(x86emu_t *emu, uintptr_t fnc); void iFEpuvvpVV(x86emu_t *emu, uintptr_t fnc); +void iFEpvpVV(x86emu_t *emu, uintptr_t fnc); +void iFEpvvpVV(x86emu_t *emu, uintptr_t fnc); #endif //__WRAPPER_H_ diff --git a/src/x86emu.c b/src/x86emu.c index 8b32eb00..edbfa072 100755 --- a/src/x86emu.c +++ b/src/x86emu.c @@ -125,10 +125,42 @@ void FreeX86Emu(x86emu_t **emu) free((*emu)->scratch); + free((*emu)->stack); + free(*emu); *emu = NULL; } +void CloneEmu(x86emu_t *newemu, const x86emu_t* emu) +{ + memcpy(newemu->regs, emu->regs, sizeof(emu->regs)); + memcpy(&newemu->ip, &emu->ip, sizeof(emu->ip)); + memcpy(&newemu->eflags, &emu->eflags, sizeof(emu->eflags)); + newemu->old_ip = emu->old_ip; + memcpy(newemu->segs, emu->segs, sizeof(emu->segs)); + memcpy(newemu->fpu, emu->fpu, sizeof(emu->fpu)); + memcpy(newemu->fpu_ld, emu->fpu_ld, sizeof(emu->fpu_ld)); + memcpy(newemu->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll)); + memcpy(newemu->p_regs, emu->p_regs, sizeof(emu->p_regs)); + newemu->cw = emu->cw; + newemu->cw_mask_all = emu->cw_mask_all; + memcpy(&newemu->sw, &emu->sw, sizeof(emu->sw)); + newemu->top = emu->top; + newemu->fpu_stack = emu->fpu_stack; + memcpy(&newemu->round, &emu->round, sizeof(emu->round)); + memcpy(newemu->mmx, emu->mmx, sizeof(emu->mmx)); + memcpy(newemu->xmm, emu->xmm, sizeof(emu->xmm)); + newemu->mxcsr = emu->mxcsr; + memcpy(&newemu->zero, &emu->zero, sizeof(emu->zero)); + memcpy(newemu->sbiidx, emu->sbiidx, sizeof(emu->sbiidx)); + newemu->quit = emu->quit; + newemu->error = emu->error; + // addapt R_ESP to new stack frame + uintptr_t oldst = (uintptr_t)((emu->stack)?emu->stack:emu->context->stack); + uintptr_t newst = (uintptr_t)((newemu->stack)?newemu->stack:newemu->context->stack); + newemu->regs[_SP].dword[0] = emu->regs[_SP].dword[0] + (intptr_t)(newst - oldst); +} + uint32_t GetEAX(x86emu_t *emu) { return R_EAX; diff --git a/src/x86emu.h b/src/x86emu.h index 8386d819..6f685c25 100755 --- a/src/x86emu.h +++ b/src/x86emu.h @@ -8,6 +8,7 @@ x86emu_t *NewX86Emu(box86context_t *context, uintptr_t start, uintptr_t stack, i void SetupX86Emu(x86emu_t *emu, int* shared_gloabl, void* globals); void SetTraceEmu(x86emu_t *emu, uintptr_t trace_start, uintptr_t trace_end); void FreeX86Emu(x86emu_t **x86emu); +void CloneEmu(x86emu_t *newemu, const x86emu_t* emu); uint32_t GetEAX(x86emu_t *emu); void SetEAX(x86emu_t *emu, uint32_t v); diff --git a/src/x86emu_private.h b/src/x86emu_private.h index 8bc608ca..35c4595f 100755 --- a/src/x86emu_private.h +++ b/src/x86emu_private.h @@ -38,6 +38,7 @@ typedef struct x86emu_s { // emu control int quit; int error; + int fork; // quit because need to fork // trace zydis_dec_t *dec; uintptr_t trace_start, trace_end; @@ -52,6 +53,8 @@ typedef struct x86emu_s { int clean_cap; // scratch stack, used for alignement of double and 64bits ints on arm uint32_t *scratch; + // local stack, do be deleted when emu is freed + void* stack; } x86emu_t; diff --git a/src/x86int3.c b/src/x86int3.c index 62b9e7a0..4b4b3f07 100755 --- a/src/x86int3.c +++ b/src/x86int3.c @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include "debug.h" #include "stack.h" @@ -14,6 +16,31 @@ #include "wrapper.h" #include "box86context.h" +x86emu_t* x86emu_fork(x86emu_t* e) +{ + x86emu_t *emu = e; + // lets duplicate the emu + void* newstack = 0; + posix_memalign(&newstack, emu->context->stackalign, emu->context->stacksz); + memcpy(newstack, emu->context->stack, emu->context->stacksz); + x86emu_t* newemu = NewX86Emu(emu->context, R_EIP, (uintptr_t)newstack, emu->context->stacksz); + SetupX86Emu(newemu, emu->shared_global, emu->globals); + CloneEmu(newemu, emu); + emu->stack = newstack; + // ready to fork + ++emu->context->forked; + int v = fork(); + if(!v) { + emu = newemu; + } + if(v==EAGAIN || v==ENOMEM) { + --emu->context->forked; + FreeX86Emu(&newemu); // fork failed, free the new emu + } + R_EAX = v; + return emu; +} + void x86Int3(x86emu_t* emu) { if(Peek(emu, 0)=='S' && Peek(emu, 1)=='C') // Signature for "Out of x86 door" diff --git a/src/x86run.c b/src/x86run.c index 83626ff5..237ee436 100755 --- a/src/x86run.c +++ b/src/x86run.c @@ -17,6 +17,7 @@ int Run(x86emu_t *emu) { //ref opcode: http://ref.x86asm.net/geek32.html#xA1 printf_log(LOG_DEBUG, "Run X86, EIP=%p, Stack=%p\n", (void*)R_EIP, emu->context->stack); +x86emurun: emu->quit = 0; while (!emu->quit) { @@ -1057,4 +1058,9 @@ int Run(x86emu_t *emu) UnimpOpcode(emu); } } + if(emu->fork) { + emu->fork = 0; + emu = x86emu_fork(emu); + goto x86emurun; + } } diff --git a/src/x86run_private.h b/src/x86run_private.h index 3e7898d0..30304f98 100755 --- a/src/x86run_private.h +++ b/src/x86run_private.h @@ -34,6 +34,7 @@ void RunF30F(x86emu_t *emu); void x86Syscall(x86emu_t *emu); void x86Int3(x86emu_t* emu); +x86emu_t* x86emu_fork(x86emu_t* e); const char* GetNativeName(void* p); diff --git a/src/x87run.c b/src/x87run.c index 72494bf0..b4334e2e 100755 --- a/src/x87run.c +++ b/src/x87run.c @@ -316,29 +316,47 @@ void RunD9(x86emu_t *emu) ST0.d = 0.0; break; + case 0xF2: /* FTAN */ + ST0.d = tan(ST0.d); + fpu_do_push(emu); + ST0.d = 1.0; + break; + case 0xF3: /* FPATAN */ + ST(1).d = atan2(ST(1).d, ST0.d); + fpu_do_pop(emu); + break; + case 0xFA: /* FSQRT */ ST0.d = sqrt(ST0.d); break; - + case 0xFB: /* FSINCOS */ + d = ST0.d; + ST0.d = sin(d); + fpu_do_push(emu); + ST0.d = cos(d); + break; case 0xFC: /* FRNDINT */ ST0.d = fpu_round(emu, ST0.d); break; + case 0xFE: /* FSIN */ + ST0.d = sin(ST0.d); + break; + case 0xFF: /* FCOS */ + ST0.d = cos(ST0.d); + break; + + case 0xE4: case 0xF0: case 0xF1: - case 0xF2: - case 0xF3: case 0xF4: case 0xF5: case 0xF6: case 0xF7: case 0xF8: case 0xF9: - case 0xFB: case 0xFD: - case 0xFE: - case 0xFF: UnimpOpcode(emu); break; default: diff --git a/tests/ref09.txt b/tests/ref09.txt new file mode 100644 index 00000000..adcb7a7c --- /dev/null +++ b/tests/ref09.txt @@ -0,0 +1,2 @@ +Child has x = 2 +Parent has x = 0 diff --git a/tests/test09 b/tests/test09 new file mode 100755 index 00000000..c5d953b0 Binary files /dev/null and b/tests/test09 differ diff --git a/tests/test09.c b/tests/test09.c new file mode 100755 index 00000000..e4a56050 --- /dev/null +++ b/tests/test09.c @@ -0,0 +1,20 @@ +#include +#include +#include + +void forkexample() +{ + int x = 1; + + if (fork() == 0) + printf("Child has x = %d\n", ++x); + else { + usleep(20000); + printf("Parent has x = %d\n", --x); + } +} +int main() +{ + forkexample(); + return 0; +} \ No newline at end of file