about summary refs log tree commit diff stats
path: root/src/emu/x64run_private.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/x64run_private.c')
-rw-r--r--src/emu/x64run_private.c95
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