From 3e6f63ea93c17893ecc5d343223d849e1476818a Mon Sep 17 00:00:00 2001 From: komaruworld Date: Thu, 8 Oct 2026 16:13:41 +0300 Subject: [PATCH 1/4] remove libexecinfo dependency --- CMakeLists.txt | 45 ------------------------------------ src/legacy/legacy_runtime.cc | 1 - 2 files changed, 46 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 314f6e9..a3019d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -557,50 +557,6 @@ target_link_libraries(mocktail_bionic_abi_exports PRIVATE Threads::Threads ) -include(CheckCXXSourceCompiles) -include(CheckIncludeFileCXX) -include(CMakePushCheckState) - -check_include_file_cxx(execinfo.h MOCKTAIL_HAVE_EXECINFO_H) -if(NOT MOCKTAIL_HAVE_EXECINFO_H) - message(FATAL_ERROR - "execinfo.h is required for crash diagnostics; on musl install " - "libexecinfo-devel" - ) -endif() - -set(MOCKTAIL_EXECINFO_LINK_LIBRARY "") -set(_mocktail_execinfo_link_probe [=[ - #include - int main() { - void* frames[1] = {}; - const int count = backtrace(frames, 1); - return backtrace_symbols(frames, count) == nullptr; - } -]=]) -check_cxx_source_compiles( - "${_mocktail_execinfo_link_probe}" - MOCKTAIL_EXECINFO_IN_HOST_LIBC -) -if(NOT MOCKTAIL_EXECINFO_IN_HOST_LIBC) - find_library(MOCKTAIL_EXECINFO_LIBRARY NAMES execinfo REQUIRED) - cmake_push_check_state(RESET) - set(CMAKE_REQUIRED_LIBRARIES "${MOCKTAIL_EXECINFO_LIBRARY}") - check_cxx_source_compiles( - "${_mocktail_execinfo_link_probe}" - MOCKTAIL_EXECINFO_IN_EXTERNAL_LIBRARY - ) - cmake_pop_check_state() - if(NOT MOCKTAIL_EXECINFO_IN_EXTERNAL_LIBRARY) - message(FATAL_ERROR - "execinfo.h is available, but backtrace and backtrace_symbols cannot " - "be linked" - ) - endif() - set(MOCKTAIL_EXECINFO_LINK_LIBRARY "${MOCKTAIL_EXECINFO_LIBRARY}") -endif() -unset(_mocktail_execinfo_link_probe) - add_library(mocktail_legacy_runtime STATIC src/legacy/legacy_runtime.cc src/runtime/roblox_text_input_jni_bridge.cc @@ -625,7 +581,6 @@ target_link_libraries(mocktail_legacy_runtime PRIVATE libc_shim mocktail_window mocktail_graphics_foundation - ${MOCKTAIL_EXECINFO_LINK_LIBRARY} ) target_compile_definitions(mocktail_legacy_runtime PRIVATE "MOCKTAIL_DEFAULT_COMPATIBILITY_MANIFEST=\"${MOCKTAIL_DEFAULT_COMPATIBILITY_MANIFEST}\"" diff --git a/src/legacy/legacy_runtime.cc b/src/legacy/legacy_runtime.cc index 8a9f464..e57e4de 100644 --- a/src/legacy/legacy_runtime.cc +++ b/src/legacy/legacy_runtime.cc @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include From aa31cdf395a0d7da3d0deceb5e8d5501a11f653b Mon Sep 17 00:00:00 2001 From: komaruworld Date: Thu, 8 Oct 2026 16:59:11 +0300 Subject: [PATCH 2/4] Improve chimera support --- include/compat/bionic_host_libc_runtime.h | 20 +++++++++---------- src/compat/bionic_host_libc_runtime.cc | 9 +++++++-- src/compat/bionic_pthread_create_runtime.cc | 2 +- src/runtime/external_launch_broker.cc | 1 + tests/bionic_host_libc_runtime_test.cc | 16 ++++++++++++--- .../mcpelauncher-linker/include/assert.h | 3 ++- .../mcpelauncher-linker/include/compat.h | 4 ++++ .../mcpelauncher-linker/include/sys/cdefs.h | 6 ++++++ 8 files changed, 44 insertions(+), 17 deletions(-) diff --git a/include/compat/bionic_host_libc_runtime.h b/include/compat/bionic_host_libc_runtime.h index 5c8d44c..15c14d9 100644 --- a/include/compat/bionic_host_libc_runtime.h +++ b/include/compat/bionic_host_libc_runtime.h @@ -14,16 +14,16 @@ namespace mocktail::compat { // Android uses size_t fields here; glibc uses int and musl has no equivalent. // An all-zero fallback means unknown, not zero usage. struct BionicMallinfoSnapshot { - size_t arena = 0; - size_t ordblks = 0; - size_t smblks = 0; - size_t hblks = 0; - size_t hblkhd = 0; - size_t usmblks = 0; - size_t fsmblks = 0; - size_t uordblks = 0; - size_t fordblks = 0; - size_t keepcost = 0; + 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; }; struct BionicLocaleState; diff --git a/src/compat/bionic_host_libc_runtime.cc b/src/compat/bionic_host_libc_runtime.cc index 9ec8eff..324e2e9 100644 --- a/src/compat/bionic_host_libc_runtime.cc +++ b/src/compat/bionic_host_libc_runtime.cc @@ -323,8 +323,13 @@ int BionicStrError(int error_number, char* buffer, ::strerror_r(error_number, host_buffer.data(), host_buffer.size()); const char* message = HostStrErrorResult(host_result, host_buffer.data()); - std::array unknown_buffer{}; - if (message == nullptr) { + std::array unknown_buffer{}; + const char* unknown_message = HostStrErrorResult( + ::strerror_r(-1, unknown_buffer.data(), unknown_buffer.size()), + unknown_buffer.data()); + if (message == nullptr || + (error_number != 0 && unknown_message != nullptr && + std::strcmp(message, unknown_message) == 0)) { std::snprintf(unknown_buffer.data(), unknown_buffer.size(), "Unknown error %d", error_number); message = unknown_buffer.data(); diff --git a/src/compat/bionic_pthread_create_runtime.cc b/src/compat/bionic_pthread_create_runtime.cc index e34fcf6..af5ff8e 100644 --- a/src/compat/bionic_pthread_create_runtime.cc +++ b/src/compat/bionic_pthread_create_runtime.cc @@ -114,7 +114,7 @@ int CopySupportedThreadAttributes(const MocktailBionicPthreadAttr& source, if (RejectRealtimeScheduling(source.sched_policy)) { return EPERM; } - if (source.sched_policy != SCHED_NORMAL) { + if (source.sched_policy != SCHED_OTHER) { result = pthread_attr_setschedpolicy(destination, source.sched_policy); if (result != 0) { return result; diff --git a/src/runtime/external_launch_broker.cc b/src/runtime/external_launch_broker.cc index 3ea4632..b723e28 100644 --- a/src/runtime/external_launch_broker.cc +++ b/src/runtime/external_launch_broker.cc @@ -10,6 +10,7 @@ #include #include #include +#include #include #include diff --git a/tests/bionic_host_libc_runtime_test.cc b/tests/bionic_host_libc_runtime_test.cc index 663bea7..b67e753 100644 --- a/tests/bionic_host_libc_runtime_test.cc +++ b/tests/bionic_host_libc_runtime_test.cc @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "libc_shim/libc_shim.h" @@ -214,9 +215,18 @@ TEST(BionicHostLibcRuntimeTest, UsesBionicPosixStrErrorContract) { EXPECT_NE(std::strstr(buffer.data(), "Invalid"), nullptr); EXPECT_EQ(errno, EDOM); - buffer.fill('\0'); - EXPECT_EQ(mocktail_bionic_strerror_r(4567, buffer.data(), buffer.size()), 0); - EXPECT_NE(std::strstr(buffer.data(), "4567"), nullptr); + EXPECT_EQ(mocktail_bionic_strerror_r(0, buffer.data(), buffer.size()), 0); + EXPECT_STREQ(buffer.data(), std::strerror(0)); + EXPECT_EQ(errno, EDOM); + + for (const int error_number : {-1, 4567, INT_MIN, INT_MAX}) { + errno = EDOM; + ASSERT_EQ(mocktail_bionic_strerror_r(error_number, buffer.data(), + buffer.size()), 0); + EXPECT_EQ(std::string(buffer.data()), + "Unknown error " + std::to_string(error_number)); + EXPECT_EQ(errno, EDOM); + } std::array truncated{}; errno = 0; diff --git a/third_party/mcpelauncher-linker/include/assert.h b/third_party/mcpelauncher-linker/include/assert.h index 7205cce..3ffb4a1 100644 --- a/third_party/mcpelauncher-linker/include/assert.h +++ b/third_party/mcpelauncher-linker/include/assert.h @@ -1,4 +1,5 @@ +#include #include "../bionic/libc/include/assert.h" #ifdef __BIONIC__ #undef __BIONIC__ -#endif \ No newline at end of file +#endif diff --git a/third_party/mcpelauncher-linker/include/compat.h b/third_party/mcpelauncher-linker/include/compat.h index 4f435e0..4ce7490 100644 --- a/third_party/mcpelauncher-linker/include/compat.h +++ b/third_party/mcpelauncher-linker/include/compat.h @@ -15,8 +15,12 @@ typedef std::atomic_int atomic_int; typedef std::atomic_uint atomic_uint; #endif +#ifndef PAGE_SIZE #define PAGE_SIZE 4096 +#endif +#ifndef PAGE_MASK #define PAGE_MASK (~(PAGE_SIZE - 1)) +#endif #if !defined(__APPLE__) && !defined(__FreeBSD__) #define DEF_WEAK(a) #define __BIONIC_ALIGN(__value, __alignment) (((__value) + (__alignment)-1) & ~((__alignment)-1)) diff --git a/third_party/mcpelauncher-linker/include/sys/cdefs.h b/third_party/mcpelauncher-linker/include/sys/cdefs.h index 3e6455b..53749da 100644 --- a/third_party/mcpelauncher-linker/include/sys/cdefs.h +++ b/third_party/mcpelauncher-linker/include/sys/cdefs.h @@ -1,6 +1,12 @@ #pragma once #ifndef __APPLE__ +#pragma push_macro("_FORTIFY_SOURCE") +#pragma push_macro("__bos") +#undef _FORTIFY_SOURCE +#undef __bos #include "../../bionic/libc/include/sys/cdefs.h" +#pragma pop_macro("__bos") +#pragma pop_macro("_FORTIFY_SOURCE") #endif #if defined(__has_include_next) #if __has_include_next() From bc108106dbaf89333dd85d8db9f48f841b973410 Mon Sep 17 00:00:00 2001 From: komaruworld Date: Thu, 8 Oct 2026 18:14:23 +0300 Subject: [PATCH 3/4] mog chimera --- include/compat/bionic_host_libc_runtime.h | 1 + src/compat/bionic_host_libc_runtime.cc | 4 ++++ src/linker/linker.cc | 4 +++- src/update/readiness_canary.cc | 4 +++- tests/bionic_host_libc_runtime_test.cc | 15 +++++++++++++++ tests/linker_registry_test.cc | 2 ++ tests/native_update_test.cc | 19 +++++++++++++++++++ 7 files changed, 47 insertions(+), 2 deletions(-) diff --git a/include/compat/bionic_host_libc_runtime.h b/include/compat/bionic_host_libc_runtime.h index 15c14d9..be55994 100644 --- a/include/compat/bionic_host_libc_runtime.h +++ b/include/compat/bionic_host_libc_runtime.h @@ -90,6 +90,7 @@ int mocktail_bionic_cxa_thread_atexit_impl( mocktail::compat::BionicThreadDestructor destructor, void* argument, void* dso_handle); void mocktail_bionic_arc4random_buf(void* buffer, size_t size); +int mocktail_bionic_atoi(const char* text); mocktail::compat::BionicMallinfoSnapshot mocktail_bionic_mallinfo(); int mocktail_bionic_sysinfo(struct sysinfo* info); int mocktail_bionic_uname(struct utsname* name); diff --git a/src/compat/bionic_host_libc_runtime.cc b/src/compat/bionic_host_libc_runtime.cc index 324e2e9..d1d6cd6 100644 --- a/src/compat/bionic_host_libc_runtime.cc +++ b/src/compat/bionic_host_libc_runtime.cc @@ -378,6 +378,10 @@ extern "C" void mocktail_bionic_arc4random_buf(void* buffer, size_t size) { mocktail::compat::BionicArc4RandomBuffer(buffer, size); } +extern "C" int mocktail_bionic_atoi(const char* text) { + return static_cast(std::strtol(text, nullptr, 10)); +} + extern "C" mocktail::compat::BionicMallinfoSnapshot mocktail_bionic_mallinfo() { return mocktail::compat::BionicMallinfo(); } diff --git a/src/linker/linker.cc b/src/linker/linker.cc index 24a8df1..e8461cb 100644 --- a/src/linker/linker.cc +++ b/src/linker/linker.cc @@ -134,7 +134,7 @@ bool IsBionicLibcOnlySymbol(std::string_view symbol) { } return symbol == "__cmsg_nxthdr" || symbol == "__cxa_thread_atexit_impl" || symbol == "__readlink_chk" || symbol == "__register_atfork" || - symbol == "arc4random_buf" || symbol == "geteuid" || + symbol == "arc4random_buf" || symbol == "atoi" || symbol == "geteuid" || symbol == "getuid" || symbol == "lseek64" || symbol == "mallinfo" || symbol == "pread64" || symbol == "pwrite64" || symbol == "sigaction" || symbol == "strerror_r" || @@ -384,6 +384,8 @@ void RegisterBionicHostLibcRuntimeForLibc() { RegisterSyntheticSymbol("libc.so", "arc4random_buf", reinterpret_cast( mocktail_bionic_arc4random_buf)); + RegisterSyntheticSymbol("libc.so", "atoi", + reinterpret_cast(mocktail_bionic_atoi)); RegisterSyntheticSymbol("libc.so", "mallinfo", reinterpret_cast(mocktail_bionic_mallinfo)); RegisterSyntheticSymbol("libc.so", "sysinfo", diff --git a/src/update/readiness_canary.cc b/src/update/readiness_canary.cc index ea56bd2..a33c4cb 100644 --- a/src/update/readiness_canary.cc +++ b/src/update/readiness_canary.cc @@ -468,7 +468,9 @@ CanaryResult RunReadinessCanary(const CanaryOptions& options) { } std::filesystem::remove_all(isolated, filesystem_error); if (!result.error.empty()) return result; - result.exit_code = WIFEXITED(status) ? WEXITSTATUS(status) : 128; + result.exit_code = WIFEXITED(status) + ? WEXITSTATUS(status) + : 128 + (WIFSIGNALED(status) ? WTERMSIG(status) : 0); if (result.exit_code != 0) { result.error = "graphics canary exited with status " + diff --git a/tests/bionic_host_libc_runtime_test.cc b/tests/bionic_host_libc_runtime_test.cc index b67e753..2809cb0 100644 --- a/tests/bionic_host_libc_runtime_test.cc +++ b/tests/bionic_host_libc_runtime_test.cc @@ -206,6 +206,21 @@ TEST(BionicHostLibcRuntimeTest, HidesPrivilegedHostIdentityFromAndroidGuest) { mocktail::compat::NormalizeBionicApplicationUid(::geteuid())); } +TEST(BionicHostLibcRuntimeTest, ParsesAtoiWithBionicOverflowBehavior) { + EXPECT_EQ(mocktail_bionic_atoi(""), 0); + EXPECT_EQ(mocktail_bionic_atoi("invalid"), 0); + EXPECT_EQ(mocktail_bionic_atoi(" -42suffix"), -42); + EXPECT_EQ(mocktail_bionic_atoi("2147483647"), INT_MAX); + EXPECT_EQ(mocktail_bionic_atoi("-2147483648"), INT_MIN); + EXPECT_EQ(mocktail_bionic_atoi("2147483648"), INT_MIN); + EXPECT_EQ(mocktail_bionic_atoi("4294967295"), -1); + EXPECT_EQ(mocktail_bionic_atoi("9999999999"), 1410065407); + + errno = 0; + EXPECT_EQ(mocktail_bionic_atoi("9223372036854775808"), -1); + EXPECT_EQ(errno, ERANGE); +} + TEST(BionicHostLibcRuntimeTest, UsesBionicPosixStrErrorContract) { std::array buffer{}; diff --git a/tests/linker_registry_test.cc b/tests/linker_registry_test.cc index 860f75d..75816bd 100644 --- a/tests/linker_registry_test.cc +++ b/tests/linker_registry_test.cc @@ -130,6 +130,8 @@ TEST(LinkerRegistryTest, KeepsHostIndependentBionicAbiOwnedByLibc) { reinterpret_cast(mocktail___readlink_chk)); EXPECT_EQ(symbols.at("arc4random_buf"), reinterpret_cast(mocktail_bionic_arc4random_buf)); + EXPECT_EQ(symbols.at("atoi"), + reinterpret_cast(mocktail_bionic_atoi)); EXPECT_EQ(symbols.at("mallinfo"), reinterpret_cast(mocktail_bionic_mallinfo)); EXPECT_EQ(symbols.at("sysinfo"), diff --git a/tests/native_update_test.cc b/tests/native_update_test.cc index c496a1c..e799eb5 100644 --- a/tests/native_update_test.cc +++ b/tests/native_update_test.cc @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -266,6 +267,24 @@ TEST(ReadinessCanaryTest, PreservesEtc2DriverOverride) { } } +TEST(ReadinessCanaryTest, ReportsTerminatingSignal) { + TemporaryDirectory temporary; + CanaryOptions options; + options.runtime_binary = temporary.root() / "runtime"; + options.cache_root = temporary.root() / "cache"; + options.state_root = temporary.root() / "state"; + options.payload_directory = temporary.root() / "payload"; + options.timeout_seconds = 5; + Write(options.runtime_binary, "#!/bin/sh\nkill -TERM $$\n"); + ASSERT_EQ(chmod(options.runtime_binary.c_str(), 0700), 0); + + const auto result = RunReadinessCanary(options); + EXPECT_FALSE(result); + EXPECT_EQ(result.exit_code, 128 + SIGTERM); + EXPECT_EQ(result.error, "graphics canary exited with status " + + std::to_string(128 + SIGTERM)); +} + TEST(ReadinessCanaryTest, AcceptsRealPresentWithoutShaderPackSummary) { const std::string valid = "[compat] legacy binary patches: disabled\n" From cb2e9dd5980695069ad71376b494d5df48a15e8d Mon Sep 17 00:00:00 2001 From: komaruworld Date: Thu, 8 Oct 2026 21:12:29 +0300 Subject: [PATCH 4/4] Small ci fix --- config/upstream_dependencies.json | 2 +- tests/native_update_test.cc | 1 + tests/webview_helper_launcher_test.cc | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/config/upstream_dependencies.json b/config/upstream_dependencies.json index eb796fd..b8f9b19 100644 --- a/config/upstream_dependencies.json +++ b/config/upstream_dependencies.json @@ -32,7 +32,7 @@ "mode": "vendored-patched-snapshot", "url": "https://github.com/minecraft-linux/mcpelauncher-linker.git", "upstream_commit": "1ac3ea6c1cf4f73a84d73f0bff510fba94a7d0f2", - "vendor_tree": "fca44d85e3773c135ccfc603b14abdf6aeb8efd1", + "vendor_tree": "0637221e48f382ec8d0bc701385f4b10bcd07a65", "patch": "third_party/patches/mcpelauncher-linker.patch", "nested_sources": { "android_bionic": { diff --git a/tests/native_update_test.cc b/tests/native_update_test.cc index e799eb5..c96f888 100644 --- a/tests/native_update_test.cc +++ b/tests/native_update_test.cc @@ -798,6 +798,7 @@ TEST(PayloadStoreTest, StagesAndPromotesVerifiedExactPayload) { temporary.root() / "compatibility.json"; Write(compatibility, "{\"schema_version\":1,\"profiles\":[{" + "\"abi\":\"" + std::string(compat::kGuestAbi) + "\"," "\"version_name\":\"2.727.1199\",\"version_code\":2628," "\"elf_build_id\":\"1686400865ae0e408cd7bd67de7a439625c6fd13\"," "\"status\":\"supported\",\"default_allowed\":true," diff --git a/tests/webview_helper_launcher_test.cc b/tests/webview_helper_launcher_test.cc index ca24ade..b5b0944 100644 --- a/tests/webview_helper_launcher_test.cc +++ b/tests/webview_helper_launcher_test.cc @@ -350,7 +350,7 @@ TEST(WebViewHelperLauncherTest, OwnsAndClosesTheExactSpawnedProcess) { const std::filesystem::path close_packet = temporary.path() / "close-packet"; const std::filesystem::path ready = temporary.path() / "ready"; ASSERT_TRUE(WriteExecutable(helper, - "#!/bin/sh\n" + "#!/usr/bin/env bash\n" "cat >/dev/null\n" "touch '" + ready.string() +