#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include #include #include #include #include #include #include #include #include #include "x64_signals.h" #include "os.h" #include "debug.h" #include "box64stack.h" #include "x64emu.h" #include "x64emu_private.h" #include "x64run_private.h" #include "x87emu_private.h" #include "x64primop.h" #include "x64trace.h" #include "wrapper32.h" #include "box32context.h" #include "librarian.h" #include "emit_signals.h" #include "tools/bridge_private.h" #include #include "elfloader.h" #include "elfload_dump.h" #include "elfs/elfloader_private.h" typedef int32_t (*iFpppp_t)(void*, void*, void*, void*); static uint64_t F64(uintptr_t* addr) { uint64_t ret = *(uint64_t*)*addr; *addr+=8; return ret; } static uint8_t Peek8(uintptr_t addr, uintptr_t offset) { return *(uint8_t*)(addr+offset); } extern int errno; void x86Int3(x64emu_t* emu, uintptr_t* addr) { onebridge_t* bridge = (onebridge_t*)(*addr-1); if (IsBridgeSignature(Peek8(*addr, 0), Peek8(*addr, 1))) { // Signature for "Out of x86 door" *addr += 2; uintptr_t a = F64(addr); if(a==0) { R_RIP = *addr; //printf_log(LOG_INFO, "%p:Exit x86 emu (emu=%p)\n", *(void**)(R_ESP), emu); emu->quit=1; // normal quit } else { RESET_FLAGS(emu); wrapper_t w = bridge->w; a = F64(addr); R_RIP = *addr; /* This party can be used to trace only 1 specific lib (but it is quite slow) elfheader_t *h = FindElfAddress(my_context, *(uintptr_t*)(R_ESP)); int have_trace = 0; if(h && strstr(ElfName(h), "libMiles")) have_trace = 1;*/ if(BOX64ENV(log)>=LOG_DEBUG || BOX64ENV(rolling_log)) { int tid = GetTID(); char t_buff[256] = "\0"; char buff2[64] = "\0"; char buff3[64] = "\0"; int cycle_line = my_context->current_line; if(BOX64ENV(rolling_log)) { my_context->current_line = (my_context->current_line+1)%BOX64ENV(rolling_log); } char* buff = BOX64ENV(rolling_log)?(my_context->log_call+256*cycle_line):t_buff; char* buffret = BOX64ENV(rolling_log)?(my_context->log_ret+128*cycle_line):NULL; if(buffret) buffret[0] = '\0'; char *tmp; int post = 0; int perr = 0; int ret_fmt = 0; uint64_t *pu64 = NULL; uint32_t *pu32 = NULL; uint8_t *pu8 = NULL; const char *s = bridge->name; if(!s) s = GetNativeName((void*)a); if(a==(uintptr_t)PltResolver32) { if(BOX64ENV(rolling_log)) { ptr_t addr = *((uint32_t*)from_ptrv(R_ESP)); int slot = *((uint32_t*)from_ptrv(R_ESP+4)); elfheader_t *h = (elfheader_t*)from_ptrv(addr); Elf32_Rel * rel = (Elf32_Rel *)from_ptrv(h->jmprel + h->delta + slot); Elf32_Sym *sym = &h->DynSym._32[ELF32_R_SYM(rel->r_info)]; const char* symname = SymName32(h, sym); snprintf(buff, 256, "%04d|PltResolver \"%s\"", tid, symname?symname:"???"); } else { snprintf(buff, 256, "%s", " ... "); } } else if(strstr(s, "SDL_PollEvent")==s) { snprintf(buff, 255, "%04d|%p: Calling %s(%p)", tid, from_ptriv(R_ESP), (char *)s, from_ptriv(R_ESP+4)); pu8 = from_ptriv(R_ESP+4); post = 10; } else if(strstr(s, "SDL_RWFromFile")==s || strstr(s, "SDL_RWFromFile")==s) { snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, from_ptriv(R_ESP), (char *)s, (char *)from_ptriv(R_ESP+4), (char *)from_ptriv(R_ESP+8)); } else if(strstr(s, "SDL_WarpMouse")==s) { snprintf(buff, 255, "%04d|%p: Calling %s(%hd, %hd)", tid, from_ptriv(R_ESP), (char *)s, *(uint16_t*)from_ptr(R_ESP+4), *(uint16_t*)from_ptr(R_ESP+8)); } else if(strstr(s, "glColor4f")==s) { snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f, %f, %f)", tid, from_ptriv(R_ESP), (char *)s, *(float*)from_ptr(R_ESP+4), *(float*)from_ptr(R_ESP+8), *(float*)from_ptr(R_ESP+12), *(float*)from_ptr(R_ESP+16)); } else if(strstr(s, "glTexCoord2f")==s) { snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, from_ptriv(R_ESP), (char *)s, *(float*)from_ptr(R_ESP+4), *(float*)from_ptr(R_ESP+8)); } else if(strstr(s, "glVertex2f")==s) { snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, from_ptriv(R_ESP), (char *)s, *(float*)from_ptr(R_ESP+4), *(float*)from_ptr(R_ESP+8)); } else if(strstr(s, "glVertex3f")==s) { snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f, %f)", tid, from_ptriv(R_ESP), (char *)s, *(float*)from_ptr(R_ESP+4), *(float*)from_ptr(R_ESP+8), *(float*)from_ptr(R_ESP+12)); } else if(strstr(s, "__open64")==s || strcmp(s, "open64")==0) { snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d, %d)", tid, from_ptriv(R_ESP), (char *)s, (char *)from_ptriv(R_ESP+4), *(int*)from_ptr(R_ESP+8), *(int*)from_ptr(R_ESP+12)); perr = 1; } else if(!strcmp(s, "opendir")) { snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, from_ptriv(R_ESP), (char *)s, (char *)from_ptriv(R_ESP+4)); perr = 2; } else if(strstr(s, "__open")==s || !strcmp(s, "open") || !strcmp(s, "my_open64")) { tmp = from_ptriv(R_ESP+4); snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d (,%d))", tid, from_ptriv(R_ESP), (char *)s, (tmp)?tmp:"(nil)", *(int*)from_ptr(R_ESP+8), *(int*)from_ptr(R_ESP+12)); perr = 1; } else if(!strcmp(s, "shm_open")) { tmp = from_ptriv(R_ESP+4); snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d, %d)", tid, from_ptriv(R_ESP), (char *)s, (tmp)?tmp:"(nil)", *(int*)from_ptr(R_ESP+8), *(int*)from_ptr(R_ESP+12)); perr = 1; } else if(strcmp(s, "mkdir")==0) { tmp = from_ptriv(R_ESP+4); snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d)", tid, from_ptriv(R_ESP), (char *)s, (tmp)?tmp:"(nil)", *(int*)from_ptr(R_ESP+8)); perr = 1; } else if(!strcmp(s, "fopen")) { snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, from_ptriv(R_ESP), (char *)s, (char *)from_ptriv(R_ESP+4), (char *)from_ptriv(R_ESP+8)); perr = 2; } else if(!strcmp(s, "freopen")) { snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", %p)", tid, from_ptriv(R_ESP), (char *)s, (char *)from_ptriv(R_ESP+4), (char *)from_ptriv(R_ESP+8), from_ptriv(R_ESP+12)); perr = 2; } else if(!strcmp(s, "fopen64")) { snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, from_ptriv(R_ESP), (char *)s, (char *)from_ptriv(R_ESP+4), (char *)from_ptriv(R_ESP+8)); perr = 2; } else if(!strcmp(s, "chdir")) { pu32=(uint32_t*)from_ptrv(R_ESP+4); snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, from_ptriv(R_ESP), (char *)s, pu32?((pu32==(uint32_t*)1)?"/1/":(char*)(uintptr_t)(*pu32)):"/0/"); } else if(!strcmp(s, "poll")) { pu32=from_ptrv(*(ptr_t*)from_ptrv(R_ESP+4)); char tmp[50]; char tmp2[50] = {0}; uint32_t n = from_ptri(uint32_t, R_ESP+8); for(int ii=0; iicontext->mutex_trace); printf_log(LOG_NONE, "%s =>", buff); mutex_unlock(&emu->context->mutex_trace); } w(emu, a); // some function never come back, so unlock the mutex first! if(post) switch(post) { case 1: snprintf(buff2, 63, " [%d sec %d nsec]", pu32?pu32[0]:-1, pu32?pu32[1]:-1); break; case 2: snprintf(buff2, 63, "(%s)", R_EAX?((char*)from_ptr(R_EAX)):"nil"); break; case 3: snprintf(buff2, 63, "(%s)", pu32?((char*)pu32):"nil"); break; case 4: snprintf(buff2, 63, " (%f)", ST0.d); break; case 5: { uint32_t* p = (uint32_t*)from_ptrv(R_EAX); if(p) snprintf(buff2, 63, " size=%dx%d, pitch=%d, pixels=%p", p[2], p[3], p[4], p+5); else snprintf(buff2, 63, "NULL Surface"); } break; case 6: snprintf(buff2, 63, "(%S)", pu32?((wchar_t*)pu32):L"nil"); break; case 7: if(R_EAX) snprintf(buff2, 63, " (error=\"%s\")", strerror(R_EAX)); break; case 8: if(!R_EAX) snprintf(buff2, 63, " [%p]", from_ptrv(*pu32)); break; case 9: if(errno) snprintf(buff2, 63, " (errno=%d/\"%s\")", errno, strerror(errno)); else snprintf(buff2, 63, " (errno=0)"); break; break; case 10: if(R_EAX) switch(*pu8) { case 4: snprintf(buff2, 63, " [type=%hhd, x=%hd, y=%hd, relx=%+hd, rely=%+hd]", *pu8, *(uint16_t*)(pu8+4), *(uint16_t*)(pu8+6), *(int16_t*)(pu8+8), *(int16_t*)(pu8+10)); break; default: snprintf(buff2, 63, " [type=%hhd]", *pu8); } break; case 11: snprintf(buff2, 63, " [%d / %d / %d /%d]", pu32[0], pu32[1], pu32[2], pu32[3]); break; case 12: if(R_EAX>0) { char tmp[50]; char tmp2[50] = {0}; uint32_t n = from_ptri(uint32_t, R_ESP+8); for(int ii=0; ii>16); strncat(tmp2, tmp, 49); } snprintf(buff2, 63, "[%s]", tmp2); } case 13: if(R_EAX==0x25E) snprintf(buff2, 63, "%s", "here"); break; case 14: snprintf(buff2, 63, " [%d]", *(int*)pu32); break; } if(perr==1 && (S_EAX)<0) snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno)); else if(perr==2 && R_EAX==0) snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno)); else if(perr==3 && (S_EAX)==-1) snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno)); else if(perr==4) snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno)); if(BOX64ENV(rolling_log)) { if(ret_fmt==1) snprintf(buffret, 127, "%d%s%s", S_EAX, buff2, buff3); else snprintf(buffret, 127, "0x%X%s%s", R_EAX, buff2, buff3); } else { mutex_lock(&emu->context->mutex_trace); if(ret_fmt==1) printf_log_prefix(0, LOG_NONE, " return %d%s%s\n", S_EAX, buff2, buff3); else printf_log_prefix(0, LOG_NONE, " return 0x%X%s%s\n", R_EAX, buff2, buff3); mutex_unlock(&emu->context->mutex_trace); } } else w(emu, a); } return; } if(!BOX64ENV(ignoreint3) && my_context->signals[X64_SIGTRAP]) { R_RIP = *addr; // update RIP EmitSignal(emu, X64_SIGTRAP, NULL, 3); } else { printf_log(LOG_DEBUG, "%04d|Warning, ignoring unsupported Int 3 call @%p\n", GetTID(), (void*)R_RIP); R_RIP = *addr; } //emu->quit = 1; }