mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-22 08:33:12 -05:00
libstdc++ and libgcc raise C++ exceptions as SEH exceptions (STATUS_GCC_THROW, 0x20474343), which the system dispatcher delivers by unwinding frame by frame with each function's unwind data. The libraries are built with -fno-asynchronous-unwind-tables and unwind with DWARF, so their functions have no SEH unwind data. When a host runtime call such as operator new throws straight into one of them, the dispatcher cannot unwind it: no handler, the unhandled exception filter or std::terminate runs, and the process ends without output and with exit code 0x20474343. The vectored crash handler now follows a GCC exception through the runtime frames that raise it (KERNELBASE, libgcc_s_seh-1, libstdc++-6). When the first frame outside them has no unwind data, it reports the exception's type, the thread and that frame, and lists the stack's return address candidates, before the dispatcher continues. The test loads libc.prx, then lets operator new throw std::bad_alloc into a function built with the libraries' flags. Without the handler change it exits silently with 0x20474343.
30 lines
867 B
C++
30 lines
867 B
C++
#include <cstddef>
|
|
#include <cstdio>
|
|
#include <new>
|
|
#include <windows.h>
|
|
|
|
namespace {
|
|
|
|
[[gnu::noinline]] void* AllocateWithoutUnwindData(std::size_t size) {
|
|
void* const block = ::operator new(size);
|
|
std::printf("allocated %p\n", block);
|
|
return block;
|
|
}
|
|
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
if (argc != 2) {
|
|
std::fprintf(stderr, "usage: %s <libc.prx>\n", argv[0]);
|
|
return 2;
|
|
}
|
|
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
|
|
if (LoadLibraryExA(argv[1], nullptr, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS) == nullptr) {
|
|
std::fprintf(stderr, "%s: LoadLibraryEx failed with error %lu\n", argv[1], GetLastError());
|
|
return 1;
|
|
}
|
|
AllocateWithoutUnwindData(std::size_t{1} << 46);
|
|
std::fputs("operator new returned instead of throwing\n", stderr);
|
|
return 1;
|
|
}
|