97 lines
2.6 KiB
C++
97 lines
2.6 KiB
C++
#include "SceTypes.hpp"
|
|
#include "prx/libc/include/General.hpp"
|
|
#include "prx/libc/include/HeapDiagnostics.hpp"
|
|
#include "prx/libc/include/HostThreadLocal.hpp"
|
|
#include <sstream>
|
|
#include <stdexcept>
|
|
#include <vector>
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#else
|
|
#include <dlfcn.h>
|
|
#endif
|
|
|
|
extern "C" void APS5_VABI sceKernelSetThreadDtors(thread_dtors_func_t dtors);
|
|
|
|
namespace {
|
|
|
|
using ThreadDestructorFunction = void (APS5_VABI*)(void*);
|
|
|
|
struct ThreadDestructor {
|
|
ThreadDestructorFunction function;
|
|
void* object;
|
|
void* dsoSymbol;
|
|
};
|
|
|
|
struct ThreadDestructorsTag {};
|
|
|
|
std::vector<ThreadDestructor>& ThreadDestructors() {
|
|
return HostThreadLocal<std::vector<ThreadDestructor>, ThreadDestructorsTag>();
|
|
}
|
|
|
|
bool IsInLoadedImage(const void* address) {
|
|
if (address == nullptr)
|
|
return false;
|
|
#ifdef _WIN32
|
|
HMODULE module = nullptr;
|
|
return GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, static_cast<LPCSTR>(address), &module) != 0;
|
|
#else
|
|
Dl_info info{};
|
|
return dladdr(address, &info) != 0;
|
|
#endif
|
|
}
|
|
|
|
void APS5_VABI RunThreadDestructors_nid_no_patch() {
|
|
auto& destructors = ThreadDestructors();
|
|
while (!destructors.empty()) {
|
|
const ThreadDestructor destructor = destructors.back();
|
|
destructors.pop_back();
|
|
const auto* function = reinterpret_cast<const void*>(destructor.function);
|
|
if (!IsInLoadedImage(function)) {
|
|
std::ostringstream message;
|
|
message << "thread_local destructor " << function << " of dso " << destructor.dsoSymbol << " is not in a loaded image";
|
|
throw std::runtime_error(message.str());
|
|
}
|
|
destructor.function(destructor.object);
|
|
}
|
|
}
|
|
|
|
void RegisterThreadExitHook() {
|
|
[[maybe_unused]] static const bool registered = [] {
|
|
sceKernelSetThreadDtors(RunThreadDestructors_nid_no_patch);
|
|
return true;
|
|
}();
|
|
}
|
|
|
|
}
|
|
|
|
extern "C" {
|
|
|
|
int Need_sceLibcInternal_nid_postfix = 1;
|
|
|
|
void APS5_VABI __cxa_finalize_nid_postfix(void* dsoHandle) {
|
|
CxaFinalize_nid_no_patch(dsoHandle);
|
|
}
|
|
|
|
void APS5_VABI sceLibcHeapGetTraceInfo_nid_postfix(Info* info) {
|
|
LibcHeapTraceInfo_nid_no_patch(info);
|
|
}
|
|
|
|
int APS5_VABI _sceLibcInternalThreadAtexit_nid_postfix(ThreadDestructorFunction destructor, void* object, void* dsoSymbol) {
|
|
RegisterThreadExitHook();
|
|
ThreadDestructors().push_back({destructor, object, dsoSymbol});
|
|
return 0;
|
|
}
|
|
|
|
void APS5_VABI _sceLibcInternalThreadDtors_nid_postfix() {
|
|
RunThreadDestructors_nid_no_patch();
|
|
}
|
|
|
|
int APS5_VABI _sceLibcInternalForceTlsDestructor_nid_postfix(KernelModule handle) {
|
|
(void)handle;
|
|
NotImplemented_nid_no_patch(__func__);
|
|
return 0;
|
|
}
|
|
|
|
}
|