From 1b3e774abfafe89321824e2cf65d0c00fe09b0b4 Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 19 Oct 2026 17:12:51 +0200 Subject: [PATCH 01/23] conditional: execinfo.h Signed-off-by: Pepper Gray --- CMakeLists.txt | 24 ++++++++++++++++++++++++ src/libtools/signal32.c | 2 +- src/libtools/signals.c | 4 ++-- src/os/backtrace.c | 2 +- src/os/emit_signals_linux.c | 4 ++-- tests/CMakeLists.txt | 4 +++- 6 files changed, 33 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c74391b616..bb9d46275e 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,29 @@ 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() + # generated files set_source_files_properties( "${BOX64_ROOT}/src/git_head.h" diff --git a/src/libtools/signal32.c b/src/libtools/signal32.c index cf16e276ea..abb1c814cb 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 diff --git a/src/libtools/signals.c b/src/libtools/signals.c index 8d72716325..97de60b6d7 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 @@ -1806,7 +1806,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) { 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/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) From 9ab118c834950f6ea1c3bf93e301518cb9fa15a8 Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 19 Oct 2026 17:21:01 +0200 Subject: [PATCH 02/23] conditional: mallopt Signed-off-by: Pepper Gray --- CMakeLists.txt | 28 ++++++++++++++++++++++++++++ src/os/os_linux.c | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bb9d46275e..29cb7d983a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -442,6 +442,34 @@ if(HAVE_EXECINFO_H AND NOT ANDROID) add_compile_definitions(USE_BACKTRACE) endif() +include(CheckSymbolExists) + +set(PROJECT_SYMBOL_CHECKS + mallopt malloc.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() + # generated files set_source_files_properties( "${BOX64_ROOT}/src/git_head.h" 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) { From 01038b3ad83bed3072b13df61c87a858c627aad6 Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 19 Oct 2026 18:22:24 +0200 Subject: [PATCH 03/23] conditional: malloc_trim Signed-off-by: Pepper Gray --- CMakeLists.txt | 1 + src/mallochook.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 29cb7d983a..78ada8a1bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -446,6 +446,7 @@ include(CheckSymbolExists) set(PROJECT_SYMBOL_CHECKS mallopt malloc.h + malloc_trim malloc.h ) list(LENGTH PROJECT_SYMBOL_CHECKS checks_len) 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) From c72c2517b2529e7d3f6a2d2ad7bc74f3f9830131 Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 19 Oct 2026 18:35:05 +0200 Subject: [PATCH 04/23] conditional: mallinfo, mallinfo2 Signed-off-by: Pepper Gray --- CMakeLists.txt | 6 ++++-- src/include/libc_malloc.h | 35 +++++++++++++++++++++++++++++++++++ src/wrapped/wrappedlibc.c | 24 ++++++++---------------- src/wrapped32/wrappedlibc.c | 34 +++++++++++++++------------------- 4 files changed, 62 insertions(+), 37 deletions(-) create mode 100644 src/include/libc_malloc.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 78ada8a1bd..d43b74e273 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -445,8 +445,10 @@ endif() include(CheckSymbolExists) set(PROJECT_SYMBOL_CHECKS - mallopt malloc.h - malloc_trim malloc.h + mallopt malloc.h + malloc_trim malloc.h + mallinfo malloc.h + mallinfo2 malloc.h ) list(LENGTH PROJECT_SYMBOL_CHECKS checks_len) 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/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c index 65f41f1596..25c80c381a 100644 --- a/src/wrapped/wrappedlibc.c +++ b/src/wrapped/wrappedlibc.c @@ -99,6 +99,7 @@ extern const char *const sys_siglist[] __asm__("__sys_siglist"); #include "random.h" #include "cpumask.h" #include "x64tls.h" +#include "libc_malloc.h" #ifndef LOG_INFO #define LOG_INFO 1 #endif @@ -4173,6 +4174,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 +4184,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 +4200,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/wrapped32/wrappedlibc.c b/src/wrapped32/wrappedlibc.c index 71653dd567..7a36f700c7 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,7 @@ #include "box32_inputevent.h" #include "syscall_user_dispatch.h" #include "cpumask.h" +#include "libc_malloc.h" // need to undef all read / read64 stuffs! #undef pread @@ -2500,27 +2502,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; } From c0a307658aadec3762c3ce064d6c68d348809299 Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 19 Oct 2026 18:42:32 +0200 Subject: [PATCH 05/23] conditional: _pthread_cleanup_push/pop Signed-off-by: Pepper Gray --- CMakeLists.txt | 2 ++ src/libtools/threads.c | 4 ++++ src/libtools/threads32.c | 6 +++++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d43b74e273..692e4aadf7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -449,6 +449,8 @@ set(PROJECT_SYMBOL_CHECKS malloc_trim malloc.h mallinfo malloc.h mallinfo2 malloc.h + _pthread_cleanup_push pthread.h + _pthread_cleanup_pop pthread.h ) list(LENGTH PROJECT_SYMBOL_CHECKS checks_len) diff --git a/src/libtools/threads.c b/src/libtools/threads.c index 08317ed40c..8a147214b7 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; diff --git a/src/libtools/threads32.c b/src/libtools/threads32.c index c03e31585e..6c12fd7816 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; From 74eb86eb6b147b2467d7b5ea691b381c59a2711c Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 19 Oct 2026 18:55:48 +0200 Subject: [PATCH 06/23] conditional: pthread_attr_get/setaffinity_np Signed-off-by: Pepper Gray --- CMakeLists.txt | 3 +++ src/libtools/signals.c | 13 ++++++++++++- src/libtools/threads.c | 6 ++++-- src/libtools/threads32.c | 4 ++++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 692e4aadf7..4abc1d1033 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -451,6 +451,9 @@ set(PROJECT_SYMBOL_CHECKS 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 ) list(LENGTH PROJECT_SYMBOL_CHECKS checks_len) diff --git a/src/libtools/signals.c b/src/libtools/signals.c index 97de60b6d7..45639ebd4b 100644 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -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) @@ -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 8a147214b7..7e4325f34d 100644 --- a/src/libtools/threads.c +++ b/src/libtools/threads.c @@ -478,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; @@ -491,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; @@ -1093,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; diff --git a/src/libtools/threads32.c b/src/libtools/threads32.c index 6c12fd7816..92e1f3823a 100755 --- a/src/libtools/threads32.c +++ b/src/libtools/threads32.c @@ -887,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) { @@ -908,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) { @@ -922,6 +925,7 @@ EXPORT int my32_pthread_attr_getaffinity_np(x64emu_t* emu, void* attr, uint32_t } return ret; } +#endif #endif From 10ae8c68d934dc9f30fcfb8fe7e5f9256e769fac Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Tue, 20 Oct 2026 04:29:20 +0200 Subject: [PATCH 07/23] conditional: __pthread_mutex_s->__kind my32_pthread_mutex_init: fake->i386__kind: incomplete definition of type 'struct __pthread_mutex_s' Signed-off-by: Pepper Gray --- src/libtools/threads32.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libtools/threads32.c b/src/libtools/threads32.c index 92e1f3823a..52003d88df 100755 --- a/src/libtools/threads32.c +++ b/src/libtools/threads32.c @@ -1064,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; } From 6459ad810ed694145fdb1b982ba2aa634f41b854 Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 19 Oct 2026 18:59:15 +0200 Subject: [PATCH 08/23] conditional: dlvsym Signed-off-by: Pepper Gray --- CMakeLists.txt | 1 + src/libtools/threads.c | 2 ++ src/libtools/threads32.c | 2 ++ 3 files changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4abc1d1033..20677ac307 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -454,6 +454,7 @@ set(PROJECT_SYMBOL_CHECKS pthread_attr_getaffinity_np pthread.h pthread_attr_setaffinity_np pthread.h pthread_mutexattr_setprioceiling pthread.h + dlvsym dlfcn.h ) list(LENGTH PROJECT_SYMBOL_CHECKS checks_len) diff --git a/src/libtools/threads.c b/src/libtools/threads.c index 7e4325f34d..724a0aacff 100644 --- a/src/libtools/threads.c +++ b/src/libtools/threads.c @@ -1457,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); @@ -1467,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 52003d88df..fa44f15af5 100755 --- a/src/libtools/threads32.c +++ b/src/libtools/threads32.c @@ -1116,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); @@ -1124,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) From 8e392ac6c10cf5c22f8e39aca4eef107cec8b1d6 Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 19 Oct 2026 19:07:23 +0200 Subject: [PATCH 09/23] conditional: obstack_vprintf Signed-off-by: Pepper Gray --- CMakeLists.txt | 2 ++ src/include/libc_obstack.h | 9 ++++++++ src/libtools/libc.c | 44 ++++++++++++++++++++++++++++++++++++++ src/libtools/obstack.c | 1 + 4 files changed, 56 insertions(+) create mode 100644 src/include/libc_obstack.h create mode 100644 src/libtools/libc.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 20677ac307..e01263d070 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -455,6 +455,7 @@ set(PROJECT_SYMBOL_CHECKS pthread_attr_setaffinity_np pthread.h pthread_mutexattr_setprioceiling pthread.h dlvsym dlfcn.h + obstack_vprintf stdio.h ) list(LENGTH PROJECT_SYMBOL_CHECKS checks_len) @@ -538,6 +539,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_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/libtools/libc.c b/src/libtools/libc.c new file mode 100644 index 0000000000..df45e7b75a --- /dev/null +++ b/src/libtools/libc.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +#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 \ No newline at end of file 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*); From 1b6a8515633b2973fd973956afb02b1ff1ab4542 Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 19 Oct 2026 19:45:56 +0200 Subject: [PATCH 10/23] conditional: struct obstack Signed-off-by: Pepper Gray --- CMakeLists.txt | 19 +++++++++++++++++++ src/libtools/myalign32.c | 12 ++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e01263d070..11d6bc13b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -480,6 +480,25 @@ foreach(i RANGE 0 ${checks_last} 2) 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() + # generated files set_source_files_properties( "${BOX64_ROOT}/src/git_head.h" 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); From f587b70d7db46cbe7f5368fd0339d3dcb6b6417f Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 19 Oct 2026 19:56:18 +0200 Subject: [PATCH 11/23] conditional: siginfo_t Signed-off-by: Pepper Gray --- CMakeLists.txt | 13 +++++++++++++ src/include/signals.h | 4 ++++ src/libtools/signal32.c | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 11d6bc13b3..3b72d66705 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -499,6 +499,19 @@ 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() + # generated files set_source_files_properties( "${BOX64_ROOT}/src/git_head.h" 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/signal32.c b/src/libtools/signal32.c index abb1c814cb..c1e9c4ea20 100644 --- a/src/libtools/signal32.c +++ b/src/libtools/signal32.c @@ -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) { From 498322cf0571cb0426a6fe42744f746dee7ca316 Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 19 Oct 2026 20:34:49 +0200 Subject: [PATCH 12/23] conditional: getprotobyname/number_r Signed-off-by: Pepper Gray --- CMakeLists.txt | 2 + src/include/libc_netdb.h | 13 ++++++ src/libtools/libc.c | 86 ++++++++++++++++++++++++++++++++++++++- src/libtools/libc_net32.c | 1 + 4 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 src/include/libc_netdb.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b72d66705..e84af23896 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -456,6 +456,8 @@ set(PROJECT_SYMBOL_CHECKS pthread_mutexattr_setprioceiling pthread.h dlvsym dlfcn.h obstack_vprintf stdio.h + getprotobyname_r netdb.h + getprotobynumber_r netdb.h ) list(LENGTH PROJECT_SYMBOL_CHECKS checks_len) 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/libtools/libc.c b/src/libtools/libc.c index df45e7b75a..daa46eaec0 100644 --- a/src/libtools/libc.c +++ b/src/libtools/libc.c @@ -2,6 +2,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include #if !defined(HAVE_OBSTACK_VPRINTF) && !defined(ANDROID) @@ -41,4 +47,82 @@ int obstack_vprintf(struct obstack *obstack, const char *fmt, va_list args) return len; } -#endif \ No newline at end of file +#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 diff --git a/src/libtools/libc_net32.c b/src/libtools/libc_net32.c index aac38a317a..d48dead106 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) { From 7272e1164d98d51cf24ccb0f707cc8f8cf898698 Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 19 Oct 2026 20:36:48 +0200 Subject: [PATCH 13/23] conditional: struct __res_state Signed-off-by: Pepper Gray --- CMakeLists.txt | 15 +++++++++++++++ src/libtools/libc_net32.c | 8 ++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e84af23896..557ec72a10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -514,6 +514,21 @@ 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() + # generated files set_source_files_properties( "${BOX64_ROOT}/src/git_head.h" diff --git a/src/libtools/libc_net32.c b/src/libtools/libc_net32.c index d48dead106..60afaa9636 100644 --- a/src/libtools/libc_net32.c +++ b/src/libtools/libc_net32.c @@ -599,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; @@ -619,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; From 795b1ac565a1ea4f38c5eb4a936cb7dee5785bc1 Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 19 Oct 2026 20:42:47 +0200 Subject: [PATCH 14/23] conditional: RTLD_DL_SYMENT/LINKMAP Signed-off-by: Pepper Gray --- src/include/mydlfcn.h | 14 ++++++++++++++ src/wrapped/wrappedlibdl.c | 9 +-------- src/wrapped32/wrappedlibdl.c | 9 +-------- 3 files changed, 16 insertions(+), 16 deletions(-) create mode 100644 src/include/mydlfcn.h 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/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/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*); From f323ffc479574065c931879f2812cfdcdef4b99f Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 19 Oct 2026 21:22:44 +0200 Subject: [PATCH 15/23] conditional: scandirat Signed-off-by: Pepper Gray --- CMakeLists.txt | 1 + src/include/libc_dirent.h | 10 +++++++ src/libtools/libc.c | 62 ++++++++++++++++++++++++++++++++++++++- src/wrapped/wrappedlibc.c | 1 + 4 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/include/libc_dirent.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 557ec72a10..c67ea38066 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -458,6 +458,7 @@ set(PROJECT_SYMBOL_CHECKS obstack_vprintf stdio.h getprotobyname_r netdb.h getprotobynumber_r netdb.h + scandirat dirent.h ) list(LENGTH PROJECT_SYMBOL_CHECKS checks_len) 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/libtools/libc.c b/src/libtools/libc.c index daa46eaec0..071ccd3bec 100644 --- a/src/libtools/libc.c +++ b/src/libtools/libc.c @@ -8,6 +8,11 @@ #include #include #include +#include +#include +#include +#include +#include #if !defined(HAVE_OBSTACK_VPRINTF) && !defined(ANDROID) @@ -45,7 +50,7 @@ int obstack_vprintf(struct obstack *obstack, const char *fmt, va_list args) if(len > 0) obstack_grow(obstack, buf, len); if(buf != buffer) free(buf); - return len; + return len; } #endif @@ -126,3 +131,58 @@ int getprotobynumber_r(int proto, struct protoent *result_buf, char *buf, size_t } #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/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c index 25c80c381a..3053adf5c5 100644 --- a/src/wrapped/wrappedlibc.c +++ b/src/wrapped/wrappedlibc.c @@ -100,6 +100,7 @@ extern const char *const sys_siglist[] __asm__("__sys_siglist"); #include "cpumask.h" #include "x64tls.h" #include "libc_malloc.h" +#include "libc_dirent.h" #ifndef LOG_INFO #define LOG_INFO 1 #endif From 55b2ffcee635112b887e5bc290f4013f54c16c10 Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 19 Oct 2026 21:48:49 +0200 Subject: [PATCH 16/23] conditional: __ctype_b/tolower/toupper_loc Signed-off-by: Pepper Gray --- CMakeLists.txt | 13 +++++++++++++ src/include/libc_ctype.h | 14 ++++++++++++++ src/wrapped/wrappedlibc.c | 1 + src/wrapped32/wrappedlibc.c | 1 + 4 files changed, 29 insertions(+) create mode 100644 src/include/libc_ctype.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c67ea38066..910aac4f64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -530,6 +530,19 @@ 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() + # generated files set_source_files_properties( "${BOX64_ROOT}/src/git_head.h" 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/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c index 3053adf5c5..9bb7987068 100644 --- a/src/wrapped/wrappedlibc.c +++ b/src/wrapped/wrappedlibc.c @@ -101,6 +101,7 @@ extern const char *const sys_siglist[] __asm__("__sys_siglist"); #include "x64tls.h" #include "libc_malloc.h" #include "libc_dirent.h" +#include "libc_ctype.h" #ifndef LOG_INFO #define LOG_INFO 1 #endif diff --git a/src/wrapped32/wrappedlibc.c b/src/wrapped32/wrappedlibc.c index 7a36f700c7..a89837012c 100755 --- a/src/wrapped32/wrappedlibc.c +++ b/src/wrapped32/wrappedlibc.c @@ -79,6 +79,7 @@ #include "syscall_user_dispatch.h" #include "cpumask.h" #include "libc_malloc.h" +#include "libc_ctype.h" // need to undef all read / read64 stuffs! #undef pread From 1d6650ded6b668aa8915e84c4160891f13151b28 Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 19 Oct 2026 21:56:34 +0200 Subject: [PATCH 17/23] conditional: glob_t Signed-off-by: Pepper Gray --- CMakeLists.txt | 23 +++++++++++++++++++++++ src/include/libc_glob.h | 13 +++++++++++++ src/wrapped32/wrappedlibc.c | 17 ++++++++++++++--- 3 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 src/include/libc_glob.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 910aac4f64..8d898c1fca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -543,6 +543,29 @@ elseif(CTYPE_B_LOC_EXT) # musl 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() + # generated files set_source_files_properties( "${BOX64_ROOT}/src/git_head.h" 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/wrapped32/wrappedlibc.c b/src/wrapped32/wrappedlibc.c index a89837012c..82d92a6ee9 100755 --- a/src/wrapped32/wrappedlibc.c +++ b/src/wrapped32/wrappedlibc.c @@ -80,6 +80,7 @@ #include "cpumask.h" #include "libc_malloc.h" #include "libc_ctype.h" +#include "libc_glob.h" // need to undef all read / read64 stuffs! #undef pread @@ -1751,7 +1752,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); @@ -1768,8 +1769,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) { @@ -1779,10 +1785,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) From f8b852c5331de19d47fa4e933f7bdb50f033215e Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 19 Oct 2026 21:58:39 +0200 Subject: [PATCH 18/23] conditional: posix_spawn_file_actions_t Signed-off-by: Pepper Gray --- CMakeLists.txt | 21 +++++++++++++++++++++ src/wrapped32/wrappedlibc.c | 12 ++++++------ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d898c1fca..74ca02898f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -566,6 +566,27 @@ 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" diff --git a/src/wrapped32/wrappedlibc.c b/src/wrapped32/wrappedlibc.c index 82d92a6ee9..1d8f40d0b4 100755 --- a/src/wrapped32/wrappedlibc.c +++ b/src/wrapped32/wrappedlibc.c @@ -2208,17 +2208,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) From 7d6fff162a20b995c3aadf8b810bdc7d5e4bad86 Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 19 Oct 2026 22:00:20 +0200 Subject: [PATCH 19/23] conditional: __NFDBITS Signed-off-by: Pepper Gray --- src/include/libc_select.h | 13 +++++++++++++ src/wrapped32/wrappedlibc.c | 1 + 2 files changed, 14 insertions(+) create mode 100644 src/include/libc_select.h 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/wrapped32/wrappedlibc.c b/src/wrapped32/wrappedlibc.c index 1d8f40d0b4..f81ec95bb1 100755 --- a/src/wrapped32/wrappedlibc.c +++ b/src/wrapped32/wrappedlibc.c @@ -81,6 +81,7 @@ #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 From ba48cec612d79ad53fbfa5402e950bb9fc0ec984 Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 19 Oct 2026 22:52:12 +0200 Subject: [PATCH 20/23] conditional: __chk_fail Signed-off-by: Pepper Gray --- CMakeLists.txt | 19 +++++++++++++++++++ src/wrapped32/wrappedlibc.c | 7 ++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 74ca02898f..2f1f42133b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -483,6 +483,25 @@ foreach(i RANGE 0 ${checks_last} 2) 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 diff --git a/src/wrapped32/wrappedlibc.c b/src/wrapped32/wrappedlibc.c index f81ec95bb1..725207a01e 100755 --- a/src/wrapped32/wrappedlibc.c +++ b/src/wrapped32/wrappedlibc.c @@ -2377,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; } From 68b1aae5aebbb3706ab2e0f71d3364b3214c3198 Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 19 Oct 2026 22:21:32 +0200 Subject: [PATCH 21/23] musl: link additional libs Signed-off-by: Pepper Gray --- CMakeLists.txt | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ docs/COMPILE.md | 13 +++++++++ 2 files changed, 83 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f1f42133b..b101f4fe97 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -423,6 +423,7 @@ include(CheckIncludeFile) set(PROJECT_HEADERS execinfo.h + error.h ) foreach(header IN LISTS PROJECT_HEADERS) @@ -606,6 +607,25 @@ elseif(NOT ANDROID) message(FATAL_ERROR "Unknown posix_spawn_file_actions_t layout!") endif() +if(HAVE_ERROR_H) + set(ERROR_TEST [[ + #include + int main(void) { error(0, 0, "test"); return 0; } + ]]) + check_c_source_compiles("${ERROR_TEST}" HAVE_ERROR) + if(NOT HAVE_ERROR) + include(CMakePushCheckState) + cmake_push_check_state() + set(CMAKE_REQUIRED_LIBRARIES error) + check_c_source_compiles("${ERROR_TEST}" HAVE_ERROR_LIB) + cmake_pop_check_state() + endif() +endif() + +if(NOT HAVE_ERROR AND NOT HAVE_ERROR_LIB) + message(FATAL_ERROR "error() is unavailable") +endif() + # generated files set_source_files_properties( "${BOX64_ROOT}/src/git_head.h" @@ -1572,6 +1592,56 @@ if(NOT NOBOX64) endif() target_link_libraries(${BOX64} interpreter) + set(BOX64_MUSL FALSE) + + if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + if(CMAKE_C_COMPILER_TARGET MATCHES "musl") + set(BOX64_MUSL TRUE) + set(BOX64_LIBC_TARGET "${CMAKE_C_COMPILER_TARGET}") + else() + execute_process( + COMMAND "${CMAKE_C_COMPILER}" -dumpmachine + OUTPUT_VARIABLE BOX64_CC_MACHINE + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + + if(BOX64_CC_MACHINE MATCHES "musl") + set(BOX64_MUSL TRUE) + set(BOX64_LIBC_TARGET "${BOX64_CC_MACHINE}") + endif() + endif() + endif() + + if(BOX64_MUSL) + set(MUSL_COMPAT_LIBS + argp + obstack + fts + ucontext + ) + + if(HAVE_ERROR_LIB) + list(APPEND MUSL_COMPAT_LIBS error) + endif() + + foreach(lib IN LISTS MUSL_COMPAT_LIBS) + string(TOUPPER "${lib}" LIB_UPPER) + set(LIB_VAR "MUSL_${LIB_UPPER}_LIBRARY") + + message(STATUS "Looking for lib${lib}") + find_library(${LIB_VAR} NAMES ${lib}) + + if(${LIB_VAR}) + message(STATUS "Looking for lib${lib} - found: ${${LIB_VAR}}") + else() + message(FATAL_ERROR "Looking for lib${lib} - not found.") + endif() + + target_link_libraries(${BOX64} "${MUSL_${LIB_UPPER}_LIBRARY}") + endforeach() + endif() + if(${CMAKE_VERSION} VERSION_LESS "3.13") if(NOT NOLOADADDR) if(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR WITH_MOLD) diff --git a/docs/COMPILE.md b/docs/COMPILE.md index b8d9b7afeb..fc0875fa9a 100644 --- a/docs/COMPILE.md +++ b/docs/COMPILE.md @@ -309,6 +309,19 @@ Add `-DWITH_MOLD=1` option when GNU ld is extremely slow. Then run `mold -run ma You can now build box64 statically linked, with `-DSTATICBUILD` to use inside of a x86_64 chroot. Note that this version of box64 will only have the minimal wrapped libs, such as libc, libm and libpthread. Other libs (like libGL or libvulkan, SDL2, etc...) will use x86_64 versions. A static build is intended to be used in a docker image, or in a headless server. It is highly experimental, but feedback is always welcome. + +#### Build with musl + +Building with musl needs additional libraries: + +| Library | Alpine Linux | Gentoo | +| -------- | ------------------- | ----------------------------- | +| argp | `argp-standalone` | `sys-libs/argp-standalone` | +| obstack | `musl-obstack` | `sys-libs/obstack-standalone` | +| fts | `musl-fts` | `sys-libs/fts-standalone` | +| ucontext | `libucontext` | `sys-libs/libucontext` | +| error | `musl-legacy-error` | `sys-libs/error-standalone` | + ---- ## Testing From baff4569664ea9395ff27b6e6f8038f919f76fe9 Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 19 Oct 2026 22:39:57 +0200 Subject: [PATCH 22/23] musl: update malloc hook Signed-off-by: Pepper Gray --- src/include/debug.h | 15 ++++++++++++--- src/mallochook.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/src/include/debug.h b/src/include/debug.h index f6b3b8673d..8f289fc621 100644 --- a/src/include/debug.h +++ b/src/include/debug.h @@ -120,7 +120,7 @@ void init_malloc_hook(void); #define box_strdup strdup #define box_realpath realpath #else -extern size_t (*box_malloc_usable_size)(void*); +#ifdef __GLIBC__ extern void* __libc_malloc(size_t); extern void* __libc_realloc(void*, size_t); extern void* __libc_calloc(size_t, size_t); @@ -131,10 +131,19 @@ extern void* __libc_memalign(size_t, size_t); #define box_calloc __libc_calloc #define box_free __libc_free #define box_memalign __libc_memalign +#else // ! __GLIBC__ +// no __libc_* on musl: call libc's own functions through dlsym +void* box_malloc(size_t s); +void* box_realloc(void* p, size_t s); +void* box_calloc(size_t n, size_t s); +void box_free(void* p); +void* box_memalign(size_t align, size_t s); +#endif // __GLIBC__ +extern size_t (*box_malloc_usable_size)(void*); extern char* box_strdup(const char* s); extern char* box_realpath(const char* path, char* ret); -#endif -#else +#endif // ANDROID || STATICBUILD +#else // _WIN32 #define box_malloc WinMalloc #define box_realloc WinRealloc #define box_calloc WinCalloc diff --git a/src/mallochook.c b/src/mallochook.c index 7fff0fcde8..2e75711897 100644 --- a/src/mallochook.c +++ b/src/mallochook.c @@ -138,6 +138,48 @@ typedef void* (*pFpLLp_t)(void*, size_t, size_t, void*); size_t(*box_malloc_usable_size)(void*) = NULL; +#if ! defined(STATICBUILD) && ! defined(ANDROID) && ! defined(__GLIBC__) +// musl's calloc and memalign call the exported (hooked) malloc and aligned_alloc, +// so only use libc functions that don't to prevent infinite loops. +// Resolve on first use: malloc can be called before init_malloc_hook +// nothing on the dlsym path may allocate +static void* (*libc_malloc)(size_t) = NULL; +static void* (*libc_realloc)(void*, size_t) = NULL; +static void (*libc_free)(void*) = NULL; +static void* (*libc_aligned_alloc)(size_t, size_t) = NULL; + +void* box_malloc(size_t s) +{ + if(libc_malloc == NULL) libc_malloc = dlsym(RTLD_NEXT, "malloc"); + return libc_malloc(s); +} +void* box_realloc(void* p, size_t s) +{ + if(libc_realloc == NULL) libc_realloc = dlsym(RTLD_NEXT, "realloc"); + return libc_realloc(p, s); +} +void box_free(void* p) +{ + if(libc_free == NULL) libc_free = dlsym(RTLD_NEXT, "free"); + libc_free(p); +} +void* box_memalign(size_t align, size_t s) +{ + if(libc_aligned_alloc == NULL) libc_aligned_alloc = dlsym(RTLD_NEXT, "aligned_alloc"); + return libc_aligned_alloc(align, s); +} +void* box_calloc(size_t n, size_t s) +{ + if(s && n>((size_t)-1)/s) { + errno = ENOMEM; + return NULL; + } + void* ret = box_malloc(n*s); + if(ret) memset(ret, 0, n*s); + return ret; +} +#endif + int GetTID(); uint32_t getProtection(uintptr_t addr); // malloc_hack "2" handling From 1b32884d396d7a2479d868ea8c54db30337f1719 Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Tue, 20 Oct 2026 02:11:27 +0200 Subject: [PATCH 23/23] musl: elfloader find symbol Signed-off-by: Pepper Gray --- src/elfs/elfloader.c | 12 +++++++++++- src/include/elfhacks.h | 8 ++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index 255e06c21c..d4e0aed589 100644 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -2154,7 +2154,17 @@ int dl_iterate_phdr_findsymbol(eh_obj_t* obj, search_symbol_t* s) ++dyn; } - if (strtab && verdef && verdef_cnt) { +#if defined(__GLIBC__) || defined (ANDROID) + int candidate = verdef && verdef_cnt; +#else // MUSL + // glibc allows the usage of versioned symbols, musl provides only default symbols, + // -> verdef test would reject musl's libc. replace it with an address-based test + // to skip box64 itself (it exports its own dlsym/dlopen/dlclose): + // accept candidate if eh_check_addr returns that the address of this function + // lies not in obj, i.e. obj is not box64 + int candidate = eh_check_addr(obj, (void*)dl_iterate_phdr_findsymbol) != 0; +#endif + if (strtab && candidate) { eh_find_sym(obj, s->name, &s->addr); if (s->addr) { eh_destroy_obj(obj); diff --git a/src/include/elfhacks.h b/src/include/elfhacks.h index 57d1e5ae5c..5ceb019f4d 100644 --- a/src/include/elfhacks.h +++ b/src/include/elfhacks.h @@ -158,6 +158,14 @@ __PUBLIC int eh_iterate_obj(eh_iterate_obj_callback_func callback, void *arg); */ __PUBLIC int eh_find_sym(eh_obj_t *obj, const char *name, void **to); +/** + * \brief Checks if address is inside one of object's PT_LOAD segments. + * \param obj elfhacks program object + * \param addr address to check + * \return 0 if address is inside object otherwise EINVAL +*/ +__PUBLIC int eh_check_addr(eh_obj_t *obj, const void *addr); + /** * \brief Walk through list of symbols in object * \param obj elfhacks program object