diff options
Diffstat (limited to 'src/emu/x64run_private.c')
| -rw-r--r-- | src/emu/x64run_private.c | 95 |
1 files changed, 81 insertions, 14 deletions
diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c index 9f8457c2..b17b3e7f 100644 --- a/src/emu/x64run_private.c +++ b/src/emu/x64run_private.c @@ -33,6 +33,8 @@ int32_t EXPORT my___libc_start_main(x64emu_t* emu, int *(main) (int, char * *, c (void)argc; (void)ubp_av; (void)fini; (void)rtld_fini; (void)stack_end; if(init) { + uintptr_t old_rsp = GetRSP(emu); + uintptr_t old_rbp = GetRBP(emu); // should not be needed, but seems to be without dynarec Push64(emu, GetRBP(emu)); // set frame pointer SetRBP(emu, GetRSP(emu)); // save RSP SetRSP(emu, GetRSP(emu)&~0xFLL); // Align RSP @@ -47,6 +49,8 @@ int32_t EXPORT my___libc_start_main(x64emu_t* emu, int *(main) (int, char * *, c return 0; SetRSP(emu, GetRBP(emu)); // restore RSP SetRBP(emu, Pop64(emu)); // restore RBP + SetRSP(emu, old_rsp); + SetRBP(emu, old_rbp); emu->quit = 0; } else { RunElfInit(my_context->elfs[0], emu); @@ -1006,7 +1010,7 @@ const char* getAddrFunctionName(uintptr_t addr) return ret; } -void printFunctionAddr(uintptr_t nextaddr, const char* text) +int printFunctionAddr(uintptr_t nextaddr, const char* text) { uint64_t sz = 0; uintptr_t start = 0; @@ -1017,7 +1021,9 @@ void printFunctionAddr(uintptr_t nextaddr, const char* text) printf_log(LOG_NONE, " (%s%s:%s)", text, ElfName(FindElfAddress(my_context, nextaddr)), symbname); else printf_log(LOG_NONE, " (%s%s:%s + %ld)", text, ElfName(FindElfAddress(my_context, nextaddr)), symbname, nextaddr - start); + return 1; } + return 0; } #ifdef HAVE_TRACE @@ -1028,6 +1034,7 @@ extern uint64_t start_cnt; void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec) { + int is32bits = (emu->segs[_CS]==0x23); if(start_cnt) --start_cnt; if(!start_cnt && my_context->dec && ( (trace_end == 0) @@ -1047,7 +1054,7 @@ void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec) my_context->trace_tid = tid; } #endif - printf_log(LOG_NONE, "%s", DumpCPURegs(emu, ip)); + printf_log(LOG_NONE, "%s", DumpCPURegs(emu, ip, is32bits)); if(R_RIP==0) { printf_log(LOG_NONE, "Running at NULL address\n"); mutex_unlock(&my_context->mutex_trace); @@ -1061,30 +1068,38 @@ void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec) printf_log(LOG_NONE, "%p: Native call to %p => %s\n", (void*)ip, (void*)a, GetNativeName(*(void**)(ip+11))); } } else { - printf_log(LOG_NONE, "%s", DecodeX64Trace(my_context->dec, ip)); + printf_log(LOG_NONE, "%s", DecodeX64Trace(is32bits?my_context->dec32:my_context->dec, ip)); uint8_t peek = PK(0); rex_t rex = {0}; - if(peek>=0x40 && peek<=0x4f) { + if(!is32bits && peek>=0x40 && peek<=0x4f) { rex.rex = peek; ip++; peek = PK(0); } if(peek==0xC3 || peek==0xC2 || (peek==0xF3 && PK(1)==0xC3)) { - printf_log(LOG_NONE, " => %p", *(void**)(R_RSP)); - printFunctionAddr(*(uintptr_t*)(R_RSP), "=> "); + if(is32bits) { + printf_log(LOG_NONE, " => %p", (void*)(uintptr_t)*(uint32_t*)(R_RSP)); + printFunctionAddr(*(uint32_t*)(R_RSP), "=> "); + } else { + printf_log(LOG_NONE, " => %p", *(void**)(R_RSP)); + printFunctionAddr(*(uintptr_t*)(R_RSP), "=> "); + } } else if(peek==0x57 && rex.b) { printf_log(LOG_NONE, " => STACK_TOP: %p", *(void**)(R_RSP)); printFunctionAddr(ip, "here: "); - } else if(peek==0x55 || peek==0x53) { + } else if((peek==0x55 || peek==0x53) && !is32bits) { printFunctionAddr(*(uintptr_t*)(R_RSP), " STACK_TOP: "); - } else if(peek==0xF3 && PK(1)==0x0F && PK(2)==0x1E && PK(3)==0xFA) { + } else if((peek==0x55 || peek==0x56) && is32bits) { + if(!printFunctionAddr(*(uint32_t*)(R_RSP), " STACK_TOP: ")) + printf_log(LOG_NONE, " STACK_TOP: %p ", (void*)(uintptr_t)*(uint32_t*)(R_RSP)); + } else if(peek==0xF3 && PK(1)==0x0F && PK(2)==0x1E && PK(3)==0xFA && !is32bits) { printFunctionAddr(*(uintptr_t*)(R_RSP), " STACK_TOP: "); } else if(peek==0xE8) { // Call - uintptr_t nextaddr = ip + 5 + PK64(1); + uintptr_t nextaddr = ip + 5 + PK32(1); printFunctionAddr(nextaddr, "=> "); } else if(peek==0xFF) { if(PK(1)==0x25) { - uintptr_t nextaddr = ip + 6 + PK64(2); + uintptr_t nextaddr = ip + 6 + PK32(2); printFunctionAddr(nextaddr, "=> "); } } @@ -1132,8 +1147,56 @@ static uint64_t F64(uintptr_t* addr) { return ret; } +reg64_t* GetECommon_32(x64emu_t* emu, uintptr_t* addr, uint8_t m, uint32_t base) +{ + if (m<=7) { + if(m==0x4) { + uint8_t sib = F8(addr); + base += ((sib&0x7)==5)?((uint32_t)F32S(addr)):(emu->regs[(sib&0x7)].dword[0]); // base + base += (emu->sbiidx[((sib>>3)&7)]->sdword[0] << (sib>>6)); + return (reg64_t*)(uintptr_t)base; + } else if (m==0x5) { //disp32 + base += F32S(addr); + return (reg64_t*)(uintptr_t)base; + } + return (reg64_t*)(uintptr_t)(base + emu->regs[m].dword[0]); + } else { + if((m&7)==4) { + uint8_t sib = F8(addr); + base += emu->regs[(sib&0x7)].dword[0]; // base + base += (emu->sbiidx[((sib>>3)&7)]->sdword[0] << (sib>>6)); + } else { + base += emu->regs[(m&0x7)].dword[0]; + } + base+=(m&0x80)?F32S(addr):F8S(addr); + return (reg64_t*)(uintptr_t)base; + } +} +reg64_t* GetEw16_32(x64emu_t *emu, uintptr_t* addr, uint8_t m, uint32_t base) +{ + switch(m&7) { + case 0: base+= R_BX+R_SI; break; + case 1: base+= R_BX+R_DI; break; + case 2: base+= R_BP+R_SI; break; + case 3: base+= R_BP+R_DI; break; + case 4: base+= R_SI; break; + case 5: base+= R_DI; break; + case 6: base+= R_BP; break; + case 7: base+= R_BX; break; + } + switch((m>>6)&3) { + case 0: if((m&7)==6) base= F16S(addr); break; + case 1: base += F8S(addr); break; + case 2: base += F16S(addr); break; + // case 3 is C0..C7, already dealt with + } + return (reg64_t*)(uintptr_t)base; +} + reg64_t* GetECommon(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_t delta) { + if(rex.is32bits) + return GetECommon_32(emu, addr, m, 0); if (m<=7) { if(m==0x4) { uint8_t sib = F8(addr); @@ -1161,6 +1224,8 @@ reg64_t* GetECommon(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_ reg64_t* GetECommonO(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_t delta, uintptr_t base) { + if(rex.is32bits) + return GetECommon_32(emu, addr, m, base); if (m<=7) { if(m==0x4) { uint8_t sib = F8(addr); @@ -1187,6 +1252,8 @@ reg64_t* GetECommonO(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8 reg64_t* GetECommon32O(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_t delta, uintptr_t base) { + if(rex.is32bits) + return GetEw16_32(emu, addr, m, base); if (m<=7) { if(m==0x4) { uint8_t sib = F8(addr); @@ -1471,7 +1538,7 @@ reg64_t* GetEw16(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v) case 7: base = R_BX; break; } switch((m>>6)&3) { - case 0: if(m==6) base = F16(addr); break; + case 0: if((m&7)==6) base = F16S(addr); break; case 1: base += F8S(addr); break; case 2: base += F16S(addr); break; // case 3 is C0..C7, already dealt with @@ -1501,7 +1568,7 @@ reg64_t* TestEw16(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v) case 7: base = R_BX; break; } switch((m>>6)&3) { - case 0: if(m==6) base = F16(addr); break; + case 0: if((m&7)==6) base = F16S(addr); break; case 1: base += F8S(addr); break; case 2: base += F16S(addr); break; // case 3 is C0..C7, already dealt with @@ -1533,7 +1600,7 @@ reg64_t* GetEw16off(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uintpt case 7: base = R_BX; break; } switch((m>>6)&3) { - case 0: if(m==6) base = F16(addr); break; + case 0: if((m&7)==6) base = F16S(addr); break; case 1: base += F8S(addr); break; case 2: base += F16S(addr); break; // case 3 is C0..C7, already dealt with @@ -1563,7 +1630,7 @@ reg64_t* TestEw16off(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uin case 7: base = R_BX; break; } switch((m>>6)&3) { - case 0: if(m==6) base = F16(addr); break; + case 0: if((m&7)==6) base = F16S(addr); break; case 1: base += F8S(addr); break; case 2: base += F16S(addr); break; // case 3 is C0..C7, already dealt with |