Merge pull request #3214 from fma-rc/fix/libs-bind-now

fix(libs): bind the system libraries eagerly on Linux
This commit is contained in:
Dean 2026-10-11 19:35:33 +13:00 committed by GitHub
commit 1690db9a24
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 31 additions and 0 deletions

View File

@ -53,6 +53,9 @@ set(LIBS_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
add_subdirectory(${LIBC_DIR} ${CMAKE_CURRENT_BINARY_DIR}/prx/libc)
target_include_directories(libc PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
configure_windows_unwind(libc)
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
target_link_options(libc PRIVATE LINKER:-z,now)
endif()
set(UNPATCHED_DIR ${CMAKE_CURRENT_BINARY_DIR}/libs/unpatched)
set(PATCHED_DIR ${CMAKE_CURRENT_BINARY_DIR}/libs)
@ -102,6 +105,9 @@ foreach(LIB_DIR ${LIBS_DIRS})
else()
target_link_libraries(${LIB_NAME} PRIVATE libkernel libc)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
target_link_options(${LIB_NAME} PRIVATE LINKER:-z,now)
endif()
if(WIN32 AND LIB_NAME STREQUAL "libSceNet")
target_link_libraries(${LIB_NAME} PRIVATE ws2_32)
target_compile_definitions(${LIB_NAME} PRIVATE _WIN32_WINNT=0x0602)

View File

@ -81,6 +81,30 @@ void APS5_VABI CheckedEntry(std::uint64_t, std::uint64_t) {
for (;;) sceFiberReturnToThread(0, &received);
}
constexpr std::size_t SmallContextSize = 2048;
constexpr unsigned char SmallGuardFill = 0xa5;
alignas(16) std::array<unsigned char, 64 * 1024> g_smallArea;
FiberStorage g_smallStorage;
void APS5_VABI SmallEntry(std::uint64_t, std::uint64_t) {
std::uint64_t received = 0;
for (;;) sceFiberReturnToThread(0, &received);
}
void RunSmallContextFirst() {
auto* small = reinterpret_cast<FiberObject*>(&g_smallStorage);
auto* context = g_smallArea.data() + g_smallArea.size() - SmallContextSize;
g_smallArea.fill(SmallGuardFill);
Require(sceFiberReturnToThread(0, nullptr) == FiberErrorPermission, "return to thread outside a fiber");
Require(_sceFiberInitializeImpl_nid_postfix(small, "small", SmallEntry, 0, context, SmallContextSize, nullptr, 0) == 0, "initialize small");
Require(sceFiberRun_nid_postfix(small, 0, nullptr) == 0, "first fiber run of the process on a 2 KiB context");
Require(sceFiberRun_nid_postfix(small, 0, nullptr) == 0, "resume on a 2 KiB context");
Require(sceFiberFinalize(small) == 0, "finalize small");
for (auto* byte = g_smallArea.data(); byte != context; ++byte) {
Require(*byte == SmallGuardFill, "nothing is written below a 2 KiB context");
}
}
[[gnu::noinline]] std::int32_t RunFirst(std::uint64_t* returned) {
g_threadFramePointer = reinterpret_cast<std::uint64_t>(__builtin_frame_address(0));
const std::int32_t result = sceFiberRun_nid_postfix(g_first, 100, returned);
@ -91,6 +115,7 @@ void APS5_VABI CheckedEntry(std::uint64_t, std::uint64_t) {
}
int main() {
RunSmallContextFirst();
FiberObject* self = nullptr;
Require(sceFiberGetSelf(&self) == FiberErrorPermission, "no fiber on the thread");
Require(_sceFiberInitializeImpl_nid_postfix(g_first, "first", FirstEntry, 11, g_firstContext.data(), g_firstContext.size(), nullptr, 0) == 0, "initialize first");