diff --git a/CMakeLists.txt b/CMakeLists.txt index c74391b616..2f1f42133b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -387,6 +387,7 @@ set(BOX64_ROOT ${CMAKE_SOURCE_DIR}) add_definitions(-std=gnu11 -funwind-tables -fvisibility=hidden) add_definitions(-D_GNU_SOURCE=1) add_definitions(-D_FILE_OFFSET_BITS=64) +list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE) if(USE_CCACHE) find_program(CCACHE_FOUND ccache) @@ -418,6 +419,193 @@ add_custom_target(generate_dynacache_hashes VERBATIM ) +include(CheckIncludeFile) + +set(PROJECT_HEADERS + execinfo.h +) + +foreach(header IN LISTS PROJECT_HEADERS) + string(MAKE_C_IDENTIFIER "${header}" header_ident) + string(TOUPPER "${header_ident}" header_ident) + + set(var "HAVE_${header_ident}") + + check_include_file("${header}" "${var}") + + if(${var}) + add_compile_definitions("${var}=1") + endif() +endforeach() + +if(HAVE_EXECINFO_H AND NOT ANDROID) + add_compile_definitions(USE_BACKTRACE) +endif() + +include(CheckSymbolExists) + +set(PROJECT_SYMBOL_CHECKS + mallopt malloc.h + malloc_trim malloc.h + mallinfo malloc.h + mallinfo2 malloc.h + _pthread_cleanup_push pthread.h + _pthread_cleanup_pop pthread.h + pthread_attr_getaffinity_np pthread.h + pthread_attr_setaffinity_np pthread.h + pthread_mutexattr_setprioceiling pthread.h + dlvsym dlfcn.h + obstack_vprintf stdio.h + getprotobyname_r netdb.h + getprotobynumber_r netdb.h + scandirat dirent.h +) + +list(LENGTH PROJECT_SYMBOL_CHECKS checks_len) +math(EXPR checks_last "${checks_len} - 1") + +foreach(i RANGE 0 ${checks_last} 2) + math(EXPR j "${i} + 1") + + list(GET PROJECT_SYMBOL_CHECKS ${i} symbol) + list(GET PROJECT_SYMBOL_CHECKS ${j} header) + + string(MAKE_C_IDENTIFIER "${symbol}" symbol_ident) + string(TOUPPER "${symbol_ident}" symbol_ident) + + set(var "HAVE_${symbol_ident}") + + set(headers "${header}") + check_symbol_exists("${symbol}" "${headers}" "${var}") + + if(${var}) + add_compile_definitions("${var}=1") + endif() +endforeach() + +include(CheckFunctionExists) + +set(PROJECT_FUNCTION_CHECKS + __chk_fail +) + +foreach(function IN LISTS PROJECT_FUNCTION_CHECKS) + string(MAKE_C_IDENTIFIER "${function}" function_ident) + string(TOUPPER "${function_ident}" function_ident) + + set(var "HAVE_${function_ident}") + + check_function_exists("${function}" "${var}") + + if(${var}) + add_compile_definitions("${var}=1") + endif() +endforeach() + +include(CheckCSourceCompiles) + +check_c_source_compiles("#include +int main(void){ struct obstack o = { .temp.tempptr = NULL }; return 0; }" OBSTACK_TEMP_TEMPPTR) +check_c_source_compiles("#include +int main(void){ struct obstack o = { .temp.p = NULL }; return 0; }" OBSTACK_TEMP_P) + +if(OBSTACK_TEMP_TEMPPTR) # glibc + add_compile_definitions("STRUCT_OBSTACK_TEMP=tempptr") + add_compile_definitions("STRUCT_OBSTACK_CHUNKFUN=chunkfun") + add_compile_definitions("STRUCT_OBSTACK_FREEFUN=freefun") +elseif(OBSTACK_TEMP_P) # musl-obstack + add_compile_definitions("STRUCT_OBSTACK_TEMP=p") + add_compile_definitions("STRUCT_OBSTACK_CHUNKFUN=chunkfun.extra") + add_compile_definitions("STRUCT_OBSTACK_FREEFUN=freefun.extra") +elseif(NOT ANDROID) + message(FATAL_ERROR "Unknown struct obstack layout!") +endif() + +check_c_source_compiles("#include +int main(void){ siginfo_t s = { ._sifields = { 0 } }; return 0; }" SIGINFO_S__SIFIELDS) +check_c_source_compiles("#include +int main(void){ siginfo_t s = { .__si_fields = { 0 } }; return 0; }" SIGINFO_S___SI_FIELDS) + +if(SIGINFO_S__SIFIELDS) # glibc + add_compile_definitions("SIGINFO_S_SIFIELDS=_sifields") +elseif(SIGINFO_S___SI_FIELDS) # musl + add_compile_definitions("SIGINFO_S_SIFIELDS=__si_fields") +elseif(NOT ANDROID) + message(FATAL_ERROR "Unknown siginfo_t layout!") +endif() + +check_c_source_compiles("#include +int main(void){ struct __res_state r = { .__glibc_unused_qhook = NULL }; return 0; }" RES_STATE_GLIBC_UNUSED_QHOOK) +check_c_source_compiles("#include +int main(void){ struct __res_state r = { .qhook = NULL }; return 0; }" RES_STATE_QHOOK) + +if(RES_STATE_GLIBC_UNUSED_QHOOK) # glibc + add_compile_definitions("RES_STATE_QHOOK=__glibc_unused_qhook") + add_compile_definitions("RES_STATE_RHOOK=__glibc_unused_rhook") +elseif(RES_STATE_QHOOK) # musl + add_compile_definitions("RES_STATE_QHOOK=qhook") + add_compile_definitions("RES_STATE_RHOOK=rhook") +elseif(NOT ANDROID) + message(FATAL_ERROR "Unknown res_state layout!") +endif() + +check_c_source_compiles("#include +int main(void){ return &__ctype_b_loc == 0; }" CTYPE_B_LOC) +check_c_source_compiles("#include +extern const unsigned short int **__ctype_b_loc(void); +int main(void){ __ctype_b_loc(); return 0; }" CTYPE_B_LOC_EXT) + +if(CTYPE_B_LOC) # glibc + add_compile_definitions("HAVE_CTYPE_B_LOC") +elseif(CTYPE_B_LOC_EXT) # musl + add_compile_definitions("HAVE_CTYPE_B_LOC") + add_compile_definitions("HAVE_CTYPE_B_LOC_EXT") +endif() + +check_c_source_compiles("#include +int main(void){ glob_t g = { .gl_flags = 0 }; return 0; }" GLOB_T_GL_FLAGS) +check_c_source_compiles("#include +int main(void){ glob_t g = { .__dummy1 = 0 }; return 0; }" GLOB_T_DUMMY) + +if(GLOB_T_GL_FLAGS) # glibc + add_compile_definitions("GLOB_T_GL_FLAGS=gl_flags") + add_compile_definitions("GLOB_T_GL_CLOSEDIR=gl_closedir") + add_compile_definitions("GLOB_T_GL_READDIR=gl_readdir") + add_compile_definitions("GLOB_T_GL_OPENDIR=gl_opendir") + add_compile_definitions("GLOB_T_GL_LSTAT=gl_lstat") + add_compile_definitions("GLOB_T_GL_STAT=gl_stat") +elseif(GLOB_T_DUMMY) # musl + add_compile_definitions("GLOB_T_GL_FLAGS=__dummy1") + add_compile_definitions("GLOB_T_GL_CLOSEDIR=__dummy2[0]") + add_compile_definitions("GLOB_T_GL_READDIR=__dummy2[1]") + add_compile_definitions("GLOB_T_GL_OPENDIR=__dummy2[2]") + add_compile_definitions("GLOB_T_GL_LSTAT=__dummy2[3]") + add_compile_definitions("GLOB_T_GL_STAT=__dummy2[4]") +elseif(NOT ANDROID) + message(FATAL_ERROR "Unknown glob_t layout!") +endif() + +check_c_source_compiles("#include +int main(void){ posix_spawn_file_actions_t a = { .__allocated = 0 }; return 0; }" + POSIX_SPAWN_FILE_ACTIONS_T__ALLOCATED) +check_c_source_compiles("#include +int main(void){ posix_spawn_file_actions_t a = { .__pad0 = {0} }; return 0; }" + POSIX_SPAWN_FILE_ACTIONS_T__PAD0) + +if(POSIX_SPAWN_FILE_ACTIONS_T__ALLOCATED) # glibc + add_compile_definitions("POSIX_SPAWN_FILE_ACTIONS_T__ALLOCATED=__allocated") + add_compile_definitions("POSIX_SPAWN_FILE_ACTIONS_T__USED=__used") + add_compile_definitions("POSIX_SPAWN_FILE_ACTIONS_T__ACTIONS=__actions") + add_compile_definitions("POSIX_SPAWN_FILE_ACTIONS_T__PAD=__pad") +elseif(POSIX_SPAWN_FILE_ACTIONS_T__PAD0) # musl + add_compile_definitions("POSIX_SPAWN_FILE_ACTIONS_T__ALLOCATED=__pad0[0]") + add_compile_definitions("POSIX_SPAWN_FILE_ACTIONS_T__USED=__pad0[1]") + add_compile_definitions("POSIX_SPAWN_FILE_ACTIONS_T__ACTIONS=__actions") + add_compile_definitions("POSIX_SPAWN_FILE_ACTIONS_T__PAD=__pad") +elseif(NOT ANDROID) + message(FATAL_ERROR "Unknown posix_spawn_file_actions_t layout!") +endif() + # generated files set_source_files_properties( "${BOX64_ROOT}/src/git_head.h" @@ -477,6 +665,7 @@ set(ELFLOADER_SRC "${BOX64_ROOT}/src/libtools/syscall_user_dispatch.c" "${BOX64_ROOT}/src/libtools/decopcode.c" "${BOX64_ROOT}/src/libtools/threads.c" + "${BOX64_ROOT}/src/libtools/libc.c" "${BOX64_ROOT}/src/steamwebhelper.c" "${BOX64_ROOT}/src/tools/bitutils.c" "${BOX64_ROOT}/src/tools/box64stack.c" diff --git a/src/include/libc_ctype.h b/src/include/libc_ctype.h new file mode 100644 index 0000000000..2563ee0504 --- /dev/null +++ b/src/include/libc_ctype.h @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +#ifndef _BOX64_LIBC_CTYPE_H_ +#define _BOX64_LIBC_CTYPE_H_ + +#ifdef HAVE_CTYPE_B_LOC_EXT + +#include + +const unsigned short **__ctype_b_loc(void); +const int32_t **__ctype_tolower_loc(void); +const int32_t **__ctype_toupper_loc(void); +#endif + +#endif \ No newline at end of file diff --git a/src/include/libc_dirent.h b/src/include/libc_dirent.h new file mode 100644 index 0000000000..807f3b68a9 --- /dev/null +++ b/src/include/libc_dirent.h @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +#ifndef _BOX64_LIBC_DIRENT_H_ +#define _BOX64_LIBC_DIRENT_H_ + +#ifndef HAVE_SCANDIRAT +int scandirat(int dirfd, const char *dirp, struct dirent ***namelist, + int (*filter)(const struct dirent *),int (*compar)(const struct dirent**, const struct dirent **)); +#endif + +#endif \ No newline at end of file diff --git a/src/include/libc_glob.h b/src/include/libc_glob.h new file mode 100644 index 0000000000..d3f7430d07 --- /dev/null +++ b/src/include/libc_glob.h @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +#ifndef _BOX64_LIBC_GLOB_H_ +#define _BOX64_LIBC_GLOB_H_ + +#ifndef GLOB_APPEND +#define GLOB_APPEND (1 << 5) +#endif + +#ifndef GLOB_ALTDIRFUNC +# define GLOB_ALTDIRFUNC (1 << 9) +#endif + +#endif \ No newline at end of file diff --git a/src/include/libc_malloc.h b/src/include/libc_malloc.h new file mode 100644 index 0000000000..153268598b --- /dev/null +++ b/src/include/libc_malloc.h @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +#ifndef _BOX64_LIBC_MALLOC_H_ +#define _BOX64_LIBC_MALLOC_H_ + +#ifndef HAVE_MALLINFO +struct mallinfo { + int arena; + int ordblks; + int smblks; + int hblks; + int hblkhd; + int usmblks; + int fsmblks; + int uordblks; + int fordblks; + int keepcost; +}; +#endif + +#ifndef HAVE_MALLINFO2 +struct mallinfo2 { + size_t arena; + size_t ordblks; + size_t smblks; + size_t hblks; + size_t hblkhd; + size_t usmblks; + size_t fsmblks; + size_t uordblks; + size_t fordblks; + size_t keepcost; +}; +#endif + +#endif \ No newline at end of file diff --git a/src/include/libc_netdb.h b/src/include/libc_netdb.h new file mode 100644 index 0000000000..8656b08d21 --- /dev/null +++ b/src/include/libc_netdb.h @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +#ifndef _BOX64_LIBC_NETDB_H_ +#define _BOX64_LIBC_NETDB_H_ + +#ifndef HAVE_GETPROTOBYNAME_R +int getprotobyname_r(const char *name, struct protoent *result_buf, char *buf, size_t buflen, struct protoent **result); +#endif + +#ifndef HAVE_GETPROTOBYNUMBER_R +int getprotobynumber_r(int proto, struct protoent *result_buf, char *buf, size_t buflen, struct protoent **result); +#endif + +#endif \ No newline at end of file diff --git a/src/include/libc_obstack.h b/src/include/libc_obstack.h new file mode 100644 index 0000000000..690ba0dd7f --- /dev/null +++ b/src/include/libc_obstack.h @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT +#ifndef _BOX64_LIBC_OBSTACK_H_ +#define _BOX64_LIBC_OBSTACK_H_ + +#ifndef HAVE_OBSTACK_VPRINTF +int obstack_vprintf(struct obstack *obstack, const char *fmt, va_list args); +#endif + +#endif \ No newline at end of file diff --git a/src/include/libc_select.h b/src/include/libc_select.h new file mode 100644 index 0000000000..629a656e77 --- /dev/null +++ b/src/include/libc_select.h @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +#ifndef _BOX64_LIBC_SELECT_H_ +#define _BOX64_LIBC_SELECT_H_ + +#ifndef __NFDBITS +#ifdef NFDBITS +#define __NFDBITS NFDBITS +#else +#error NFDBITS not defined by libc +#endif +#endif + +#endif \ No newline at end of file diff --git a/src/include/mydlfcn.h b/src/include/mydlfcn.h new file mode 100644 index 0000000000..cd743dd043 --- /dev/null +++ b/src/include/mydlfcn.h @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +#ifndef __MYDLFCN_H_ +#define __MYDLFCN_H_ + +#include + +#ifndef RTLD_DL_SYMENT +#define RTLD_DL_SYMENT 1 +#endif +#ifndef RTLD_DL_LINKMAP +#define RTLD_DL_LINKMAP 2 +#endif + +#endif // __MYDLFCN_H_ \ No newline at end of file diff --git a/src/include/signals.h b/src/include/signals.h index 23626a3cfd..fd12b57292 100644 --- a/src/include/signals.h +++ b/src/include/signals.h @@ -6,6 +6,10 @@ #include "x64_signals.h" #include "box64context.h" +#ifndef __SI_SIGFAULT_ADDL +#define __SI_SIGFAULT_ADDL +#endif + typedef void (*sighandler_t)(int); #ifdef ANDROID diff --git a/src/libtools/libc.c b/src/libtools/libc.c new file mode 100644 index 0000000000..071ccd3bec --- /dev/null +++ b/src/libtools/libc.c @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: MIT +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#if !defined(HAVE_OBSTACK_VPRINTF) && !defined(ANDROID) +#include + +int obstack_vprintf(struct obstack *obstack, const char *fmt, va_list args) +{ + char buffer[200]; + char *buf = buffer; + va_list copy; + + va_copy(copy, args); + int len = vsnprintf(buffer, sizeof(buffer), fmt, copy); + va_end(copy); + + if (len < 0) return -1; + + if ((size_t)len >= sizeof(buffer)) + { + buf = malloc((size_t)len + 1); + if (!buf) return -1; + + va_copy(copy, args); + int n = vsnprintf(buf, len + 1, fmt, copy); + va_end(copy); + + if (n != len) + { + free(buf); + return -1; + } + len = n; + } + + if(len > 0) obstack_grow(obstack, buf, len); + if(buf != buffer) free(buf); + + return len; +} +#endif + +#if ! defined(HAVE_GETPROTOBYNAME_R) || ! defined(HAVE_GETPROTOBYNUMBER_R) + +static pthread_mutex_t mutex_getproto = PTHREAD_MUTEX_INITIALIZER; + +static int copyprotoent(const struct protoent *src, struct protoent *result_buf, char *buf, size_t buflen, struct protoent **result) +{ + size_t size_buf = 0; + char *ptr = buf; + *result = NULL; + + if(!src) return 0; + + // official protocol name + size_t size_name = (strlen(src->p_name) + 1) * sizeof(char); + size_buf += size_name; + if(size_buf > buflen) return ERANGE; + memcpy(ptr, src->p_name, size_name); + result_buf->p_name = ptr; + ptr += size_name; + + // padding + size_t align = _Alignof(char *); + size_t pad_len = (align - (uintptr_t)ptr % align) % align; + size_buf += pad_len; + if(size_buf > buflen) return ERANGE; + ptr += pad_len; + + // alias list + size_t num_aliases = 0; + while(src->p_aliases[num_aliases]) num_aliases++; + size_t size_aliases = (num_aliases + 1) * sizeof(char*); + size_buf += size_aliases; + if(size_buf > buflen) return ERANGE; + char **aliases = (char **) ptr; + aliases[num_aliases] = NULL; + result_buf->p_aliases = aliases; + ptr += size_aliases; + + // aliases + for(size_t i = 0; i < num_aliases; i++) + { + size_t size_alias = (strlen(src->p_aliases[i]) + 1) * sizeof(char); + size_buf += size_alias; + if(size_buf > buflen) return ERANGE; + memcpy(ptr, src->p_aliases[i], size_alias); + aliases[i] = ptr; + ptr += size_alias; + } + + // protocol number + result_buf->p_proto = src->p_proto; + + // done + *result = result_buf; + return 0; +} + +#ifndef HAVE_GETPROTOBYNAME_R +int getprotobyname_r(const char *name, struct protoent *result_buf, char *buf, size_t buflen, struct protoent **result) +{ + pthread_mutex_lock(&mutex_getproto); + int res = copyprotoent(getprotobyname(name), result_buf, buf, buflen, result); + pthread_mutex_unlock(&mutex_getproto); + return res; +} +#endif + +#ifndef HAVE_GETPROTOBYNUMBER_R +int getprotobynumber_r(int proto, struct protoent *result_buf, char *buf, size_t buflen, struct protoent **result) +{ + pthread_mutex_lock(&mutex_getproto); + int res = copyprotoent(getprotobynumber(proto), result_buf, buf, buflen, result); + pthread_mutex_unlock(&mutex_getproto); + return res; +} +#endif +#endif + + +#ifndef HAVE_SCANDIRAT + +// Copyright (c) 2015-2016 Nuxi, https://nuxi.nl/ +// SPDX-License-Identifier: BSD-2-Clause +// https://github.com/WebAssembly/wasi-libc/blob/main/libc-bottom-half/cloudlibc/src/libc/dirent/scandirat.c +int scandirat(int dirfd, const char *dir, struct dirent ***res, + int (*sel)(const struct dirent *), + int (*cmp)(const struct dirent **, const struct dirent **)) +{ + dirfd = openat(dirfd, dir, O_RDONLY | O_DIRECTORY | O_CLOEXEC); + if (dirfd < 0) { + return -1; + } + + DIR *d = fdopendir(dirfd); + struct dirent *de, **names=0, **tmp; + size_t cnt=0, len=0; + int old_errno = errno; + + if (!d) { + close(dirfd); + return -1; + } + + while ((errno=0), (de = readdir(d))) { + if (sel && !sel(de)) continue; + if (cnt >= len) { + len = 2*len+1; + if (len > SIZE_MAX/sizeof *names) break; + tmp = realloc(names, len * sizeof *names); + if (!tmp) break; + names = tmp; + } + size_t size = de->d_reclen; + names[cnt] = malloc(size); + if (!names[cnt]) break; + memcpy(names[cnt++], de, size); + } + + closedir(d); + + if (errno) { + if (names) while (cnt-->0) free(names[cnt]); + free(names); + return -1; + } + errno = old_errno; + + if (cmp) qsort(names, cnt, sizeof *names, (int (*)(const void *, const void *))cmp); + *res = names; + return cnt; +} +#endif diff --git a/src/libtools/libc_net32.c b/src/libtools/libc_net32.c index aac38a317a..60afaa9636 100644 --- a/src/libtools/libc_net32.c +++ b/src/libtools/libc_net32.c @@ -39,6 +39,7 @@ #include "box32.h" #include "converter32.h" #include "custommem.h" +#include "libc_netdb.h" EXPORT ssize_t my32_recvmsg(x64emu_t* emu, int socket, struct i386_msghdr* msg, int flags) { @@ -598,8 +599,8 @@ void* convert_res_state_to_32(void* d, void* s) dst->ipv6_unavail = src->ipv6_unavail; dst->unused = src->unused; memmove(dst->sort_list, src->sort_list, sizeof(dst->sort_list)); - dst->__glibc_unused_qhook = to_ptrv(src->__glibc_unused_qhook); - dst->__glibc_unused_rhook = to_ptrv(src->__glibc_unused_rhook); + dst->__glibc_unused_qhook = to_ptrv(src->RES_STATE_QHOOK); + dst->__glibc_unused_rhook = to_ptrv(src->RES_STATE_RHOOK); dst->res_h_errno = src->res_h_errno; dst->_vcsock = src->_vcsock; dst->_flags = src->_flags; @@ -618,8 +619,8 @@ void* convert_res_state_to_64(void* d, void* s) dst->_flags = src->_flags; dst->_vcsock = src->_vcsock; dst->res_h_errno = src->res_h_errno; - dst->__glibc_unused_rhook = from_ptrv(src->__glibc_unused_rhook); - dst->__glibc_unused_qhook = from_ptrv(src->__glibc_unused_qhook); + dst->RES_STATE_RHOOK = from_ptrv(src->__glibc_unused_rhook); + dst->RES_STATE_QHOOK = from_ptrv(src->__glibc_unused_qhook); memmove(dst->sort_list, src->sort_list, sizeof(dst->sort_list)); dst->unused = src->unused; dst->ipv6_unavail = src->ipv6_unavail; diff --git a/src/libtools/myalign32.c b/src/libtools/myalign32.c index eae303f017..d1e9979a37 100755 --- a/src/libtools/myalign32.c +++ b/src/libtools/myalign32.c @@ -1508,9 +1508,9 @@ void convert_obstack_to_32(void* d, void* s) dst->object_base = to_ptrv(src->object_base); dst->next_free = to_ptrv(src->next_free); dst->chunk_limit = to_ptrv(src->chunk_limit); - dst->temp.tempptr = to_ptrv(src->temp.tempptr); - dst->chunkfun = to_ptrv(src->chunkfun); - dst->freefun = to_ptrv(src->freefun); + dst->temp.tempptr = to_ptrv(src->temp.STRUCT_OBSTACK_TEMP); + dst->chunkfun = to_ptrv(src->STRUCT_OBSTACK_CHUNKFUN); + dst->freefun = to_ptrv(src->STRUCT_OBSTACK_FREEFUN); dst->extra_arg = to_ptrv(src->extra_arg); dst->use_extra_arg = src->use_extra_arg; dst->maybe_empty_object = src->maybe_empty_object; @@ -1526,9 +1526,9 @@ void convert_obstack_to_64(void* d, void* s) dst->maybe_empty_object = src->maybe_empty_object; dst->use_extra_arg = src->use_extra_arg; dst->extra_arg = from_ptrv(src->extra_arg); - dst->freefun = from_ptrv(src->freefun); - dst->chunkfun = from_ptrv(src->chunkfun); - dst->temp.tempptr = from_ptrv(src->temp.tempptr); + dst->STRUCT_OBSTACK_FREEFUN = from_ptrv(src->freefun); + dst->STRUCT_OBSTACK_CHUNKFUN = from_ptrv(src->chunkfun); + dst->temp.STRUCT_OBSTACK_TEMP = from_ptrv(src->temp.tempptr); dst->chunk_limit = from_ptrv(src->chunk_limit); dst->next_free = from_ptrv(src->next_free); dst->object_base = from_ptrv(src->object_base); diff --git a/src/libtools/obstack.c b/src/libtools/obstack.c index 4b40fee618..2ac435c349 100644 --- a/src/libtools/obstack.c +++ b/src/libtools/obstack.c @@ -27,6 +27,7 @@ #ifdef BOX32 #include "myalign32.h" #endif +#include "libc_obstack.h" typedef void (*vFv_t) (); typedef int32_t (*iFppp_t) (void*, void*, void*); diff --git a/src/libtools/signal32.c b/src/libtools/signal32.c index cf16e276ea..c1e9c4ea20 100644 --- a/src/libtools/signal32.c +++ b/src/libtools/signal32.c @@ -12,7 +12,7 @@ #include #include #include -#ifndef ANDROID +#ifdef USE_BACKTRACE #include #endif @@ -450,7 +450,7 @@ void convert_siginfo_to_32(void* d, void* s, int sig) dst->si_signo = src->si_signo; dst->si_errno = src->si_errno; dst->si_code = src->si_code; - memcpy(&dst->_sifields, &src->_sifields, sizeof(siginfo_t) - offsetof(siginfo_t, _sifields)); + memcpy(&dst->_sifields, &src->SIGINFO_S_SIFIELDS, sizeof(siginfo_t) - offsetof(siginfo_t, SIGINFO_S_SIFIELDS)); if(sig==X64_SIGILL || sig==X64_SIGFPE || sig==X64_SIGSEGV || sig==X64_SIGBUS) dst->_sifields._sigfault.__si_addr = to_ptr(((uintptr_t)src->si_addr)&0xffffffff); // in case addr is not a 32bits value... if(sig==X64_SIGCHLD) { diff --git a/src/libtools/signals.c b/src/libtools/signals.c index 8d72716325..45639ebd4b 100644 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -12,7 +12,7 @@ #include #include #include -#ifndef ANDROID +#ifdef USE_BACKTRACE #include #endif @@ -824,8 +824,10 @@ extern int fillblock_active; #ifdef USE_SIGNAL_MUTEX #ifdef USE_CUSTOM_MUTEX static uint32_t mutex_dynarec_prot = 0; -#else +#elif defined(PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP) static pthread_mutex_t mutex_dynarec_prot = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; +#else +static pthread_mutex_t mutex_dynarec_prot = PTHREAD_MUTEX_INITIALIZER; #endif #define lock_signal() mutex_lock(&mutex_dynarec_prot) #define unlock_signal() mutex_unlock(&mutex_dynarec_prot) @@ -1806,7 +1808,7 @@ void box64_abort() { char **strings; x64emu_t* emu = thread_get_emu(); -#ifndef ANDROID +#ifdef USE_BACKTRACE nptrs = backtrace(buffer, BT_BUF_SIZE); strings = backtrace_symbols(buffer, nptrs); if(strings) { @@ -1847,8 +1849,17 @@ static void atfork_child_dynarec_prot(void) #ifdef USE_CUSTOM_MUTEX native_lock_store(&mutex_dynarec_prot, 0); #else + #ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP pthread_mutex_t tmp = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; memcpy(&mutex_dynarec_prot, &tmp, sizeof(mutex_dynarec_prot)); + #else + pthread_mutex_t tmp = PTHREAD_MUTEX_INITIALIZER; + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); + pthread_mutex_init(&mutex_dynarec_prot, &attr); + pthread_mutexattr_destroy(&attr); + #endif #endif } #endif diff --git a/src/libtools/threads.c b/src/libtools/threads.c index 08317ed40c..724a0aacff 100644 --- a/src/libtools/threads.c +++ b/src/libtools/threads.c @@ -49,8 +49,12 @@ typedef struct emuthread_s emuthread_t; static vFppp_t real_pthread_cleanup_push_defer = NULL; static vFpi_t real_pthread_cleanup_pop_restore = NULL; static iFppip_t real_pthread_cond_clockwait = NULL; +#ifndef HAVE__PTHREAD_CLEANUP_PUSH void _pthread_cleanup_push(void* buffer, void* routine, void* arg); // declare hidden functions +#endif +#ifndef HAVE__PTHREAD_CLEANUP_POP void _pthread_cleanup_pop(void* buffer, int exec); +#endif // with glibc 2.34+, pthread_kill changed behaviour and might break some program, so using old version if possible // it will be pthread_kill@GLIBC_2.17 on aarch64, but it's GLIBC_2.2.5 on x86_64 static iFli_t real_phtread_kill_old = NULL; @@ -474,7 +478,7 @@ EXPORT int my_pthread_attr_init(x64emu_t* emu, pthread_attr_t* attr) PTHREAD_ATTR_UNALIGN(attr); return ret; } -#ifndef ANDROID +#ifdef HAVE_PTHREAD_ATTR_GETAFFINITY_NP EXPORT int my_pthread_attr_getaffinity_np(x64emu_t* emu, pthread_attr_t* attr, size_t cpusize, void* cpuset) { (void)emu; @@ -487,6 +491,8 @@ EXPORT int my_pthread_attr_getaffinity_np(x64emu_t* emu, pthread_attr_t* attr, s } return ret; } +#endif +#ifdef HAVE_PTHREAD_ATTR_SETAFFINITY_NP EXPORT int my_pthread_attr_setaffinity_np(x64emu_t* emu, pthread_attr_t* attr, size_t cpusize, void* cpuset) { (void)emu; @@ -1089,7 +1095,7 @@ EXPORT int my_pthread_mutexattr_setkind_np(x64emu_t* emu, my_mutexattr_t *attr, } EXPORT int my_pthread_mutexattr_setprioceiling(x64emu_t* emu, my_mutexattr_t *attr, int p) { -#if !defined(TERMUX) && !defined(ANDROID) +#ifdef HAVE_PTHREAD_MUTEXATTR_SETPRIOCEILING (void)emu; my_mutexattr_t mattr = {0}; mattr.x86 = attr->x86; @@ -1451,6 +1457,7 @@ void init_pthread_helper() // search for older symbol for pthread_kill { +#ifdef HAVE_DLVSYM char buff[50]; for(int i=0; i<34 && !real_phtread_kill_old; ++i) { snprintf(buff, 50, "GLIBC_2.%d", i); @@ -1461,6 +1468,7 @@ void init_pthread_helper() real_phtread_kill_old = (iFli_t)dlvsym(NULL, "pthread_kill", "GLIBC_2.2.5"); if(!real_phtread_kill_old) { printf_log(LOG_INFO, "Warning, older then 2.34 pthread_kill not found, using current one\n"); +#endif real_phtread_kill_old = (iFli_t)pthread_kill; } diff --git a/src/libtools/threads32.c b/src/libtools/threads32.c index c03e31585e..fa44f15af5 100755 --- a/src/libtools/threads32.c +++ b/src/libtools/threads32.c @@ -52,8 +52,12 @@ static vFpi_t real_pthread_cleanup_pop_restore = NULL; static iFLi_t real_phtread_kill_old = NULL; static iFv_t real_pthread_yield = NULL; // those function can be used simply -void _pthread_cleanup_push(void* buffer, void* routine, void* arg); // declare hidden functions +#ifndef HAVE__PTHREAD_CLEANUP_PUSH +void _pthread_cleanup_push(void* buffer, void* routine, void* arg); // declare hidden functions +#endif +#ifndef HAVE__PTHREAD_CLEANUP_POP void _pthread_cleanup_pop(void* buffer, int exec); +#endif typedef struct threadstack_s { void* stack; @@ -883,6 +887,7 @@ EXPORT int my32_pthread_setaffinity_np(x64emu_t* emu, pthread_t thread, int cpus return ret; } +#ifdef HAVE_PTHREAD_ATTR_SETAFFINITY_NP EXPORT int my32_pthread_attr_setaffinity_np(x64emu_t* emu, void* attr, uint32_t cpusetsize, void* cpuset) { if(cpusetsize>0x1000) { @@ -904,6 +909,8 @@ EXPORT int my32_pthread_attr_setaffinity_np(x64emu_t* emu, void* attr, uint32_t return ret; } +#endif +#ifdef HAVE_PTHREAD_ATTR_GETAFFINITY_NP EXPORT int my32_pthread_attr_getaffinity_np(x64emu_t* emu, void* attr, uint32_t cpusetsize, void* cpuset) { if(cpusetsize>0x1000) { @@ -918,6 +925,7 @@ EXPORT int my32_pthread_attr_getaffinity_np(x64emu_t* emu, void* attr, uint32_t } return ret; } +#endif #endif @@ -1056,7 +1064,14 @@ EXPORT int my32_pthread_mutex_init(pthread_mutex_t *m, pthread_mutexattr_t *att) fake->__kind = KIND_SIGN; fake->real_mutex = to_ptrv(createNewMutex()); int ret = pthread_mutex_init(from_ptrv(fake->real_mutex), att); +#ifdef __GLIBC__ fake->i386__kind = ((struct __pthread_mutex_s*)from_ptrv(fake->real_mutex))->__kind; +#else + // reads only the basic mutex type & fails silently + int kind = PTHREAD_MUTEX_NORMAL; + if(att) pthread_mutexattr_gettype(att, &kind); + fake->i386__kind = kind; +#endif printf_log(LOG_DEBUG, "(init t%d %p) ", fake->i386__kind, from_ptrv(fake->real_mutex)); return ret; } @@ -1101,6 +1116,7 @@ void init_pthread_helper_32() // search for older symbol for pthread_kill { +#ifdef HAVE_DLVSYM char buff[50]; for(int i=0; i<34 && !real_phtread_kill_old; ++i) { snprintf(buff, 50, "GLIBC_2.%d", i); @@ -1109,6 +1125,7 @@ void init_pthread_helper_32() } if(!real_phtread_kill_old) { printf_log(LOG_INFO, "Warning, older than 2.34 pthread_kill not found, using current one\n"); +#endif real_phtread_kill_old = (iFLi_t)pthread_kill; } // pthread_yield (or sched_yield if not found) diff --git a/src/mallochook.c b/src/mallochook.c index ad8d28646e..7fff0fcde8 100644 --- a/src/mallochook.c +++ b/src/mallochook.c @@ -196,7 +196,9 @@ void* box32_calloc(size_t n, size_t s) void* ret = box_calloc(n, s); if(ret && FITS_IN_32BIT(ret, n * s)) return ret; box_free(ret); +#ifdef HAVE_MALLOC_TRIM malloc_trim(0); +#endif ret = box_calloc(n, s); if(ret && FITS_IN_32BIT(ret, n * s)) return ret; box_free(ret); @@ -207,7 +209,9 @@ void* box32_malloc(size_t s) void* ret = box_malloc(s); if(ret && FITS_IN_32BIT(ret, s)) return ret; box_free(ret); +#ifdef HAVE_MALLOC_TRIM malloc_trim(0); +#endif ret = box_malloc(s); if(ret && FITS_IN_32BIT(ret, s)) return ret; box_free(ret); @@ -220,7 +224,9 @@ void* box32_realloc(void* p, size_t s) void* ret = box_realloc(p, s); if(!ret) return NULL; if(FITS_IN_32BIT(ret, s)) return ret; +#ifdef HAVE_MALLOC_TRIM malloc_trim(0); +#endif void* newret = customMalloc32(s); memcpy(newret, ret, s); box_free(ret); @@ -238,7 +244,9 @@ void* box32_memalign(size_t align, size_t s) void* ret = box_memalign(align, s); if(ret && FITS_IN_32BIT(ret, s)) return ret; box_free(ret); +#ifdef HAVE_MALLOC_TRIM malloc_trim(0); +#endif return customMemAligned32(align, s); } size_t box32_malloc_usable_size(void* p) diff --git a/src/os/backtrace.c b/src/os/backtrace.c index 327280542e..b89ccff2cc 100644 --- a/src/os/backtrace.c +++ b/src/os/backtrace.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT #include "backtrace.h" -#if !defined(ANDROID) && !defined(_WIN32) +#ifdef USE_BACKTRACE #include #include diff --git a/src/os/emit_signals_linux.c b/src/os/emit_signals_linux.c index 7e51fab15d..d8bd5826df 100644 --- a/src/os/emit_signals_linux.c +++ b/src/os/emit_signals_linux.c @@ -7,7 +7,7 @@ #include #include #include -#ifndef ANDROID +#ifdef USE_BACKTRACE #include #endif @@ -69,7 +69,7 @@ void EmitSignal(x64emu_t* emu, int sig, void* addr, int code) void* buffer[BT_BUF_SIZE]; char** strings; - #ifndef ANDROID + #ifdef USE_BACKTRACE nptrs = backtrace(buffer, BT_BUF_SIZE); strings = backtrace_symbols(buffer, nptrs); if (strings) { diff --git a/src/os/os_linux.c b/src/os/os_linux.c index 369d6faa09..a3285c2a1b 100644 --- a/src/os/os_linux.c +++ b/src/os/os_linux.c @@ -142,7 +142,7 @@ const char* GetNativeName(void* p, int lib) void PersonalityAddrLimit32Bit(void) { personality(ADDR_LIMIT_32BIT); - #ifndef ANDROID + #if defined(HAVE_MALLOPT) && defined(M_ARENA_TEST) && defined(M_ARENA_MAX) /*struct rlimit l; if(getrlimit(RLIMIT_DATA, &l)<0) return; // failed if(l.rlim_max>3*1024*1024*1024LL) { diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c index 65f41f1596..9bb7987068 100644 --- a/src/wrapped/wrappedlibc.c +++ b/src/wrapped/wrappedlibc.c @@ -99,6 +99,9 @@ extern const char *const sys_siglist[] __asm__("__sys_siglist"); #include "random.h" #include "cpumask.h" #include "x64tls.h" +#include "libc_malloc.h" +#include "libc_dirent.h" +#include "libc_ctype.h" #ifndef LOG_INFO #define LOG_INFO 1 #endif @@ -4173,6 +4176,7 @@ EXPORT int my_posix_madvise(x64emu_t* emu, void* addr, size_t length, int advice typedef struct mallinfo (*mallinfo_fnc)(void); EXPORT void* my_mallinfo(x64emu_t* emu, void* p) { +#ifdef HAVE_MALLINFO static mallinfo_fnc f = NULL; static int inited = 0; if(!inited) { @@ -4182,26 +4186,15 @@ EXPORT void* my_mallinfo(x64emu_t* emu, void* p) if(f) *(struct mallinfo*)p=f(); else +#endif memset(p, 0, sizeof(struct mallinfo)); return p; } -struct my_mallinfo2_s { - size_t arena; - size_t ordblks; - size_t smblks; - size_t hblks; - size_t hblkhd; - size_t usmblks; - size_t fsmblks; - size_t uordblks; - size_t fordblks; - size_t keepcost; -}; - -typedef struct my_mallinfo2_s (*mallinfo2_fnc)(void); +typedef struct mallinfo2 (*mallinfo2_fnc)(void); EXPORT void* my_mallinfo2(x64emu_t* emu, void* p) { +#ifdef HAVE_MALLINFO2 static mallinfo2_fnc f = NULL; static int inited = 0; if(!inited) { @@ -4209,9 +4202,10 @@ EXPORT void* my_mallinfo2(x64emu_t* emu, void* p) f = (mallinfo2_fnc)dlsym(my_lib->w.lib, "mallinfo2"); } if(f) - *(struct my_mallinfo2_s*)p = f(); + *(struct mallinfo2*)p = f(); else - memset(p, 0, sizeof(struct my_mallinfo2_s)); +#endif + memset(p, 0, sizeof(struct mallinfo2)); return p; } diff --git a/src/wrapped/wrappedlibdl.c b/src/wrapped/wrappedlibdl.c index 38cfc2b58f..b8a4e5c968 100644 --- a/src/wrapped/wrappedlibdl.c +++ b/src/wrapped/wrappedlibdl.c @@ -19,6 +19,7 @@ #include "x64tls.h" #include "elfloader.h" #include "elfs/elfloader_private.h" +#include "mydlfcn.h" typedef struct dllib_s { library_t* lib; @@ -523,14 +524,6 @@ int my_dlclose(x64emu_t* emu, void *handle) unlockLibLoader(); return ret; } -#ifdef ANDROID -#ifndef RTLD_DL_SYMENT -#define RTLD_DL_SYMENT 1 -#endif -#ifndef RTLD_DL_LINKMAP -#define RTLD_DL_LINKMAP 2 -#endif -#endif static int my_dladdr1_internal(x64emu_t* emu, void *addr, void *i, void** extra_info, int flags) { diff --git a/src/wrapped32/wrappedlibc.c b/src/wrapped32/wrappedlibc.c index 71653dd567..725207a01e 100755 --- a/src/wrapped32/wrappedlibc.c +++ b/src/wrapped32/wrappedlibc.c @@ -49,6 +49,7 @@ #include #include #include +#include #include "wrappedlibs.h" @@ -77,6 +78,10 @@ #include "box32_inputevent.h" #include "syscall_user_dispatch.h" #include "cpumask.h" +#include "libc_malloc.h" +#include "libc_ctype.h" +#include "libc_glob.h" +#include "libc_select.h" // need to undef all read / read64 stuffs! #undef pread @@ -1748,7 +1753,7 @@ typedef struct my_glob_32_s ulong_t gl_offs; int gl_flags; ptr_t gl_closedir; //void (*gl_closedir) (void *); - ptr_t gl_readir; //struct dirent *(*gl_readdir) (void *); + ptr_t gl_readdir; //struct dirent *(*gl_readdir) (void *); ptr_t gl_opendir; //void *(*gl_opendir) (const char *); ptr_t gl_lstat; //int (*gl_lstat) (const char *__restrict, struct stat *__restrict); ptr_t gl_stat; //int (*gl_stat) (const char *__restrict, struct stat *__restrict); @@ -1765,8 +1770,13 @@ static void convert_glob_to_32(void* d, void* s, int is64) dst->gl_pathc = to_ulong(src->gl_pathc); dst->gl_pathv = to_ptrv(src->gl_pathv); dst->gl_offs = to_ulong(src->gl_offs); - dst->gl_flags = src->gl_flags; + dst->gl_flags = src->GLOB_T_GL_FLAGS; // TODO: functions pointers + // dst->gl_closedir = to_ptrv(src->GLOB_T_GL_CLOSEDIR); + // dst->gl_readdir = to_ptrv(src->GLOB_T_GL_READDIR); + // dst->gl_opendir = to_ptrv(src->GLOB_T_GL_OPENDIR); + // dst->gl_lstat = to_ptrv(src->GLOB_T_GL_LSTAT); + // dst->gl_stat = to_ptrv(src->GLOB_T_GL_STAT); } static void convert_glob_to_64(void* d, void* s, int is64) { @@ -1776,10 +1786,15 @@ static void convert_glob_to_64(void* d, void* s, int is64) dst->gl_pathc = from_ulong(src->gl_pathc); dst->gl_pathv = from_ptrv(src->gl_pathv); dst->gl_offs = from_ulong(src->gl_offs); - dst->gl_flags = src->gl_flags; + dst->GLOB_T_GL_FLAGS = src->gl_flags; for(ulong_t i=dst->gl_pathc; i--;) dst->gl_pathv[i] = from_ptrv(((ptr_t*)dst->gl_pathv)[i]); // TODO: functions pointers + // dst->GLOB_T_GL_CLOSEDIR = from_ptrv(src->gl_closedir); + // dst->GLOB_T_GL_READDIR = from_ptrv(src->gl_readdir); + // dst->GLOB_T_GL_OPENDIR = from_ptrv(src->gl_opendir); + // dst->GLOB_T_GL_LSTAT = from_ptrv(src->gl_lstat); + // dst->GLOB_T_GL_STAT = from_ptrv(src->gl_stat); } EXPORT int32_t my32_glob(x64emu_t *emu, void* pat, int32_t flags, void* errfnc, void* pglob) @@ -2194,17 +2209,17 @@ void convert_file_action_to_32(void* d, void* s) { posix_spawn_file_actions_32_t* dst = d; posix_spawn_file_actions_t* src = s; - dst->__allocated = src->__allocated; - dst->__used = src->__used; - dst->__actions = to_ptrv(src->__actions); + dst->__allocated = src->POSIX_SPAWN_FILE_ACTIONS_T__ALLOCATED; + dst->__used = src->POSIX_SPAWN_FILE_ACTIONS_T__USED; + dst->__actions = to_ptrv(src->POSIX_SPAWN_FILE_ACTIONS_T__ACTIONS); } void convert_file_action_to_64(void* d, void* s) { posix_spawn_file_actions_t* dst = d; posix_spawn_file_actions_32_t* src = s; - dst->__actions = from_ptrv(src->__actions); - dst->__used = src->__used; - dst->__allocated = src->__allocated; + dst->POSIX_SPAWN_FILE_ACTIONS_T__ACTIONS = from_ptrv(src->__actions); + dst->POSIX_SPAWN_FILE_ACTIONS_T__USED = src->__used; + dst->POSIX_SPAWN_FILE_ACTIONS_T__ALLOCATED = src->__allocated; } EXPORT int my32_posix_spawn_file_actions_init(x64emu_t* emu, posix_spawn_file_actions_32_t* action) @@ -2362,8 +2377,13 @@ EXPORT int32_t my32___cxa_thread_atexit_impl(x64emu_t* emu, void* dtor, void* ob extern void __chk_fail(); EXPORT unsigned long int my32___fdelt_chk (unsigned long int d) { - if (d >= FD_SETSIZE) + if (d >= FD_SETSIZE) { +#ifdef HAVE___CHK_FAIL __chk_fail (); +#else + abort (); +#endif + } return d / __NFDBITS; } @@ -2500,27 +2520,21 @@ EXPORT int my32_utimensat(int dirfd, void* name, void* times, int flags) return utimensat(dirfd, name, times ? times_l : NULL, flags); } -#ifndef ANDROID -struct mallinfo { - int arena; - int ordblks; - int smblks; - int hblks; - int hblkhd; - int usmblks; - int fsmblks; - int uordblks; - int fordblks; - int keepcost; -}; -#endif - +typedef struct mallinfo (*mallinfo_fnc)(void); EXPORT void* my32_mallinfo(x86emu_t* emu, void* p) { - (void)emu; - static struct mallinfo(*p_mallinfo)() = NULL; - if(!p_mallinfo) p_mallinfo = dlsym(NULL, "mallinfo"); - *((struct mallinfo*)p) = p_mallinfo(); +#ifdef HAVE_MALLINFO + static mallinfo_fnc f = NULL; + static int inited = 0; + if(!inited) { + inited = 1; + f = (mallinfo_fnc)dlsym(my_lib->w.lib, "mallinfo"); + } + if(f) + *(struct mallinfo*)p=f(); + else +#endif + memset(p, 0, sizeof(struct mallinfo)); return p; } diff --git a/src/wrapped32/wrappedlibdl.c b/src/wrapped32/wrappedlibdl.c index 379f588fc9..f65ea28495 100755 --- a/src/wrapped32/wrappedlibdl.c +++ b/src/wrapped32/wrappedlibdl.c @@ -19,7 +19,7 @@ #include "elfloader.h" #include "elfs/elfloader_private.h" #include "x64emu.h" - +#include "mydlfcn.h" #define LIBNAME libdl #ifdef ANDROID @@ -38,13 +38,6 @@ int my32_dladdr1(x64emu_t* emu, void *addr, void *info, void** extra_info, int f void* my_dlvsym(x64emu_t* emu, void *handle, void *symbol, const char *vername) EXPORT; int my32_dlinfo(x64emu_t* emu, void* handle, int request, void* info) EXPORT; -#ifndef RTLD_DL_SYMENT -#define RTLD_DL_SYMENT 1 -#endif -#ifndef RTLD_DL_LINKMAP -#define RTLD_DL_LINKMAP 2 -#endif - void dl_clear_error(); #define CLEARERR dl_clear_error() void dl_set_error(const char*); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7d523cfd2a..3cdd67bd00 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -61,7 +61,9 @@ box64_add_test(linkingIndirectNoversion 15) box64_add_test(sse_asm 16 ENV "BOX64_DYNAREC_FASTROUND=0" DISABLED_ON_ANDROID) box64_add_test(sse_intrinsics 17 ENV "BOX64_DYNAREC_FASTNAN=0;BOX64_DYNAREC_FASTROUND=0" DISABLED_ON_ANDROID) box64_add_test(aes 18) -box64_add_test(backtrace 19 DISABLED_ON_ANDROID) +IF(HAVE_EXECINFO_H) + box64_add_test(backtrace 19 DISABLED_ON_ANDROID) +ENDIF() box64_add_test(irelative_reloc 20) box64_add_test(longjumpInSignals_nocosim 21 DISABLED_ON_ANDROID) box64_add_test(x87 22 ENV "BOX64_DYNAREC_FASTROUND=0" ANDROID_REF_NUM 22_android)