Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial Android support attempt #372

Merged
merged 1 commit into from
Apr 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 25 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ option(RK3399 "Set to ON if targeting an Rockchip RK3399 based device" ${RK3399}
option(GAMESHELL "Set to ON if targeting a GameShell device" ${GAMESHELL})
option(ODROID "Set to ON if targeting an ODroid device" ${ODROID})
option(POWER9 "Set to ON if targeting a POWER9 processor" ${POWER9})
option(ANDROID "Set to ON if targeting an Android device" ${ANDROID})
option(USE_CCACHE "Set to ON to use ccache if present in the system" ${USE_CCACHE})
option(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${HAVE_TRACE})
option(NOLOADADDR "Set to ON to avoid fixing the load address of Box86" ${NO_LOADAADR})
Expand All @@ -20,6 +21,9 @@ if(PANDORA OR PYRA OR RPI2 OR RPI3 OR RPI4 OR GAMESHELL OR ODROID OR RK3399 OR R
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC ON CACHE BOOL "")
endif()
if(ANDROID)
set(NOLOADADDR ON CACHE BOOL "")
endif()
option(LD80BITS "Set to ON if host device have 80bits long double (i.e. i386)" ${LD80BITS})
option(NOALIGN "Set to ON if host device doesn't need re-align (i.e. i386)" ${NOALIGN})
option(ARM_DYNAREC "Set to ON to use ARM Dynamic Recompilation" ${ARM_DYNAREC})
Expand Down Expand Up @@ -228,7 +232,6 @@ set(ELFLOADER_SRC
"${BOX86_ROOT}/src/libtools/myalign.c"
"${BOX86_ROOT}/src/libtools/myalign64.c"
"${BOX86_ROOT}/src/libtools/myfts.c"
"${BOX86_ROOT}/src/libtools/obstack.c"
"${BOX86_ROOT}/src/libtools/sdl1rwops.c"
"${BOX86_ROOT}/src/libtools/sdl2rwops.c"
"${BOX86_ROOT}/src/libtools/signals.c"
Expand All @@ -237,6 +240,9 @@ set(ELFLOADER_SRC
"${BOX86_ROOT}/src/dynarec/dynarec.c"
"${BOX86_ROOT}/src/wrapped/generated/wrapper.c"
)
if(NOT ANDROID)
set(ELFLOADER_SRC "${BOX86_ROOT}/src/libtools/obstack.c")
endif()

set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedlibc.c"
Expand Down Expand Up @@ -296,9 +302,6 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedopenal.c"
"${BOX86_ROOT}/src/wrapped/wrappedalure.c"
"${BOX86_ROOT}/src/wrapped/wrappedalut.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibjpeg.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibjpeg62.c"
"${BOX86_ROOT}/src/wrapped/wrappedturbojpeg.c"
"${BOX86_ROOT}/src/wrapped/wrappedcurl.c"
"${BOX86_ROOT}/src/wrapped/wrappedudev0.c"
"${BOX86_ROOT}/src/wrapped/wrappedudev1.c"
Expand Down Expand Up @@ -368,6 +371,13 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedldlinux.c"
"${BOX86_ROOT}/src/wrapped/wrappedcrashhandler.c"
)
if(NOT ANDROID)
set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedlibjpeg.c"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

libjpeg is used by wine, so thisone will need to be added at some point

"${BOX86_ROOT}/src/wrapped/wrappedlibjpeg62.c"
"${BOX86_ROOT}/src/wrapped/wrappedturbojpeg.c"
)
endif()

# If BOX86_ROOT contains a ".c", the build breaks...
string(REPLACE ".c" "_private.h" MODROOT ${BOX86_ROOT})
Expand All @@ -385,7 +395,7 @@ add_custom_command(
OUTPUT "${BOX86_ROOT}/src/wrapped/generated/functions_list.txt"
COMMAND "${PYTHON_EXECUTABLE}" "${BOX86_ROOT}/rebuild_wrappers.py"
"${BOX86_ROOT}"
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "POWERPCLE" "--"
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "POWERPCLE" "ANDROID" "--"
${WRAPPEDS_HEAD}
MAIN_DEPENDENCY "${BOX86_ROOT}/rebuild_wrappers.py"
DEPENDS ${WRAPPEDS} ${WRAPPEDS_HEAD}
Expand Down Expand Up @@ -494,7 +504,11 @@ else()
add_library(${BOX86} OBJECT ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX86_ROOT}/src/git_head.h")
endif()
if(ARM_DYNAREC)
target_link_libraries(${BOX86} dynarec m dl rt pthread)
if(ANDROID)
target_link_libraries(${BOX86} dynarec m dl)
else()
target_link_libraries(${BOX86} dynarec m dl rt pthread)
endif()
endif()
if(${CMAKE_VERSION} VERSION_LESS "3.13")
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS -rdynamic)
Expand All @@ -512,7 +526,11 @@ else(BOX86LIB)
add_executable(${BOX86} ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX86_ROOT}/src/git_head.h")
add_dependencies(${BOX86} WRAPPERS)
add_dependencies(${BOX86} PRINTER)
target_link_libraries(${BOX86} m dl rt pthread)
if(ANDROID)
target_link_libraries(${BOX86} m dl)
else()
target_link_libraries(${BOX86} m dl rt pthread)
endif()
if(ARM_DYNAREC)
target_link_libraries(${BOX86} dynarec)
endif()
Expand Down
2 changes: 2 additions & 0 deletions rebuild_wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ def main(root, defines, files, ver):
continue #if !(defined(GO) && defined(GOM)...)
elif preproc_cmd.startswith("error"):
continue #error meh!
elif preproc_cmd.startswith("include"):
continue #inherit other library
elif preproc_cmd.startswith("endif"):
if dependants != []:
dependants.pop()
Expand Down
7 changes: 6 additions & 1 deletion src/elfs/elfloader.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <link.h>
#include <unistd.h>
#include <errno.h>
#include <dlfcn.h>

#include "box86version.h"
#include "elfloader.h"
Expand Down Expand Up @@ -945,6 +946,10 @@ void RunElfFini(elfheader_t* h, x86emu_t *emu)
if(!h || h->fini_done)
return;
h->fini_done = 1;
#ifdef ANDROID
// TODO: Fix .fini_array on Android
printf_log(LOG_DEBUG, "Android does not support Fini for %s\n", ElfName(h));
#else
// first check fini array
Elf32_Addr *addr = (Elf32_Addr*)(h->finiarray + h->delta);
for (int i=0; i<h->finiarray_sz; ++i) {
Expand All @@ -958,7 +963,7 @@ void RunElfFini(elfheader_t* h, x86emu_t *emu)
RunFunctionWithEmu(emu, 0, p, 0);
}
h->init_done = 0; // can be re-inited again...
return;
#endif
}

uintptr_t GetElfInit(elfheader_t* h)
Expand Down
115 changes: 65 additions & 50 deletions src/elfs/elfparser.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,30 +189,71 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
// also grab the DT_STRTAB string table
{
for (int i=0; i<h->numDynamic; ++i) {
if(h->Dynamic[i].d_tag == DT_REL)
h->rel = h->Dynamic[i].d_un.d_ptr;
else if(h->Dynamic[i].d_tag == DT_RELSZ)
h->relsz = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_RELENT)
h->relent = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_RELA)
h->rela = h->Dynamic[i].d_un.d_ptr;
else if(h->Dynamic[i].d_tag == DT_RELASZ)
h->relasz = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_RELAENT)
h->relaent = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_PLTGOT)
h->pltgot = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_PLTREL)
h->pltrel = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_PLTRELSZ)
h->pltsz = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_JMPREL)
h->jmprel = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_STRTAB)
h->DynStrTab = (char*)(h->Dynamic[i].d_un.d_ptr);
else if(h->Dynamic[i].d_tag == DT_STRSZ)
h->szDynStrTab = h->Dynamic[i].d_un.d_val;
Elf32_Dyn d = h->Dynamic[i];
Elf32_Word val = d.d_un.d_val;
Elf32_Addr ptr = d.d_un.d_ptr;
switch (d.d_tag) {
case DT_REL:
h->rel = ptr;
break;
case DT_RELSZ:
h->relsz = val;
break;
case DT_RELENT:
h->relent = val;
break;
case DT_RELA:
h->rela = ptr;
break;
case DT_RELASZ:
h->relasz = val;
break;
case DT_RELAENT:
h->relaent = val;
break;
case DT_PLTGOT:
h->pltgot = val;
break;
case DT_PLTREL:
h->pltrel = val;
break;
case DT_PLTRELSZ:
h->pltsz = val;
break;
case DT_JMPREL:
h->jmprel = val;
break;
case DT_STRTAB:
h->DynStrTab = (char *)(ptr);
break;
case DT_STRSZ:
h->szDynStrTab = val;
break;
case DT_INIT: // Entry point
h->initentry = ptr;
printf_log(LOG_DEBUG, "The DT_INIT is at address %p\n", (void*)h->initentry);
break;
case DT_INIT_ARRAY:
h->initarray = ptr;
printf_log(LOG_DEBUG, "The DT_INIT_ARRAY is at address %p\n", (void*)h->initarray);
break;
case DT_INIT_ARRAYSZ:
h->initarray_sz = val / sizeof(Elf32_Addr);
printf_log(LOG_DEBUG, "The DT_INIT_ARRAYSZ is %d\n", h->initarray_sz);
break;
case DT_FINI: // Exit hook
h->finientry = ptr;
printf_log(LOG_DEBUG, "The DT_FINI is at address %p\n", (void*)h->finientry);
break;
case DT_FINI_ARRAY:
h->finiarray = ptr;
printf_log(LOG_DEBUG, "The DT_FINI_ARRAY is at address %p\n", (void*)h->finiarray);
break;
case DT_FINI_ARRAYSZ:
h->finiarray_sz = val / sizeof(Elf32_Addr);
printf_log(LOG_DEBUG, "The DT_FINI_ARRAYSZ is %d\n", h->finiarray_sz);
break;
}
}
if(h->rel) {
if(h->relent != sizeof(Elf32_Rel)) {
Expand Down Expand Up @@ -270,32 +311,6 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
h->plt_end = h->plt + h->SHEntries[ii].sh_size;
printf_log(LOG_DEBUG, "The PLT Table is at address %p..%p\n", (void*)h->plt, (void*)h->plt_end);
}
// look for .init entry point
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".init");
if(ii) {
h->initentry = h->SHEntries[ii].sh_addr;
printf_log(LOG_DEBUG, "The .init is at address %p\n", (void*)h->initentry);
}
// and .init_array
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".init_array");
if(ii) {
h->initarray_sz = h->SHEntries[ii].sh_size / sizeof(Elf32_Addr);
h->initarray = (uintptr_t)(h->SHEntries[ii].sh_addr);
printf_log(LOG_DEBUG, "The .init_array is at address %p, and have %d elements\n", (void*)h->initarray, h->initarray_sz);
}
// look for .fini entry point
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".fini");
if(ii) {
h->finientry = h->SHEntries[ii].sh_addr;
printf_log(LOG_DEBUG, "The .fini is at address %p\n", (void*)h->finientry);
}
// and .fini_array
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".fini_array");
if(ii) {
h->finiarray_sz = h->SHEntries[ii].sh_size / sizeof(Elf32_Addr);
h->finiarray = (uintptr_t)(h->SHEntries[ii].sh_addr);
printf_log(LOG_DEBUG, "The .fini_array is at address %p, and have %d elements\n", (void*)h->finiarray, h->finiarray_sz);
}
// grab .text for main code
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".text");
if(ii) {
Expand Down
4 changes: 3 additions & 1 deletion src/emu/x86emu.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,8 @@ const char* DumpCPURegs(x86emu_t* emu, uintptr_t ip)
}
sprintf(tmp, "EIP=%08x ", ip);
strcat(buff, tmp);
sprintf(tmp, "[EBP-0x10]=%08x ", *(uint32_t *)(emu->regs[_BP].dword[0]-0x10));
strcat(buff, tmp);
return buff;
}

Expand Down Expand Up @@ -477,4 +479,4 @@ void ResetSegmentsCache(x86emu_t *emu)
if(!emu)
return;
memset(emu->segs_serial, 0, sizeof(emu->segs_serial));
}
}
20 changes: 20 additions & 0 deletions src/emu/x86run_private.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,25 @@
#define PARITY(x) (((emu->x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
#define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)

#ifdef ANDROID
void EXPORT my___libc_init(x86emu_t* emu, void* raw_args __unused, void (*onexit)(void) __unused, int (*main)(int, char**, char**), void const * const structors __unused)
{
//TODO: register fini
// let's cheat and set all args...
Push(emu, (uint32_t)my_context->envv);
Push(emu, (uint32_t)my_context->argv);
Push(emu, (uint32_t)my_context->argc);

printf_log(LOG_DEBUG, "Transfert to main(%d, %p, %p)=>%p from __libc_init\n", my_context->argc, my_context->argv, my_context->envv, main);
// call main and finish
PushExit(emu);
R_EIP=(uint32_t)main;

DynaRun(emu);

emu->quit = 1; // finished!
}
#else
int32_t EXPORT my___libc_start_main(x86emu_t* emu, int *(main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end))
{
//TODO: register rtld_fini
Expand Down Expand Up @@ -54,6 +73,7 @@ int32_t EXPORT my___libc_start_main(x86emu_t* emu, int *(main) (int, char * *, c
emu->quit = 1; // finished!
return 0;
}
#endif

const char* GetNativeName(void* p)
{
Expand Down
3 changes: 3 additions & 0 deletions src/include/myalign.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,11 @@ void AlignSmpegInfo(void* dest, void* source); // x86 -> Arm

// stat64 is packed on i386, not on arm (and possibly other structures)
#undef st_atime
#undef st_atime_nsec
#undef st_mtime
#undef st_mtime_nsec
#undef st_ctime
#undef st_ctime_nsec
struct i386_stat64 {
uint64_t st_dev;
uint8_t __pad0[4];
Expand Down
Loading