about summary refs log tree commit diff stats
path: root/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/box32stack.c137
-rw-r--r--src/tools/box64stack.c10
-rw-r--r--src/tools/callback.c306
3 files changed, 369 insertions, 84 deletions
diff --git a/src/tools/box32stack.c b/src/tools/box32stack.c
new file mode 100644
index 00000000..441b27ab
--- /dev/null
+++ b/src/tools/box32stack.c
@@ -0,0 +1,137 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/mman.h>
+
+#include "box64stack.h"
+#include "box64context.h"
+#include "elfloader.h"
+#include "debug.h"
+#include "emu/x64emu_private.h"
+#include "emu/x64run_private.h"
+#include "auxval.h"
+#include "custommem.h"
+#include "box32.h"
+
+static void PushString32(x64emu_t *emu, const char* s)
+{
+    int sz = strlen(s) + 1;
+    // round to 4 bytes boundary
+    R_ESP -= sz;
+    memcpy(from_ptrv(R_ESP), s, sz);
+}
+
+static void Push32_32(x64emu_t *emu, uint32_t v)
+{
+    R_ESP -= 4;
+    *((uint32_t*)from_ptr(R_ESP)) = v;
+}
+
+
+EXPORTDYN
+void SetupInitialStack32(x64emu_t *emu)
+{
+    // start with 0
+    Push32_32(emu, 0);
+    // push program executed
+    PushString32(emu, emu->context->argv[0]);
+    uintptr_t p_arg0 = from_ptr(R_ESP);
+    // push envs
+    uintptr_t p_envv[emu->context->envc];
+    for (int i=emu->context->envc-1; i>=0; --i) {
+        PushString32(emu, emu->context->envv[i]);
+        p_envv[i] = from_ptr(R_ESP);
+    }
+    // push args, also, free the argv[] string and point to the one in the main stack
+    uintptr_t p_argv[emu->context->argc];
+    for (int i=emu->context->argc-1; i>=0; --i) {
+        PushString32(emu, emu->context->argv[i]);
+        p_argv[i] = R_ESP;
+        free(emu->context->argv[i]);
+        emu->context->argv[i] = (char*)p_argv[i];
+    }
+    // align
+    uintptr_t tmp = from_ptr(R_ESP)&~(emu->context->stackalign-1);
+    memset((void*)tmp, 0, from_ptr(R_ESP)-tmp);
+    R_ESP=to_ptr(tmp);
+
+    // push some AuxVector stuffs
+    PushString32(emu, "i686");
+    uintptr_t p_i686 = from_ptr(R_ESP);
+    uintptr_t p_random = real_getauxval(25);
+    if(!p_random) {
+        for (int i=0; i<4; ++i)
+            Push32_32(emu, random());
+        p_random = from_ptr(R_ESP);
+    }
+    // align
+    tmp = (R_ESP)&~(emu->context->stackalign-1);
+    memset((void*)tmp, 0, from_ptr(R_ESP)-tmp);
+    R_ESP=tmp;
+
+    // push the AuxVector themselves
+    /*
+    00: 00000000
+    03: 08048034
+    04: 00000020
+    05: 0000000b
+    06: 00001000
+    07: f7fc0000
+    08: 00000000
+    09: 08049060
+    11: 000003e8
+    12: 000003e8
+    13: 000003e8
+    14: 000003e8
+    15: ffd8aa5b/i686
+    16: bfebfbff
+    17: 00000064
+    23: 00000000
+    25: ffd8aa4b
+    26: 00000000
+    31: ffd8bfeb/./testAuxVec
+    32: f7fbfb40
+    33: f7fbf000
+    */
+    Push32_32(emu, 0); Push32_32(emu, 0);                            //AT_NULL(0)=0
+    //Push32_32(emu, ); Push32_32(emu, 3);                             //AT_PHDR(3)=address of the PH of the executable
+    //Push32_32(emu, ); Push32_32(emu, 4);                             //AT_PHENT(4)=size of PH entry
+    //Push32_32(emu, ); Push32_32(emu, 5);                             //AT_PHNUM(5)=number of elf headers
+    Push32_32(emu, box64_pagesize); Push32_32(emu, 6);               //AT_PAGESZ(6)
+    //Push32_32(emu, real_getauxval(7)); Push32_32(emu, 7);            //AT_BASE(7)=ld-2.27.so start (in memory)
+    Push32_32(emu, 0); Push32_32(emu, 8);                            //AT_FLAGS(8)=0
+    Push32_32(emu, R_EIP); Push32_32(emu, 9);                        //AT_ENTRY(9)=entrypoint
+    Push32_32(emu, from_ulong(real_getauxval(11))); Push32_32(emu, 11);          //AT_UID(11)
+    Push32_32(emu, from_ulong(real_getauxval(12))); Push32_32(emu, 12);          //AT_EUID(12)
+    Push32_32(emu, from_ulong(real_getauxval(13))); Push32_32(emu, 13);          //AT_GID(13)
+    Push32_32(emu, from_ulong(real_getauxval(14))); Push32_32(emu, 14);          //AT_EGID(14)
+    Push32_32(emu, p_i686); Push32_32(emu, 15);                      //AT_PLATFORM(15)=&"i686"
+    // Push HWCAP:
+    //  FPU: 1<<0 ; VME: 1<<1 ; DE : 1<<2 ; PSE: 1<<3 ; TSC: 1<<4 ; MSR: 1<<5 ; PAE: 1<<6 ; MCE: 1<<7
+    //  CX8: 1<<8 ; APIC:1<<9 ;             SEP: 1<<11; MTRR:1<<12; PGE: 1<<13; MCA: 1<<14; CMOV:1<<15
+    // FCMOV:1<<16;                                                                         MMX: 1<<23
+    // OSFXR:1<<24; XMM: 1<<25;XMM2: 1<<26;                                                AMD3D:1<<31
+    Push32_32(emu, (1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<8)  | (1<<15) | (1<<16) | (1<<23) | (1<<25) | (1<<26));
+    Push32_32(emu, 16);                                         //AT_HWCAP(16)=...
+    //Push32_32(emu, sysconf(_SC_CLK_TCK)); Push32_32(emu, 17);        //AT_CLKTCK(17)=times() frequency
+    Push32_32(emu, from_ulong(real_getauxval(23))); Push32_32(emu, 23);          //AT_SECURE(23)
+    Push32_32(emu, p_random); Push32_32(emu, 25);                    //AT_RANDOM(25)=p_random
+    Push32_32(emu, 0); Push32_32(emu, 26);                           //AT_HWCAP2(26)=0
+    Push32_32(emu, p_arg0); Push32_32(emu, 31);                      //AT_EXECFN(31)=p_arg0
+    Push32_32(emu, emu->context->vsyscall); Push32_32(emu, 32); //AT_SYSINFO(32)=vsyscall
+    //Push32_32(emu, ); Push32_32(emu, 33);                            //AT_SYSINFO_EHDR(33)=address of vDSO
+    if(!emu->context->auxval_start) // store auxval start if needed
+        emu->context->auxval_start = (uintptr_t*)from_ptr(R_ESP);
+
+    // push nil / envs / nil / args / argc
+    Push32_32(emu, 0);
+    for (int i=emu->context->envc-1; i>=0; --i)
+        Push32_32(emu, to_ptr(p_envv[i]));
+    emu->context->envv32 = R_ESP;
+    Push32_32(emu, 0);
+    for (int i=emu->context->argc-1; i>=0; --i)
+        Push32_32(emu, to_ptr(p_argv[i]));
+    emu->context->argv32 = R_ESP;
+    Push32_32(emu, emu->context->argc);
+}
diff --git a/src/tools/box64stack.c b/src/tools/box64stack.c
index 7be31b4d..82dc9a63 100644
--- a/src/tools/box64stack.c
+++ b/src/tools/box64stack.c
@@ -42,9 +42,19 @@ void PushString(x64emu_t *emu, const char* s)
     memcpy((void*)R_RSP, s, sz);
 }
 
+void SetupInitialStack32(x64emu_t *emu)
+#ifndef BOX32
+ { }
+#else
+ ;
+#endif
 EXPORTDYN
 void SetupInitialStack(x64emu_t *emu)
 {
+    if(box64_is32bits) {
+        SetupInitialStack32(emu);
+        return;
+    }
     // start with 0
     Push64(emu, 0);
     // push program executed
diff --git a/src/tools/callback.c b/src/tools/callback.c
index 341a554d..661a3b13 100644
--- a/src/tools/callback.c
+++ b/src/tools/callback.c
@@ -12,43 +12,74 @@
 #include "box64context.h"
 #include "box64stack.h"
 #include "dynarec.h"
+#ifdef BOX32
+#include "box32.h"
+#endif
 
 EXPORTDYN
 uint64_t RunFunction(uintptr_t fnc, int nargs, ...)
 {
     x64emu_t *emu = thread_get_emu();
-    int align = (nargs>6)?(((nargs-6)&1)):0;
-    int stackn = align + ((nargs>6)?(nargs-6):0);
-
-    Push64(emu, R_RBP); // push rbp
-    R_RBP = R_RSP;      // mov rbp, rsp
+    #ifdef BOX32
+    if(box64_is32bits) {
+        Push_32(emu, R_RBP); // push ebp
+        R_RBP = R_ESP;       // mov ebp, esp
 
-    R_RSP -= stackn*sizeof(void*);   // need to push in reverse order
+        R_ESP -= nargs*4;   // need to push in reverse order
 
-    uint64_t *p = (uint64_t*)R_RSP;
+        ptr_t *p = (ptr_t*)from_ptrv(R_ESP);
 
-    va_list va;
-    va_start (va, nargs);
-    for (int i=0; i<nargs; ++i) {
-        if(i<6) {
-            int nn[] = {_DI, _SI, _DX, _CX, _R8, _R9};
-            emu->regs[nn[i]].q[0] = va_arg(va, uint64_t);
-        } else {
-            *p = va_arg(va, uint64_t);
+        va_list va;
+        va_start (va, nargs);
+        for (int i=0; i<nargs; ++i) {
+            *p = va_arg(va, uint32_t);
             p++;
         }
+        va_end (va);
+    } else
+    #endif
+    {
+        int align = (nargs>6)?(((nargs-6)&1)):0;
+        int stackn = align + ((nargs>6)?(nargs-6):0);
+
+        Push64(emu, R_RBP); // push rbp
+        R_RBP = R_RSP;      // mov rbp, rsp
+
+        R_RSP -= stackn*sizeof(void*);   // need to push in reverse order
+
+        uint64_t *p = (uint64_t*)R_RSP;
+
+        va_list va;
+        va_start (va, nargs);
+        for (int i=0; i<nargs; ++i) {
+            if(i<6) {
+                int nn[] = {_DI, _SI, _DX, _CX, _R8, _R9};
+                emu->regs[nn[i]].q[0] = va_arg(va, uint64_t);
+            } else {
+                *p = va_arg(va, uint64_t);
+                p++;
+            }
+        }
+        va_end (va);
     }
-    va_end (va);
 
     uintptr_t oldip = R_RIP;
     DynaCall(emu, fnc);
 
     if(oldip==R_RIP) {
-        R_RSP = R_RBP;          // mov rsp, rbp
-        R_RBP = Pop64(emu);     // pop rbp
+        #ifdef BOX32
+        if(box64_is32bits) {
+            R_RSP = R_EBP;          // mov esp, ebp
+            R_EBP = Pop_32(emu);    // pop ebp
+        }
+        #endif
+        {
+            R_RSP = R_RBP;          // mov rsp, rbp
+            R_RBP = Pop64(emu);     // pop rbp
+        }
     }
 
-    uint64_t ret = R_RAX;
+    uint64_t ret = box64_is32bits?((uint64_t)R_EAX | ((uint64_t)R_EDX)<<32):R_RAX;
 
     return ret;
 }
@@ -61,6 +92,27 @@ uint64_t RunFunctionFmt(uintptr_t fnc, const char* fmt, ...)
     int ni = 0;
     int ndf = 0;
     for (int i=0; fmt[i]; ++i) {
+        #ifdef BOX32
+        if(box64_is32bits)
+            switch(fmt[i]) {
+                case 'd': 
+                case 'I': 
+                case 'U': nargs+=2; break;
+                case 'p': 
+                case 'L': 
+                case 'l': 
+                case 'f': 
+                case 'i': 
+                case 'u': 
+                case 'w': 
+                case 'W': 
+                case 'c': 
+                case 'C': ++nargs; break;
+                default:
+                    ++nargs; break;
+            }
+        else
+        #endif
         switch(fmt[i]) {
             case 'f': 
             case 'd': if(ndf<8) ++ndf; else ++nargs; break;
@@ -83,63 +135,116 @@ uint64_t RunFunctionFmt(uintptr_t fnc, const char* fmt, ...)
     ndf = 0;
     int align = nargs&1;
     int stackn = align + nargs;
+    int sizeof_ptr = sizeof(void*);
+    #ifdef BOX32
+    if(box64_is32bits) {
+        Push_32(emu, R_EBP); // push ebp
+        R_RBP = R_ESP;       // mov ebp, esp
+        sizeof_ptr = sizeof(ptr_t);
+    } else
+    #endif
+    {
+        Push64(emu, R_RBP); // push rbp
+        R_RBP = R_RSP;      // mov rbp, rsp
+    }
 
-    Push64(emu, R_RBP); // push rbp
-    R_RBP = R_RSP;      // mov rbp, rsp
-
-    R_RSP -= stackn*sizeof(void*);   // need to push in reverse order
-
-    uint64_t *p = (uint64_t*)R_RSP;
-
-    static const int nn[] = {_DI, _SI, _DX, _CX, _R8, _R9};
-    #define GO(c, A, B, B2, C) case c: if(ni<6) emu->regs[nn[ni++]].A[0] = C va_arg(va, B2); else {*p = 0; *((B*)p) = va_arg(va, B2); ++p;}; break;
-    va_list va;
-    va_start (va, fmt);
-    for (int i=0; fmt[i]; ++i) {
-        switch(fmt[i]) {
-            case 'f':   if(ndf<8)
-                            emu->xmm[ndf++].f[0] = va_arg(va, double);  // float are promoted to double in ...
-                        else {
-                            *p = 0;
-                            *((float*)p) = va_arg(va, double);
-                            ++p;
-                        }
-                        break;
-            case 'd':   if(ndf<8)
-                            emu->xmm[ndf++].d[0] = va_arg(va, double);
-                        else {
-                            *((double*)p) = va_arg(va, double);
-                            ++p;
-                        }
-                        break;
-            GO('p', q, void*, void*, (uintptr_t))
-            GO('i', sdword, int, int, )
-            GO('u', dword, uint32_t, uint32_t, )
-            GO('I', sq, int64_t, int64_t, )
-            GO('U', q, uint64_t, uint64_t, )
-            GO('L', q, uint64_t, uint64_t, )
-            GO('l', sq, int64_t, int64_t, )
-            GO('w', sword, int16_t, int, )
-            GO('W', word, uint16_t, int, )
-            GO('c', sbyte, int8_t, int, )
-            GO('C', byte, uint8_t, int, )
-            default:
-                printf_log(LOG_NONE, "Error, unhandled arg %d: '%c' in RunFunctionFmt\n", i, fmt[i]);
-                if(ni<6) emu->regs[nn[ni++]].q[0] = va_arg(va, uint64_t); else {*p = va_arg(va, uint64_t); ++p;}; 
-                break;
+    R_RSP -= stackn*sizeof_ptr;   // need to push in reverse order
+
+    #ifdef BOX32
+    if(box64_is32bits) {
+        ptr_t *p = (ptr_t*)from_ptrv(R_ESP);
+
+        #define GO(c, B, B2, N) case c: *((B*)p) = va_arg(va, B2); p+=N; break
+        va_list va;
+        va_start (va, fmt);
+        for (int i=0; fmt[i]; ++i) {
+            switch(fmt[i]) {
+                GO('f', float, double, 1);
+                GO('d', double, double, 2);
+                case 'p': *((ptr_t*)p) = to_ptrv(va_arg(va, void*)); p+=1; break;
+                GO('i', int, int, 1);
+                GO('u', uint32_t, uint32_t, 1);
+                GO('I', int64_t, int64_t, 2);
+                GO('U', uint64_t, uint64_t, 2);
+                GO('L', uint32_t, uint64_t, 1);     // long are 64bits on 64bits system
+                GO('l', int32_t, int64_t, 1);       // but 32bits on 32bits system
+                GO('w', int16_t, int, 1);
+                GO('W', uint16_t, int, 1);
+                GO('c', int8_t, int, 1);
+                GO('C', uint8_t, int, 1);
+                default:
+                    printf_log(LOG_NONE, "Error, unhandled arg %d: '%c' in RunFunctionFmt\n", i, fmt[i]);
+                    *p = va_arg(va, uint32_t);
+                    ++p; 
+                    break;
+            }
         }
+        #undef GO
+        va_end (va);
+    } else
+    #endif
+    {
+        uint64_t *p = (uint64_t*)R_RSP;
+
+        static const int nn[] = {_DI, _SI, _DX, _CX, _R8, _R9};
+        #define GO(c, A, B, B2, C) case c: if(ni<6) emu->regs[nn[ni++]].A[0] = C va_arg(va, B2); else {*p = 0; *((B*)p) = va_arg(va, B2); ++p;}; break;
+        va_list va;
+        va_start (va, fmt);
+        for (int i=0; fmt[i]; ++i) {
+            switch(fmt[i]) {
+                case 'f':   if(ndf<8)
+                                emu->xmm[ndf++].f[0] = va_arg(va, double);  // float are promoted to double in ...
+                            else {
+                                *p = 0;
+                                *((float*)p) = va_arg(va, double);
+                                ++p;
+                            }
+                            break;
+                case 'd':   if(ndf<8)
+                                emu->xmm[ndf++].d[0] = va_arg(va, double);
+                            else {
+                                *((double*)p) = va_arg(va, double);
+                                ++p;
+                            }
+                            break;
+                GO('p', q, void*, void*, (uintptr_t))
+                GO('i', sdword, int, int, )
+                GO('u', dword, uint32_t, uint32_t, )
+                GO('I', sq, int64_t, int64_t, )
+                GO('U', q, uint64_t, uint64_t, )
+                GO('L', q, uint64_t, uint64_t, )
+                GO('l', sq, int64_t, int64_t, )
+                GO('w', sword, int16_t, int, )
+                GO('W', word, uint16_t, int, )
+                GO('c', sbyte, int8_t, int, )
+                GO('C', byte, uint8_t, int, )
+                default:
+                    printf_log(LOG_NONE, "Error, unhandled arg %d: '%c' in RunFunctionFmt\n", i, fmt[i]);
+                    if(ni<6) emu->regs[nn[ni++]].q[0] = va_arg(va, uint64_t); else {*p = va_arg(va, uint64_t); ++p;}; 
+                    break;
+            }
+        }
+        #undef GO
+        va_end (va);
     }
-    va_end (va);
 
     uintptr_t oldip = R_RIP;
     DynaCall(emu, fnc);
 
     if(oldip==R_RIP) {
-        R_RSP = R_RBP;          // mov rsp, rbp
-        R_RBP = Pop64(emu);     // pop rbp
+        #ifdef BOX32
+        if(box64_is32bits) {
+            R_RSP = R_EBP;          // mov esp, ebp
+            R_RBP = Pop_32(emu);    // pop ebp
+        }
+        #endif
+        {
+            R_RSP = R_RBP;          // mov rsp, rbp
+            R_RBP = Pop64(emu);     // pop rbp
+        }
     }
 
-    uint64_t ret = R_RAX;
+    uint64_t ret = box64_is32bits?((uint64_t)R_EAX | ((uint64_t)R_EDX)<<32):R_RAX;
 
     return ret;
 }
@@ -148,6 +253,10 @@ EXPORTDYN
 uint64_t RunSafeFunction(uintptr_t fnc, int nargs, ...)
 {
     x64emu_t * emu = thread_get_emu();
+    if(box64_is32bits) {
+        printf_log(LOG_NONE, "Calling RunSafeFunction in 32bits\n");
+        abort();
+    }
 
     int align = (nargs>6)?(((nargs-6)&1)):0;
     int stackn = align + ((nargs>6)?(nargs-6):0);
@@ -222,28 +331,48 @@ uint64_t RunSafeFunction(uintptr_t fnc, int nargs, ...)
 EXPORTDYN
 uint64_t RunFunctionWithEmu(x64emu_t *emu, int QuitOnLongJump, uintptr_t fnc, int nargs, ...)
 {
-    int align = (nargs>6)?(((nargs-6)&1)):0;
-    int stackn = align + ((nargs>6)?(nargs-6):0);
-
-    Push64(emu, R_RBP); // push rbp
-    R_RBP = R_RSP;      // mov rbp, rsp
+    #ifdef BOX32
+    if(box64_is32bits) {
+        Push_32(emu, R_RBP); // push ebp
+        R_RBP = R_ESP;       // mov ebp, esp
 
-    R_RSP -= stackn*sizeof(void*);   // need to push in reverse order
+        R_ESP -= nargs*4;   // need to push in reverse order
 
-    uint64_t *p = (uint64_t*)R_RSP;
+        ptr_t *p = (ptr_t*)from_ptrv(R_ESP);
 
-    va_list va;
-    va_start (va, nargs);
-    for (int i=0; i<nargs; ++i) {
-        if(i<6) {
-            int nn[] = {_DI, _SI, _DX, _CX, _R8, _R9};
-            emu->regs[nn[i]].q[0] = va_arg(va, uint64_t);
-        } else {
-            *p = va_arg(va, uint64_t);
+        va_list va;
+        va_start (va, nargs);
+        for (int i=0; i<nargs; ++i) {
+            *p = va_arg(va, uint32_t);
             p++;
         }
+        va_end (va);
+    } else
+    #endif
+    {
+        int align = (nargs>6)?(((nargs-6)&1)):0;
+        int stackn = align + ((nargs>6)?(nargs-6):0);
+
+        Push64(emu, R_RBP); // push rbp
+        R_RBP = R_RSP;      // mov rbp, rsp
+
+        R_RSP -= stackn*sizeof(void*);   // need to push in reverse order
+
+        uint64_t *p = (uint64_t*)R_RSP;
+
+        va_list va;
+        va_start (va, nargs);
+        for (int i=0; i<nargs; ++i) {
+            if(i<6) {
+                int nn[] = {_DI, _SI, _DX, _CX, _R8, _R9};
+                emu->regs[nn[i]].q[0] = va_arg(va, uint64_t);
+            } else {
+                *p = va_arg(va, uint64_t);
+                p++;
+            }
+        }
+        va_end (va);
     }
-    va_end (va);
 
     uintptr_t oldip = R_RIP;
     int old_quit = emu->quit;
@@ -256,20 +385,29 @@ uint64_t RunFunctionWithEmu(x64emu_t *emu, int QuitOnLongJump, uintptr_t fnc, in
 
     if(oldip==R_RIP) {
         R_RSP = R_RBP;      // restore stack only if EIP is the one expected (else, it means return value is not the one expected)
-        R_RBP = Pop64(emu); //Pop EBP
+        #ifdef BOX32
+        if(box64_is32bits)
+            R_RBP = Pop_32(emu); //Pop EBP
+        else
+        #endif
+            R_RBP = Pop64(emu); //Pop EBP
     }
 
     emu->quit = old_quit;
     emu->flags.quitonlongjmp = oldlong;
 
 
-    return R_RAX;
+    return box64_is32bits?((uint64_t)R_EAX | ((uint64_t)R_EDX)<<32):R_RAX;;
 }
 
 EXPORTDYN
 uint64_t RunFunctionWindows(uintptr_t fnc, int nargs, ...)
 {
     x64emu_t *emu = thread_get_emu();
+    if(box64_is32bits) {
+        printf_log(LOG_NONE, "Calling RunFunctionWindows in 32bits\n");
+        abort();
+    }
     int align = (nargs>4)?(((nargs-4)&1)):0;
     int stackn = align + ((nargs>4)?(nargs-4):0);