about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-03-02 10:47:22 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-03-02 10:47:22 +0100
commit26201d7e705714cd8ecca3fa28f51e819f9eb520 (patch)
treea53914e9b6b28285ed5ee1f22d7d2900f608faec /src
parent542a2a0775e5fe2921ce7893a9c1d77915a87bc4 (diff)
downloadbox64-26201d7e705714cd8ecca3fa28f51e819f9eb520.tar.gz
box64-26201d7e705714cd8ecca3fa28f51e819f9eb520.zip
More elf loader and parsing and stack preparing
Diffstat (limited to 'src')
-rwxr-xr-xsrc/elfs/elfloader.c62
-rwxr-xr-xsrc/include/box64stack.h17
-rwxr-xr-xsrc/include/elfloader.h4
-rwxr-xr-xsrc/main.c9
-rwxr-xr-xsrc/tools/box64stack.c138
5 files changed, 197 insertions, 33 deletions
diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c
index f1d4cf39..c107ca6a 100755
--- a/src/elfs/elfloader.c
+++ b/src/elfs/elfloader.c
@@ -23,10 +23,10 @@
 #include "box64context.h"
 //#include "library.h"
 //#include "x86emu.h"
-//#include "box86stack.h"
+//#include "box64stack.h"
 //#include "callback.h"
 //#include "dynarec.h"
-//#include "box86stack.h"
+//#include "box64stack.h"
 #include "custommem.h"
 #include "wine_tools.h"
 //#ifdef DYNAREC
@@ -359,8 +359,8 @@ int FindR386COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint32_t*
         return 0;
     int cnt = h->relsz / h->relent;
     for (int i=0; i<cnt; ++i) {
-        int t = ELF32_R_TYPE(rel[i].r_info);
-        Elf64_Sym *sym = &h->DynSym[ELF32_R_SYM(rel[i].r_info)];
+        int t = ELF64_R_TYPE(rel[i].r_info);
+        Elf64_Sym *sym = &h->DynSym[ELF64_R_SYM(rel[i].r_info)];
         const char* symname = SymName(h, sym);
         if(!strcmp(symname, name) && t==R_386_COPY) {
             *offs = sym->st_value + h->delta;
@@ -374,9 +374,9 @@ int FindR386COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint32_t*
 int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cnt, Elf64_Rel *rel)
 {
     for (int i=0; i<cnt; ++i) {
-        int t = ELF32_R_TYPE(rel[i].r_info);
-        Elf64_Sym *sym = &head->DynSym[ELF32_R_SYM(rel[i].r_info)];
-        int bind = ELF32_ST_BIND(sym->st_info);
+        int t = ELF64_R_TYPE(rel[i].r_info);
+        Elf64_Sym *sym = &head->DynSym[ELF64_R_SYM(rel[i].r_info)];
+        int bind = ELF64_ST_BIND(sym->st_info);
         const char* symname = SymName(head, sym);
         uint32_t ndx = sym->st_shndx;
         uint32_t *p = (uint32_t*)(rel[i].r_offset + head->delta);
@@ -481,7 +481,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
                     }
                     printf_log(LOG_DUMP, "Apply %s R_386_COPY @%p with sym=%s, @%p size=%d (", (bind==STB_LOCAL)?"Local":"Global", p, symname, (void*)offs, sym->st_size);
                     memmove(p, (void*)offs, sym->st_size);
-                    if(LOG_DUMP<=box86_log) {
+                    if(LOG_DUMP<=box64_log) {
                         uint32_t*k = (uint32_t*)p;
                         for (int i=0; i<((sym->st_size>128)?128:sym->st_size); i+=4, ++k)
                             printf_log(LOG_DUMP, "%s0x%08X", i?" ":"", *k);
@@ -574,7 +574,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
                 }
                 break;
             default:
-                printf_log(LOG_INFO, "Warning, don't know of to handle rel #%d %s (%p)\n", i, DumpRelType(ELF32_R_TYPE(rel[i].r_info)), p);
+                printf_log(LOG_INFO, "Warning, don't know of to handle rel #%d %s (%p)\n", i, DumpRelType(ELF64_R_TYPE(rel[i].r_info)), p);
         }
     }
     return 0;
@@ -583,12 +583,12 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
 int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cnt, Elf64_Rela *rela)
 {
     for (int i=0; i<cnt; ++i) {
-        Elf64_Sym *sym = &head->DynSym[ELF32_R_SYM(rela[i].r_info)];
+        Elf64_Sym *sym = &head->DynSym[ELF64_R_SYM(rela[i].r_info)];
         const char* symname = SymName(head, sym);
         uint32_t *p = (uint32_t*)(rela[i].r_offset + head->delta);
         uintptr_t offs = 0;
         uintptr_t end = 0;
-        switch(ELF32_R_TYPE(rela[i].r_info)) {
+        switch(ELF64_R_TYPE(rela[i].r_info)) {
             case R_386_NONE:
             case R_386_PC32:
                 // can be ignored
@@ -607,7 +607,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
                 }
                 break;
             default:
-                printf_log(LOG_INFO, "Warning, don't know of to handle rela #%d %s on %s\n", i, DumpRelType(ELF32_R_TYPE(rela[i].r_info)), symname);
+                printf_log(LOG_INFO, "Warning, don't know of to handle rela #%d %s on %s\n", i, DumpRelType(ELF64_R_TYPE(rela[i].r_info)), symname);
         }
     }
     return 0;
@@ -663,7 +663,7 @@ int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, elfheader_t* head)
    
     return 0;
 }
-
+#endif
 void CalcStack(elfheader_t* elf, uint32_t* stacksz, int* stackalign)
 {
     if(*stacksz < elf->stacksz)
@@ -676,7 +676,7 @@ Elf64_Sym* GetFunction(elfheader_t* h, const char* name)
 {
     // TODO: create a hash on named to avoid this loop
     for (int i=0; i<h->numSymTab; ++i) {
-        int type = ELF32_ST_TYPE(h->SymTab[i].st_info);
+        int type = ELF64_ST_TYPE(h->SymTab[i].st_info);
         if(/*h->SymTab[i].st_info == 18*/type==STT_FUNC) {    // TODO: this "18" is probably defined somewhere
             const char * symname = h->StrTab+h->SymTab[i].st_name;
             if(strcmp(symname, name)==0) {
@@ -690,7 +690,7 @@ Elf64_Sym* GetFunction(elfheader_t* h, const char* name)
 Elf64_Sym* GetElfObject(elfheader_t* h, const char* name)
 {
     for (int i=0; i<h->numSymTab; ++i) {
-        int type = ELF32_ST_TYPE(h->SymTab[i].st_info);
+        int type = ELF64_ST_TYPE(h->SymTab[i].st_info);
         if(/*h->SymTab[i].st_info == 16*/type==STT_OBJECT) {
             const char * symname = h->StrTab+h->SymTab[i].st_name;
             if(strcmp(symname, name)==0) {
@@ -708,12 +708,12 @@ uintptr_t GetFunctionAddress(elfheader_t* h, const char* name)
     if(sym) return sym->st_value;
     return 0;
 }
-
+#if 0
 uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h)
 {
     uintptr_t ep = h->entrypoint + h->delta;
     printf_log(LOG_DEBUG, "Entry Point is %p\n", (void*)ep);
-    if(box86_log>=LOG_DUMP) {
+    if(box64_log>=LOG_DUMP) {
         printf_log(LOG_DUMP, "(short) Dump of Entry point\n");
         int sz = 64;
         uintptr_t lastbyte = GetLastByte(h);
@@ -727,7 +727,7 @@ uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h)
     if(m) {
         ep = m;
         printf_log(LOG_DEBUG, "Using \"main\" as Entry Point @%p\n", ep);
-        if(box86_log>=LOG_DUMP) {
+        if(box64_log>=LOG_DUMP) {
             printf_log(LOG_DUMP, "(short) Dump of Entry point\n");
             int sz = 64;
             uintptr_t lastbyte = GetLastByte(h);
@@ -739,19 +739,19 @@ uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h)
     */
     return ep;
 }
-
+#endif
 uintptr_t GetLastByte(elfheader_t* h)
 {
     return (uintptr_t)h->memory/* + h->delta*/ + h->memsz;
 }
-
+#if 0
 void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h)
 {
     printf_log(LOG_DUMP, "Will look for Symbol to add in SymTable(%d)\n", h->numSymTab);
     for (int i=0; i<h->numSymTab; ++i) {
         const char * symname = h->StrTab+h->SymTab[i].st_name;
-        int bind = ELF32_ST_BIND(h->SymTab[i].st_info);
-        int type = ELF32_ST_TYPE(h->SymTab[i].st_info);
+        int bind = ELF64_ST_BIND(h->SymTab[i].st_info);
+        int type = ELF64_ST_TYPE(h->SymTab[i].st_info);
         int vis = h->SymTab[i].st_other&0x3;
         if((type==STT_OBJECT || type==STT_FUNC || type==STT_COMMON || type==STT_TLS  || type==STT_NOTYPE) 
         && (vis==STV_DEFAULT || vis==STV_PROTECTED) && (h->SymTab[i].st_shndx!=0)) {
@@ -774,8 +774,8 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
     printf_log(LOG_DUMP, "Will look for Symbol to add in DynSym (%d)\n", h->numDynSym);
     for (int i=0; i<h->numDynSym; ++i) {
         const char * symname = h->DynStr+h->DynSym[i].st_name;
-        int bind = ELF32_ST_BIND(h->DynSym[i].st_info);
-        int type = ELF32_ST_TYPE(h->DynSym[i].st_info);
+        int bind = ELF64_ST_BIND(h->DynSym[i].st_info);
+        int type = ELF64_ST_TYPE(h->DynSym[i].st_info);
         int vis = h->DynSym[i].st_other&0x3;
         //st_shndx==65521 means ABS value
         if((type==STT_OBJECT || type==STT_FUNC || type==STT_COMMON || type==STT_TLS  || type==STT_NOTYPE) 
@@ -812,7 +812,7 @@ $PLATFORM – Expands to the processor type of the current machine (see the
 uname(1) man page description of the -i option). For more details of this token
 expansion, see “System Specific Shared Objects”
 */
-int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, int local, box64context_t *box86, x86emu_t* emu)
+int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, int local, box64context_t *box64, x86emu_t* emu)
 {
     DumpDynamicRPath(h);
     // update RPATH first
@@ -852,7 +852,7 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, int
                 printf_log(LOG_INFO, "BOX86: Warning, RPATH with $ variable not supported yet (%s)\n", rpath);
             } else {
                 printf_log(LOG_DEBUG, "Prepending path \"%s\" to BOX86_LD_LIBRARY_PATH\n", rpath);
-                PrependList(&box86->box86_ld_lib, rpath, 1);
+                PrependList(&box64->box64_ld_lib, rpath, 1);
             }
             if(rpath!=rpathref)
                 free(rpath);
@@ -866,7 +866,7 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, int
         if(h->Dynamic[i].d_tag==DT_NEEDED) {
             char *needed = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val;
             // TODO: Add LD_LIBRARY_PATH and RPATH Handling
-            if(AddNeededLib(maplib, neededlibs, local, needed, box86, emu)) {
+            if(AddNeededLib(maplib, neededlibs, local, needed, box64, emu)) {
                 printf_log(LOG_INFO, "Error loading needed lib: \"%s\"\n", needed);
                 if(!allow_missing_libs)
                     return 1;   //error...
@@ -1088,7 +1088,7 @@ dynablocklist_t* GetDynablocksFromAddress(box64context_t *context, uintptr_t add
     if(ret) {
         return ret;
     }*/
-    if(box86_dynarec_forced) {
+    if(box64_dynarec_forced) {
         addDBFromAddressRange(addr, 1);
         return getDB(addr>>DYNAMAP_SHIFT);
     }
@@ -1130,7 +1130,7 @@ static int my_dl_iterate_phdr_##A(struct dl_phdr_info* a, size_t b, void* c)\
 {                                                                           \
     if(!a->dlpi_name)                                                       \
         return 0;                                                           \
-    if(!a->dlpi_name[0]) /*don't send informations about box86 itself*/     \
+    if(!a->dlpi_name[0]) /*don't send informations about box64 itself*/     \
         return 0;                                                           \
     return RunFunction(my_context, my_dl_iterate_phdr_fct_##A, 3, a, b, c); \
 }
@@ -1245,8 +1245,8 @@ EXPORT void PltResolver(x86emu_t* emu)
 
     Elf64_Rel * rel = (Elf64_Rel *)(h->jmprel + h->delta + slot);
 
-    Elf64_Sym *sym = &h->DynSym[ELF32_R_SYM(rel->r_info)];
-    int bind = ELF32_ST_BIND(sym->st_info);
+    Elf64_Sym *sym = &h->DynSym[ELF64_R_SYM(rel->r_info)];
+    int bind = ELF64_ST_BIND(sym->st_info);
     const char* symname = SymName(h, sym);
     uint32_t *p = (uint32_t*)(rel->r_offset + h->delta);
     uintptr_t offs = 0;
diff --git a/src/include/box64stack.h b/src/include/box64stack.h
new file mode 100755
index 00000000..a6b00fea
--- /dev/null
+++ b/src/include/box64stack.h
@@ -0,0 +1,17 @@
+#ifndef __BOX64_STACK_H_
+#define __BOX64_STACK_H_
+
+#include <stdint.h>
+
+typedef struct box64context_s box64context_t;
+//typedef struct x64emu_s x64emu_t;
+
+int CalcStackSize(box64context_t *context);
+//void SetupInitialStack(x64emu_t *emu);
+
+//uint16_t Pop16(x64emu_t *emu);
+//void Push16(x64emu_t *emu, uint16_t v);
+//uint32_t Pop32(x64emu_t *emu);
+//void Push32(x64emu_t *emu, uint32_t v);
+
+#endif //__BOX64_STACK_H_
\ No newline at end of file
diff --git a/src/include/elfloader.h b/src/include/elfloader.h
index 2046865d..28ce4844 100755
--- a/src/include/elfloader.h
+++ b/src/include/elfloader.h
@@ -26,9 +26,9 @@ int LoadElfMemory(FILE* f, box64context_t* context, elfheader_t* head);
 int ReloadElfMemory(FILE* f, box64context_t* context, elfheader_t* head);
 //int RelocateElf(lib_t *maplib, lib_t* local_maplib, elfheader_t* head);
 //int RelocateElfPlt(lib_t *maplib, lib_t* local_maplib, elfheader_t* head);
-//void CalcStack(elfheader_t* h, uint32_t* stacksz, int* stackalign);
+void CalcStack(elfheader_t* h, uint32_t* stacksz, int* stackalign);
 //uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h);
-//uintptr_t GetLastByte(elfheader_t* h);
+uintptr_t GetLastByte(elfheader_t* h);
 //void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h);
 //int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, int local, box64context_t *box86, x86emu_t* emu);
 //uintptr_t GetElfInit(elfheader_t* h);
diff --git a/src/main.c b/src/main.c
index 90f513fd..4d5b7fe8 100755
--- a/src/main.c
+++ b/src/main.c
@@ -16,6 +16,7 @@
 #include "wine_tools.h"
 #include "elfloader.h"
 #include "custommem.h"
+#include "box64stack.h"
 
 box64context_t *my_context = NULL;
 int box64_log = LOG_NONE;
@@ -807,6 +808,14 @@ int main(int argc, const char **argv, const char **env) {
             printf_log(LOG_INFO, "BOX86: Using tcmalloc_minimal.so.4, and it's in the LD_PRELOAD command\n");
         }
     }
+    // get and alloc stack size and align
+    if(CalcStackSize(my_context)) {
+        printf_log(LOG_NONE, "Error: allocating stack\n");
+        free_contextargv();
+        FreeBox64Context(&my_context);
+        FreeCollection(&ld_preload);
+        return -1;
+    }
 
     return 0;
 }
diff --git a/src/tools/box64stack.c b/src/tools/box64stack.c
new file mode 100755
index 00000000..12be1b7d
--- /dev/null
+++ b/src/tools/box64stack.c
@@ -0,0 +1,138 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "box64stack.h"
+#include "box64context.h"
+#include "elfloader.h"
+#include "debug.h"
+//#include "emu/x64emu_private.h"
+//#include "emu/x86run_private.h"
+//#include "auxval.h"
+
+EXPORTDYN
+int CalcStackSize(box64context_t *context)
+{
+    printf_log(LOG_DEBUG, "Calc stack size, based on %d elf(s)\n", context->elfsize);
+    context->stacksz = 8*1024*1024; context->stackalign=4;
+    for (int i=0; i<context->elfsize; ++i)
+        CalcStack(context->elfs[i], &context->stacksz, &context->stackalign);
+
+    if (posix_memalign((void**)&context->stack, context->stackalign, context->stacksz)) {
+        printf_log(LOG_NONE, "Cannot allocate aligned memory (0x%x/0x%x) for stack\n", context->stacksz, context->stackalign);
+        return 1;
+    }
+    memset(context->stack, 0, context->stacksz);
+    printf_log(LOG_DEBUG, "Stack is @%p size=0x%x align=0x%x\n", context->stack, context->stacksz, context->stackalign);
+
+    return 0;
+}
+
+//uint16_t Pop16(x64emu_t *emu)
+//{
+//    uint16_t* st = ((uint16_t*)(R_ESP));
+//    R_ESP += 2;
+//    return *st;
+//}
+
+//void Push16(x64emu_t *emu, uint16_t v)
+//{
+//    R_ESP -= 2;
+//    *((uint16_t*)R_ESP) = v;
+//}
+//uint32_t Pop32(x64emu_t *emu)
+//{
+//    uint32_t* st = ((uint32_t*)(R_ESP));
+//    R_ESP += 4;
+//    return *st;
+//}
+
+//void Push32(x64emu_t *emu, uint32_t v)
+//{
+//    R_ESP -= 4;
+//    *((uint32_t*)R_ESP) = v;
+//}
+
+//void PushString(x64emu_t *emu, const char* s)
+//{
+//    int sz = strlen(s) + 1;
+//    // round to 4 bytes boundary
+//    R_ESP -= sz;
+//    memcpy((void*)R_ESP, s, sz);
+//}
+
+//EXPORTDYN
+//void SetupInitialStack(x64emu_t *emu)
+//{
+//    // start with 0
+//    Push(emu, 0);
+//    // push program executed
+//    PushString(emu, emu->context->argv[0]);
+//    uintptr_t p_arg0 = R_ESP;
+//    // push envs
+//    uintptr_t p_envv[emu->context->envc];
+//    for (int i=emu->context->envc-1; i>=0; --i) {
+//        PushString(emu, emu->context->envv[i]);
+//        p_envv[i] = 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) {
+//        PushString(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 = (R_ESP)&~(emu->context->stackalign-1);
+//    memset((void*)tmp, 0, R_ESP-tmp);
+//    R_ESP=tmp;
+//
+//    // push some AuxVector stuffs
+//    PushString(emu, "i686");
+//    uintptr_t p_386 = R_ESP;
+//    uintptr_t p_random = real_getauxval(25);
+//    if(!p_random) {
+//        for (int i=0; i<4; ++i)
+//            Push(emu, random());
+//        p_random = R_ESP;
+//    }
+//    // align
+//    tmp = (R_ESP)&~(emu->context->stackalign-1);
+//    memset((void*)tmp, 0, R_ESP-tmp);
+//    R_ESP=tmp;
+//
+//    // push the AuxVector themselves
+//    Push(emu, 0); Push(emu, 0);         //AT_NULL(0)=0
+//    Push(emu, p_386); Push(emu, 15);    //AT_PLATFORM(15)=p_386*
+//    Push(emu, 0); Push(emu, 66);        //AT_HWCAP2(26)=0
+//    // 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
+//    Push(emu, (1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<8)  | (1<<15) | (1<<16) | (1<<23) | (1<<25) | (1<<26));
+//    Push(emu, 16);                      //AT_HWCAP(16)=...
+//    Push(emu, p_arg0); Push(emu, 31);   //AT_EXECFN(31)=p_arg0
+//    Push(emu, p_random); Push(emu, 25); //AT_RANDOM(25)=p_random
+//    Push(emu, real_getauxval(23)); Push(emu, 23);        //AT_SECURE(23)=0
+//    Push(emu, real_getauxval(14)); Push(emu, 14);     //AT_EGID(14)
+//    Push(emu, real_getauxval(13)); Push(emu, 13);     //AT_GID(13)
+//    Push(emu, real_getauxval(12)); Push(emu, 12);     //AT_EUID(12)
+//    Push(emu, real_getauxval(11)); Push(emu, 11);     //AT_UID(11)
+//    Push(emu, R_EIP); Push(emu, 9);     //AT_ENTRY(9)=entrypoint
+//    Push(emu, 0/*emu->context->vsyscall*/); Push(emu, 32);      //AT_SYSINFO(32)=vsyscall
+//    if(!emu->context->auxval_start)       // store auxval start if needed
+//        emu->context->auxval_start = (uintptr_t*)R_ESP;
+//    // TODO: continue
+//
+//    // push nil / envs / nil / args / argc
+//    Push(emu, 0);
+//    for (int i=emu->context->envc-1; i>=0; --i)
+//        Push(emu, p_envv[i]);
+//    Push(emu, 0);
+//    for (int i=emu->context->argc-1; i>=0; --i)
+//        Push(emu, p_argv[i]);
+//    Push(emu, emu->context->argc);
+//}
\ No newline at end of file