about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-07-12 13:43:00 -0500
committerptitSeb <sebastien.chev@gmail.com>2021-07-12 13:43:00 -0500
commita66bb7453b335975ae0f55a96e3f9665139d8024 (patch)
tree55d579ac559eb10542e20e514fc7660d461d8df6 /src
parent5406a040fbf51bec372612a147aea1f80acf97be (diff)
downloadbox64-a66bb7453b335975ae0f55a96e3f9665139d8024.tar.gz
box64-a66bb7453b335975ae0f55a96e3f9665139d8024.zip
Use box86 to launch x86 binary (if box86 is present in same folder as box64)
Diffstat (limited to 'src')
-rwxr-xr-xsrc/include/box64context.h1
-rwxr-xr-xsrc/include/fileutils.h1
-rwxr-xr-xsrc/main.c25
-rwxr-xr-xsrc/tools/fileutils.c18
-rwxr-xr-xsrc/wrapped/wrappedlibc.c58
5 files changed, 74 insertions, 29 deletions
diff --git a/src/include/box64context.h b/src/include/box64context.h
index 0f99d1fe..1fe43d84 100755
--- a/src/include/box64context.h
+++ b/src/include/box64context.h
@@ -82,6 +82,7 @@ typedef struct box64context_s {
 
     char*               fullpath;
     char*               box64path;      // path of current box64 executable
+    char*               box86path;      // path of box86 executable (if present)
 
     uint64_t            stacksz;
     size_t              stackalign;
diff --git a/src/include/fileutils.h b/src/include/fileutils.h
index 546ec9d9..8332681e 100755
--- a/src/include/fileutils.h
+++ b/src/include/fileutils.h
@@ -14,6 +14,7 @@ int FileExist(const char* filename, int flags);
 char* ResolveFile(const char* filename, path_collection_t* paths);
 
 // 1: if file is an x86 elf, 0: if not (or not found)
+int FileIsX86ELF(const char* filename);
 int FileIsX64ELF(const char* filename);
 
 #if defined(RPI) || defined(RK3399) || defined(RK3326)
diff --git a/src/main.c b/src/main.c
index 266fa96b..10a505c7 100755
--- a/src/main.c
+++ b/src/main.c
@@ -817,7 +817,16 @@ int main(int argc, const char **argv, const char **env) {
         my_context->argv[0] = strdup(prog);
     else
         my_context->argv[0] = ResolveFile(prog, &my_context->box64_path);
-
+    // check if box86 is present
+    {
+        my_context->box86path = strdup(my_context->box64path);
+        char* p = strrchr(my_context->box86path, '6');  // get the 8 of box86
+        p[0] = '8'; p[1] = '6'; // change 64 to 86
+        if(!FileExist(my_context->box86path, IS_FILE)) {
+            free(my_context->box86path);
+            my_context->box86path = NULL;
+        }
+    }
     const char* prgname = strrchr(prog, '/');
     if(!prgname)
         prgname = prog;
@@ -894,12 +903,22 @@ int main(int argc, const char **argv, const char **env) {
     }
     elfheader_t *elf_header = LoadAndCheckElfHeader(f, my_context->argv[0], 1);
     if(!elf_header) {
-        printf_log(LOG_NONE, "Error: reading elf header of %s, try to launch natively instead\n", my_context->argv[0]);
+        int x86 = my_context->box86path?FileIsX86ELF(my_context->argv[0]):0;
+        printf_log(LOG_NONE, "Error: reading elf header of %s, try to launch %s instead\n", my_context->argv[0], x86?"using box86":"natively");
         fclose(f);
         free_contextargv();
         FreeBox64Context(&my_context);
         FreeCollection(&ld_preload);
-        return execvp(argv[1], (char * const*)(argv+1));
+        if(x86) {
+            // duplicate the array to change 1st arg as box86
+            const char** newargv = (const char**)calloc(argc+1, sizeof(char*));
+            newargv[0] = my_context->box86path;
+            for(int i=1; i<argc; ++i)
+                newargv[i] = argv[i];
+            return execvp(newargv[0], (char * const*)newargv);
+        } else
+            return execvp(argv[1], (char * const*)(argv+1));
+        printf_log(LOG_NONE, "Failed to execvp: error is %s\n", strerror(errno));
     }
     AddElfHeader(my_context, elf_header);
 
diff --git a/src/tools/fileutils.c b/src/tools/fileutils.c
index 18b8dc4d..fa57cd69 100755
--- a/src/tools/fileutils.c
+++ b/src/tools/fileutils.c
@@ -15,6 +15,7 @@
 #include "debug.h"
 #include "fileutils.h"
 
+static const char* x86sign = "\x7f" "ELF" "\x01" "\x01" "\x01" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x02" "\x00" "\x03" "\x00";
 static const char* x64sign = "\x7f" "ELF" "\x02" "\x01" "\x01" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x02" "\x00" "\x3e" "\x00";
 
 int FileExist(const char* filename, int flags)
@@ -77,6 +78,23 @@ int FileIsX64ELF(const char* filename)
     return 0;
 }
 
+int FileIsX86ELF(const char* filename)
+{
+    FILE *f = fopen(filename, "rb");
+    if(!f)
+        return 0;
+    char head[sizeof(*x86sign)] = {0};
+    int sz = fread(head, sizeof(*x86sign), 1, f);
+    if(sz!=1) {
+        fclose(f);
+        return 0;
+    }
+    fclose(f);
+    if(memcmp(head, x86sign, sizeof(*x86sign))==0)
+        return 1;
+    return 0;
+}
+
 #if defined(RPI) || defined(RK3399) || defined(RK3326)
 void sanitize_mojosetup_gtk_background()
 {
diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c
index b4bfe2d1..c11a27e3 100755
--- a/src/wrapped/wrappedlibc.c
+++ b/src/wrapped/wrappedlibc.c
@@ -1539,10 +1539,11 @@ EXPORT int32_t my_nftw64(x64emu_t* emu, void* pathname, void* B, int32_t nopenfd
 EXPORT int32_t my_execv(x64emu_t* emu, const char* path, char* const argv[])
 {
     int self = isProcSelf(path, "exe");
-    int x86 = FileIsX64ELF(path);
-    printf_log(LOG_DEBUG, "execv(\"%s\", %p) is x86=%d\n", path, argv, x86);
+    int x64 = FileIsX64ELF(path);
+    int x86 = my_context->box86path?FileIsX86ELF(path):0;
+    printf_log(LOG_DEBUG, "execv(\"%s\", %p) is x64=%d\n", path, argv, x64);
     #if 1
-    if (x86 || self) {
+    if (x64 || x86 || self) {
         int skip_first = 0;
         if(strlen(path)>=strlen("wine64-preloader") && strcmp(path+strlen(path)-strlen("wine64-preloader"), "wine64-preloader")==0)
             skip_first++;
@@ -1550,7 +1551,7 @@ EXPORT int32_t my_execv(x64emu_t* emu, const char* path, char* const argv[])
         int n=skip_first;
         while(argv[n]) ++n;
         const char** newargv = (const char**)calloc(n+2, sizeof(char*));
-        newargv[0] = emu->context->box64path;
+        newargv[0] = x86?emu->context->box86path:emu->context->box64path;
         memcpy(newargv+1, argv+skip_first, sizeof(char*)*(n+1));
         if(self) newargv[1] = emu->context->fullpath;
         printf_log(LOG_DEBUG, " => execv(\"%s\", %p [\"%s\", \"%s\", \"%s\"...:%d])\n", emu->context->box64path, newargv, newargv[0], n?newargv[1]:"", (n>1)?newargv[2]:"",n);
@@ -1565,10 +1566,11 @@ EXPORT int32_t my_execv(x64emu_t* emu, const char* path, char* const argv[])
 EXPORT int32_t my_execve(x64emu_t* emu, const char* path, char* const argv[], char* const envp[])
 {
     int self = isProcSelf(path, "exe");
-    int x86 = FileIsX64ELF(path);
-    printf_log(LOG_DEBUG, "execv(\"%s\", %p) is x86=%d\n", path, argv, x86);
+    int x64 = FileIsX64ELF(path);
+    int x86 = my_context->box86path?FileIsX86ELF(path):0;
+    printf_log(LOG_DEBUG, "execv(\"%s\", %p) is x64=%d\n", path, argv, x64);
     #if 1
-    if (x86 || self) {
+    if (x64 || x86 || self) {
         int skip_first = 0;
         if(strlen(path)>=strlen("wine64-preloader") && strcmp(path+strlen(path)-strlen("wine64-preloader"), "wine64-preloader")==0)
             skip_first++;
@@ -1576,7 +1578,7 @@ EXPORT int32_t my_execve(x64emu_t* emu, const char* path, char* const argv[], ch
         int n=skip_first;
         while(argv[n]) ++n;
         const char** newargv = (const char**)calloc(n+2, sizeof(char*));
-        newargv[0] = emu->context->box64path;
+        newargv[0] = x86?emu->context->box86path:emu->context->box64path;
         memcpy(newargv+1, argv+skip_first, sizeof(char*)*(n+1));
         if(self) newargv[1] = emu->context->fullpath;
         printf_log(LOG_DEBUG, " => execv(\"%s\", %p [\"%s\", \"%s\", \"%s\"...:%d])\n", emu->context->box64path, newargv, newargv[0], n?newargv[1]:"", (n>1)?newargv[2]:"",n);
@@ -1597,15 +1599,16 @@ EXPORT int32_t my_execvp(x64emu_t* emu, const char* path, char* const argv[])
         fullpath = strdup(path);
     // use fullpath...
     int self = isProcSelf(fullpath, "exe");
-    int x86 = FileIsX64ELF(fullpath);
-    printf_log(LOG_DEBUG, "execvp(\"%s\", %p), IsX86=%d / fullpath=\"%s\"\n", path, argv, x86, fullpath);
+    int x64 = FileIsX64ELF(fullpath);
+    int x86 = my_context->box86path?FileIsX86ELF(path):0;
+    printf_log(LOG_DEBUG, "execvp(\"%s\", %p), IsX86=%d / fullpath=\"%s\"\n", path, argv, x64, fullpath);
     free(fullpath);
-    if (x86 || self) {
+    if (x64 || x86 || self) {
         // count argv...
         int i=0;
         while(argv[i]) ++i;
         char** newargv = (char**)calloc(i+2, sizeof(char*));
-        newargv[0] = emu->context->box64path;
+        newargv[0] = x86?emu->context->box86path:emu->context->box64path;
         for (int j=0; j<i; ++j)
             newargv[j+1] = argv[j];
         if(self) newargv[1] = emu->context->fullpath;
@@ -1621,15 +1624,16 @@ EXPORT int32_t my_execvp(x64emu_t* emu, const char* path, char* const argv[])
 EXPORT int32_t my_execl(x64emu_t* emu, const char* path)
 {
     int self = isProcSelf(path, "exe");
-    int x86 = FileIsX64ELF(path);
-    printf_log(LOG_DEBUG, "execl(\"%s\", ...), IsX86=%d, self=%d\n", path, x86, self);
+    int x64 = FileIsX64ELF(path);
+    int x86 = my_context->box86path?FileIsX86ELF(path):0;
+    printf_log(LOG_DEBUG, "execl(\"%s\", ...), IsX86=%d, self=%d\n", path, x64, self);
     // count argv...
     int i=0;
     while(getVargN(emu, i+1)) ++i;
-    char** newargv = (char**)calloc(i+((x86 || self)?2:1), sizeof(char*));
+    char** newargv = (char**)calloc(i+((x64 || self)?2:1), sizeof(char*));
     int j=0;
-    if ((x86 || self))
-        newargv[j++] = emu->context->box64path;
+    if ((x64 || x86 || self))
+        newargv[j++] = x86?emu->context->box86path:emu->context->box64path;
     for (int k=0; k<i; ++k)
         newargv[j++] = getVargN(emu, k+1);
     if(self) newargv[1] = emu->context->fullpath;
@@ -1647,16 +1651,17 @@ EXPORT int32_t my_execlp(x64emu_t* emu, const char* path)
         fullpath = strdup(path);
     // use fullpath...
     int self = isProcSelf(fullpath, "exe");
-    int x86 = FileIsX64ELF(fullpath);
-    printf_log(LOG_DEBUG, "execlp(\"%s\", ...), IsX86=%d / fullpath=\"%s\"\n", path, x86, fullpath);
+    int x64 = FileIsX64ELF(fullpath);
+    int x86 = my_context->box86path?FileIsX86ELF(path):0;
+    printf_log(LOG_DEBUG, "execlp(\"%s\", ...), IsX86=%d / fullpath=\"%s\"\n", path, x64, fullpath);
     free(fullpath);
     // count argv...
     int i=0;
     while(getVargN(emu, i+1)) ++i;
-    char** newargv = (char**)calloc(i+((x86 || self)?2:1), sizeof(char*));
+    char** newargv = (char**)calloc(i+((x64 || self)?2:1), sizeof(char*));
     int j=0;
-    if ((x86 || self))
-        newargv[j++] = emu->context->box64path;
+    if ((x64 || x86 || self))
+        newargv[j++] = x86?emu->context->box86path:emu->context->box64path;
     for (int k=0; k<i; ++k)
         newargv[j++] = getVargN(emu, k+1);
     if(self) newargv[1] = emu->context->fullpath;
@@ -1675,15 +1680,16 @@ EXPORT int32_t my_posix_spawnp(x64emu_t* emu, pid_t* pid, const char* path,
     char* fullpath = ResolveFile(path, &my_context->box64_path);
     // use fullpath...
     int self = isProcSelf(fullpath, "exe");
-    int x86 = FileIsX64ELF(fullpath);
-    printf_log(LOG_DEBUG, "posix_spawnp(%p, \"%s\", %p, %p, %p, %p), IsX86=%d / fullpath=\"%s\"\n", pid, path, actions, attrp, argv, envp, x86, fullpath);
+    int x64 = FileIsX64ELF(fullpath);
+    int x86 = my_context->box86path?FileIsX86ELF(path):0;
+    printf_log(LOG_DEBUG, "posix_spawnp(%p, \"%s\", %p, %p, %p, %p), IsX86=%d / fullpath=\"%s\"\n", pid, path, actions, attrp, argv, envp, x64, fullpath);
     free(fullpath);
-    if ((x86 || self)) {
+    if (x64 || x86 || self) {
         // count argv...
         int i=0;
         while(argv[i]) ++i;
         char** newargv = (char**)calloc(i+2, sizeof(char*));
-        newargv[0] = emu->context->box64path;
+        newargv[0] = x86?emu->context->box86path:emu->context->box64path;
         for (int j=0; j<i; ++j)
             newargv[j+1] = argv[j];
         if(self) newargv[1] = emu->context->fullpath;