mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-21 08:12:09 -05:00
The nid_patcher turns each *_nid_no_patch_cut alias into a second dynamic symbol with the same name as the plain alias exported next to it, seven names in all. With those duplicates, LD_DEBUG=bindings shows libstdc++ keeping its own __cxa_allocate_exception, __cxa_throw, __cxa_begin_catch, __cxa_end_catch, __cxa_rethrow, __gxx_personality_v0 and _Unwind_Resume while taking __cxa_init_primary_exception, _Unwind_RaiseException and std::terminate from libc.prx. An exception thrown inside libstdc++ (std::stoi, a stream with exceptions enabled) got a libc header laid over a libstdc++ allocation, reached the libc personality as a foreign exception, matched no typed handler and ended in "terminate called without an active exception". The plain aliases already export these names, so the duplicates go. libstdc++ also describes std::__ios_failure with __iosfail_type_info, a class that privately derives from __si_class_type_info at the same address. Kind now follows such single same-address bases to the __cxxabiv1 class, so catching std::ios_base::failure or std::exception matches a stream failure. The plain aliases came ina4c519b26next to the cut aliases from14f8c16ac.
63 lines
1.8 KiB
C++
63 lines
1.8 KiB
C++
#include <exception>
|
|
#include <fstream>
|
|
#include <ios>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
|
|
static bool CatchesConversion() {
|
|
try {
|
|
(void)std::stoi("x");
|
|
} catch (const std::invalid_argument& error) {
|
|
return std::string(error.what()) == "stoi";
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static bool CatchesStreamFailure(const char* path) {
|
|
try {
|
|
std::ofstream file;
|
|
file.exceptions(std::ios::failbit);
|
|
file.open(path);
|
|
} catch (const std::ios_base::failure&) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static bool CatchesStreamFailureAsException(const char* path) {
|
|
try {
|
|
std::ofstream file;
|
|
file.exceptions(std::ios::failbit);
|
|
file.open(path);
|
|
} catch (const std::exception&) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static bool RethrowsStoredStreamFailure(const char* path) {
|
|
std::exception_ptr failure;
|
|
try {
|
|
std::ofstream file;
|
|
file.exceptions(std::ios::failbit);
|
|
file.open(path);
|
|
} catch (...) {
|
|
failure = std::current_exception();
|
|
}
|
|
if (!failure) return false;
|
|
try {
|
|
std::rethrow_exception(failure);
|
|
} catch (const std::ios_base::failure&) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
extern "C" const char* HostLibstdcxxExceptionFailure(const char* path) {
|
|
if (!CatchesConversion()) return "std::stoi failure was not caught as std::invalid_argument";
|
|
if (!CatchesStreamFailure(path)) return "std::ofstream::open failure was not caught as std::ios_base::failure";
|
|
if (!CatchesStreamFailureAsException(path)) return "std::ofstream::open failure was not caught as std::exception";
|
|
if (!RethrowsStoredStreamFailure(path)) return "a stored std::ofstream::open failure was not rethrown";
|
|
return nullptr;
|
|
}
|