fix(libs): ex from libc prx: unwind for catch fix (mingw)
This commit is contained in:
parent
bdff4874de
commit
bd0969c3a4
|
|
@ -12,9 +12,7 @@ Execution reaches `_start`, stack unwinding and exception handling tables are bu
|
|||
Shader initialization via `sceAgcCreate*` passes.
|
||||
Audio output and video output initialization pass
|
||||
|
||||
Now: `sceAgcDcbResetQueue not implemented`.
|
||||
|
||||
On Windows, after printing an unhandled exception the process exits with STATUS_STACK_BUFFER_OVERRUN due to the difficulty of manually [implementing proper exception handling](core/libs/prx/libc/src/exception).
|
||||
Now: `sceAgcCbSetShRegisterRangeDirect: null or misaligned address`.
|
||||
|
||||
## Disclaimer
|
||||
|
||||
|
|
|
|||
|
|
@ -14,11 +14,24 @@ if(MINGW)
|
|||
add_compile_options(-fno-asynchronous-unwind-tables)
|
||||
endif()
|
||||
|
||||
function(configure_windows_unwind target)
|
||||
if(MINGW)
|
||||
if(NOT EXISTS "${CMAKE_OBJCOPY}")
|
||||
message(FATAL_ERROR "Windows DWARF unwinding requires objcopy")
|
||||
endif()
|
||||
add_custom_command(TARGET ${target} POST_BUILD
|
||||
COMMAND "${CMAKE_OBJCOPY}" --rename-section .eh_frame=.ehfram "$<TARGET_FILE:${target}>"
|
||||
VERBATIM
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
set(LIBC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/prx/libc)
|
||||
add_library(libc SHARED EXCLUDE_FROM_ALL)
|
||||
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)
|
||||
|
||||
set(UNPATCHED_DIR ${CMAKE_CURRENT_BINARY_DIR}/libs/unpatched)
|
||||
set(PATCHED_DIR ${CMAKE_CURRENT_BINARY_DIR}/libs)
|
||||
|
|
@ -56,6 +69,7 @@ foreach(LIB_DIR ${LIBS_DIRS})
|
|||
else()
|
||||
add_library(${LIB_NAME} SHARED EXCLUDE_FROM_ALL ${LIB_DIR}/Export.cpp)
|
||||
target_include_directories(${LIB_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
configure_windows_unwind(${LIB_NAME})
|
||||
endif()
|
||||
|
||||
if(LIB_NAME STREQUAL "libkernel")
|
||||
|
|
@ -87,3 +101,13 @@ foreach(LIB_DIR ${LIBS_DIRS})
|
|||
endforeach()
|
||||
|
||||
add_custom_target(libs DEPENDS ${PATCHED_OUTPUTS})
|
||||
|
||||
if(MINGW)
|
||||
foreach(runtimeLinkFlag IN ITEMS -static-libgcc -static-libstdc++ -static)
|
||||
string(REPLACE "${runtimeLinkFlag}" "" CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
|
||||
endforeach()
|
||||
add_executable(windows_exception_tests EXCLUDE_FROM_ALL tests/WindowsExceptions.cpp)
|
||||
set_target_properties(windows_exception_tests PROPERTIES CXX_EXTENSIONS OFF)
|
||||
target_link_libraries(windows_exception_tests PRIVATE libc)
|
||||
configure_windows_unwind(windows_exception_tests)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -63,3 +63,5 @@ endforeach()
|
|||
add_executable(agc_command_tests EXCLUDE_FROM_ALL tests/Commands.cpp)
|
||||
target_include_directories(agc_command_tests PRIVATE ${LIBS_INCLUDE_DIR})
|
||||
target_link_libraries(agc_command_tests PRIVATE libSceAgc libc)
|
||||
configure_windows_unwind(agc_command_tests)
|
||||
configure_windows_unwind(libSceAgc)
|
||||
|
|
|
|||
|
|
@ -12,3 +12,4 @@ add_library(libSceAgcDriver SHARED EXCLUDE_FROM_ALL
|
|||
|
||||
target_include_directories(libSceAgcDriver PRIVATE ${LIBS_INCLUDE_DIR})
|
||||
target_link_libraries(libSceAgcDriver PRIVATE libc)
|
||||
configure_windows_unwind(libSceAgcDriver)
|
||||
|
|
|
|||
|
|
@ -13,3 +13,4 @@ target_include_directories(libSceAudioOut PRIVATE
|
|||
${CMAKE_SOURCE_DIR}/3rdparty/SDL2/include
|
||||
)
|
||||
target_link_libraries(libSceAudioOut PRIVATE libc libkernel SDL2-static)
|
||||
configure_windows_unwind(libSceAudioOut)
|
||||
|
|
|
|||
|
|
@ -10,3 +10,4 @@ target_include_directories(libSceNpTrophy2 PRIVATE
|
|||
${LIBS_INCLUDE_DIR}
|
||||
)
|
||||
target_link_libraries(libSceNpTrophy2 PRIVATE libc)
|
||||
configure_windows_unwind(libSceNpTrophy2)
|
||||
|
|
|
|||
|
|
@ -12,3 +12,4 @@ target_include_directories(libSceNpUniversalDataSystem PRIVATE
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
target_link_libraries(libSceNpUniversalDataSystem PRIVATE libc)
|
||||
configure_windows_unwind(libSceNpUniversalDataSystem)
|
||||
|
|
|
|||
|
|
@ -10,3 +10,4 @@ target_include_directories(libSceVideoOut PRIVATE
|
|||
${CMAKE_SOURCE_DIR}/3rdparty/SDL2/include
|
||||
)
|
||||
target_link_libraries(libSceVideoOut PRIVATE libc libkernel SDL2-static)
|
||||
configure_windows_unwind(libSceVideoOut)
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ bool DecodeFrame(_Unwind_Context& context, Frame& frame) {
|
|||
while (end - p >= 8) {
|
||||
const Byte* record = p;
|
||||
const auto length = Read<std::uint32_t>(p);
|
||||
if (!length) break;
|
||||
if (!length) continue;
|
||||
if (length == 0xffffffff || length < 4 || Word(end - p) < length) return false;
|
||||
const Byte* next = p + length;
|
||||
if (Read<std::uint32_t>(p)) {
|
||||
|
|
@ -357,6 +357,11 @@ bool Step(_Unwind_Context& context) {
|
|||
if (rule.kind == 1) std::memcpy(destination, reinterpret_cast<void*>(context.cfa + rule.value), 16);
|
||||
else if (rule.kind == 2 && rule.value >= 17 && rule.value < RuleCount)
|
||||
std::memcpy(destination, context.vectorRegisters[rule.value - 17], 16);
|
||||
else if (rule.kind == 3) {
|
||||
Word address;
|
||||
if (!Expression(rule.expression, context, context.cfa, address)) return false;
|
||||
std::memcpy(destination, reinterpret_cast<const void*>(address), 16);
|
||||
}
|
||||
else if (rule.kind == 5) std::memset(destination, 0, 16);
|
||||
else if (rule.kind != 0) return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,3 +40,4 @@ target_link_libraries(libkernel PRIVATE libc)
|
|||
if(WIN32)
|
||||
target_compile_definitions(libkernel PRIVATE _WIN32_WINNT=0x0602)
|
||||
endif()
|
||||
configure_windows_unwind(libkernel)
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ extern "C" void NotImplemented_nid_no_patch(const char*);
|
|||
|
||||
static int destroyed;
|
||||
struct Guard { ~Guard() { ++destroyed; } };
|
||||
__attribute__((noinline)) static void ThrowNested() {
|
||||
static void ThrowNested() {
|
||||
Guard guard;
|
||||
throw std::runtime_error("native own unwind");
|
||||
}
|
||||
__attribute__((noinline)) static void Rethrow() {
|
||||
static void Rethrow() {
|
||||
Guard guard;
|
||||
try { ThrowNested(); }
|
||||
catch (const std::runtime_error&) { throw; }
|
||||
|
|
@ -25,8 +25,29 @@ int main() {
|
|||
try { NotImplemented_nid_no_patch("cross DLL"); }
|
||||
catch (const std::runtime_error& error) {
|
||||
if (std::strcmp(error.what(), "cross DLL not implemented")) return 3;
|
||||
std::puts("Own Windows exceptions: catch, rethrow, destructors, cross DLL passed");
|
||||
try {
|
||||
Guard guard;
|
||||
throw;
|
||||
} catch (const std::logic_error&) {
|
||||
return 4;
|
||||
} catch (const std::exception& rethrown) {
|
||||
if (&rethrown != &error || destroyed != 3) return 5;
|
||||
}
|
||||
try {
|
||||
Guard guard;
|
||||
throw 42;
|
||||
} catch (const std::exception&) {
|
||||
return 6;
|
||||
} catch (...) {
|
||||
if (destroyed != 4) return 7;
|
||||
try {
|
||||
throw;
|
||||
} catch (int value) {
|
||||
if (value != 42) return 8;
|
||||
}
|
||||
}
|
||||
std::puts("Own Windows exceptions: typed catch, base catch, catch-all, rethrow, destructors, cross DLL passed");
|
||||
return 0;
|
||||
}
|
||||
return 4;
|
||||
return 9;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue