fatal: wip (pending libnx pr) update for new sf semantics

This commit is contained in:
Michael Scire 2021-01-18 08:48:47 -08:00 committed by SciresM
parent ed7c0605f9
commit 402e4d1adb
7 changed files with 191 additions and 28 deletions

View file

@ -28,6 +28,31 @@ namespace ams::fatal::srv {
u64 lr;
};
constexpr inline size_t MaxThreads = 0x60;
constinit std::pair<u64, u64> g_thread_id_to_tls_map[MaxThreads];
constinit size_t g_tls_map_index = 0;
void ResetThreadTlsMap() {
g_tls_map_index = 0;
}
void SetThreadTls(u64 thread_id, u64 tls) {
if (g_tls_map_index < MaxThreads) {
g_thread_id_to_tls_map[g_tls_map_index++] = std::make_pair(thread_id, tls);
}
}
bool GetThreadTls(u64 *out, u64 thread_id) {
for (size_t i = 0; i < g_tls_map_index; ++i) {
if (g_thread_id_to_tls_map[i].first == thread_id) {
*out = g_thread_id_to_tls_map[i].second;
return true;
}
}
return false;
}
bool IsThreadFatalCaller(Result result, u32 debug_handle, u64 thread_id, u64 thread_tls_addr, ThreadContext *thread_ctx) {
/* Verify that the thread is running or waiting. */
{
@ -177,7 +202,7 @@ namespace ams::fatal::srv {
ON_SCOPE_EXIT { R_ABORT_UNLESS(svc::CloseHandle(debug_handle)); };
/* First things first, check if process is 64 bits, and get list of thread infos. */
std::unordered_map<u64, u64> thread_id_to_tls;
ResetThreadTlsMap();
{
bool got_create_process = false;
svc::DebugEventInfo d;
@ -189,7 +214,7 @@ namespace ams::fatal::srv {
got_create_process = true;
break;
case svc::DebugEvent_CreateThread:
thread_id_to_tls[d.info.create_thread.thread_id] = d.info.create_thread.tls_address;
SetThreadTls(d.info.create_thread.thread_id, d.info.create_thread.tls_address);
break;
case svc::DebugEvent_Exception:
case svc::DebugEvent_ExitProcess:
@ -224,13 +249,14 @@ namespace ams::fatal::srv {
/* We need to locate the thread that's called fatal. */
for (s32 i = 0; i < thread_count; i++) {
const u64 cur_thread_id = thread_ids[i];
if (thread_id_to_tls.find(cur_thread_id) == thread_id_to_tls.end()) {
u64 cur_thread_tls;
if (!GetThreadTls(std::addressof(cur_thread_tls), cur_thread_id)) {
continue;
}
if (IsThreadFatalCaller(ctx->result, debug_handle, cur_thread_id, thread_id_to_tls[cur_thread_id], &thread_ctx)) {
thread_id = cur_thread_id;
thread_tls = thread_id_to_tls[thread_id];
if (IsThreadFatalCaller(ctx->result, debug_handle, cur_thread_id, cur_thread_tls, &thread_ctx)) {
thread_id = cur_thread_id;
thread_tls = cur_thread_tls;
found_fatal_caller = true;
break;
}