diff --git a/stratosphere/creport/source/creport_crash_report.cpp b/stratosphere/creport/source/creport_crash_report.cpp index f2df1c30c..edb0074bb 100644 --- a/stratosphere/creport/source/creport_crash_report.cpp +++ b/stratosphere/creport/source/creport_crash_report.cpp @@ -219,7 +219,7 @@ namespace ams::creport { void CrashReport::HandleDebugEventInfoCreateThread(const svc::DebugEventInfo &d) { /* Save info on the thread's TLS address for later. */ - this->thread_tls_map[d.info.create_thread.thread_id] = d.info.create_thread.tls_address; + this->thread_tls_map.SetThreadTls(d.info.create_thread.thread_id, d.info.create_thread.tls_address); } void CrashReport::HandleDebugEventInfoException(const svc::DebugEventInfo &d) { diff --git a/stratosphere/creport/source/creport_crash_report.hpp b/stratosphere/creport/source/creport_crash_report.hpp index 141b0b9ec..44466c699 100644 --- a/stratosphere/creport/source/creport_crash_report.hpp +++ b/stratosphere/creport/source/creport_crash_report.hpp @@ -30,7 +30,7 @@ namespace ams::creport { Result result = ResultIncompleteReport(); /* Meta, used for building module/thread list. */ - std::map thread_tls_map; + ThreadTlsMap thread_tls_map = {}; /* Attach process info. */ svc::DebugInfoCreateProcess process_info = {}; @@ -49,9 +49,11 @@ namespace ams::creport { ThreadList *thread_list = nullptr; /* Memory heap. */ - lmem::HeapHandle heap_handle; - u8 heap_storage[MemoryHeapSize]; + lmem::HeapHandle heap_handle = nullptr; + u8 heap_storage[MemoryHeapSize] = {}; public: + constexpr CrashReport() = default; + Result GetResult() const { return this->result; } diff --git a/stratosphere/creport/source/creport_main.cpp b/stratosphere/creport/source/creport_main.cpp index f016bc00e..e00dd1c35 100644 --- a/stratosphere/creport/source/creport_main.cpp +++ b/stratosphere/creport/source/creport_main.cpp @@ -24,7 +24,7 @@ extern "C" { u32 __nx_applet_type = AppletType_None; u32 __nx_fs_num_sessions = 1; - #define INNER_HEAP_SIZE 0x4000 + #define INNER_HEAP_SIZE 0x0 size_t nx_inner_heap_size = INNER_HEAP_SIZE; char nx_inner_heap[INNER_HEAP_SIZE]; @@ -68,9 +68,32 @@ void __libnx_initheap(void) { fake_heap_end = (char*)addr + size; } +namespace { + + + constinit u8 g_fs_heap_memory[4_KB]; + lmem::HeapHandle g_fs_heap_handle; + + void *AllocateForFs(size_t size) { + return lmem::AllocateFromExpHeap(g_fs_heap_handle, size); + } + + void DeallocateForFs(void *p, size_t size) { + return lmem::FreeToExpHeap(g_fs_heap_handle, p); + } + + void InitializeFsHeap() { + g_fs_heap_handle = lmem::CreateExpHeap(g_fs_heap_memory, sizeof(g_fs_heap_memory), lmem::CreateOption_None); + } + +} + void __appInit(void) { hos::InitializeForStratosphere(); + InitializeFsHeap(); + fs::SetAllocator(AllocateForFs, DeallocateForFs); + sm::DoWithSession([&]() { R_ABORT_UNLESS(fsInitialize()); }); @@ -83,7 +106,31 @@ void __appExit(void) { fsExit(); } -static creport::CrashReport g_crash_report; +namespace ams { + + void *Malloc(size_t size) { + AMS_ABORT("ams::Malloc was called"); + } + + void Free(void *ptr) { + AMS_ABORT("ams::Free was called"); + } + +} + +void *operator new(size_t size) { + AMS_ABORT("operator new(size_t) was called"); +} + +void operator delete(void *p) { + AMS_ABORT("operator delete(void *) was called"); +} + +namespace { + + constinit creport::CrashReport g_crash_report; + +} int main(int argc, char **argv) { /* Set thread name. */ diff --git a/stratosphere/creport/source/creport_threads.cpp b/stratosphere/creport/source/creport_threads.cpp index 0a3373ac7..162a0533f 100644 --- a/stratosphere/creport/source/creport_threads.cpp +++ b/stratosphere/creport/source/creport_threads.cpp @@ -113,7 +113,7 @@ namespace ams::creport { } } - bool ThreadInfo::ReadFromProcess(Handle debug_handle, std::map &tls_map, u64 thread_id, bool is_64_bit) { + bool ThreadInfo::ReadFromProcess(Handle debug_handle, ThreadTlsMap &tls_map, u64 thread_id, bool is_64_bit) { /* Set thread id. */ this->thread_id = thread_id; @@ -145,8 +145,8 @@ namespace ams::creport { /* Read TLS, if present. */ /* TODO: struct definitions for nnSdk's ThreadType/TLS Layout? */ - if (tls_map.find(thread_id) != tls_map.end()) { - this->tls_address = tls_map[thread_id]; + this->tls_address = 0; + if (tls_map.GetThreadTls(std::addressof(this->tls_address), thread_id)) { u8 thread_tls[0x200]; if (R_SUCCEEDED(svcReadDebugProcessMemory(thread_tls, debug_handle, this->tls_address, sizeof(thread_tls)))) { std::memcpy(this->tls, thread_tls, sizeof(this->tls)); @@ -243,7 +243,7 @@ namespace ams::creport { } } - void ThreadList::ReadFromProcess(Handle debug_handle, std::map &tls_map, bool is_64_bit) { + void ThreadList::ReadFromProcess(Handle debug_handle, ThreadTlsMap &tls_map, bool is_64_bit) { this->thread_count = 0; /* Get thread list. */ diff --git a/stratosphere/creport/source/creport_threads.hpp b/stratosphere/creport/source/creport_threads.hpp index 926aa961c..455742a92 100644 --- a/stratosphere/creport/source/creport_threads.hpp +++ b/stratosphere/creport/source/creport_threads.hpp @@ -22,6 +22,39 @@ namespace ams::creport { /* Forward declare ModuleList class. */ class ModuleList; + static constexpr size_t ThreadCountMax = 0x60; + + template + class ThreadTlsMapImpl { + private: + std::pair m_map[MaxThreadCount]; + size_t m_index; + public: + constexpr ThreadTlsMapImpl() : m_map(), m_index(0) { /* ... */ } + + constexpr void ResetThreadTlsMap() { + m_index = 0; + } + + constexpr void SetThreadTls(u64 thread_id, u64 tls) { + if (m_index < util::size(m_map)) { + m_map[m_index++] = std::make_pair(thread_id, tls); + } + } + + constexpr bool GetThreadTls(u64 *out, u64 thread_id) const { + for (size_t i = 0; i < m_index; ++i) { + if (m_map[i].first == thread_id) { + *out = m_map[i].second; + return true; + } + } + return false; + } + }; + + using ThreadTlsMap = ThreadTlsMapImpl; + class ThreadInfo { private: static constexpr size_t StackTraceSizeMax = 0x20; @@ -76,7 +109,7 @@ namespace ams::creport { this->module_list = ml; } - bool ReadFromProcess(Handle debug_handle, std::map &tls_map, u64 thread_id, bool is_64_bit); + bool ReadFromProcess(Handle debug_handle, ThreadTlsMap &tls_map, u64 thread_id, bool is_64_bit); void SaveToFile(ScopedFile &file); void DumpBinary(ScopedFile &file); private: @@ -84,8 +117,6 @@ namespace ams::creport { }; class ThreadList { - private: - static constexpr size_t ThreadCountMax = 0x60; private: size_t thread_count = 0; ThreadInfo threads[ThreadCountMax]; @@ -104,7 +135,7 @@ namespace ams::creport { } } - void ReadFromProcess(Handle debug_handle, std::map &tls_map, bool is_64_bit); + void ReadFromProcess(Handle debug_handle, ThreadTlsMap &tls_map, bool is_64_bit); void SaveToFile(ScopedFile &file); void DumpBinary(ScopedFile &file, u64 crashed_thread_id); }; diff --git a/stratosphere/fatal/source/fatal_debug.cpp b/stratosphere/fatal/source/fatal_debug.cpp index 6a4d1a660..6be9c5fe5 100644 --- a/stratosphere/fatal/source/fatal_debug.cpp +++ b/stratosphere/fatal/source/fatal_debug.cpp @@ -30,28 +30,38 @@ namespace ams::fatal::srv { constexpr inline size_t MaxThreads = 0x60; - constinit std::pair g_thread_id_to_tls_map[MaxThreads]; - constinit size_t g_tls_map_index = 0; + template + class ThreadTlsMapImpl { + private: + std::pair m_map[MaxThreadCount]; + size_t m_index; + public: + constexpr ThreadTlsMapImpl() : m_map(), m_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; + constexpr void ResetThreadTlsMap() { + m_index = 0; } - } - return false; - } + + constexpr void SetThreadTls(u64 thread_id, u64 tls) { + if (m_index < util::size(m_map)) { + m_map[m_index++] = std::make_pair(thread_id, tls); + } + } + + constexpr bool GetThreadTls(u64 *out, u64 thread_id) const { + for (size_t i = 0; i < m_index; ++i) { + if (m_map[i].first == thread_id) { + *out = m_map[i].second; + return true; + } + } + return false; + } + }; + + using ThreadTlsMap = ThreadTlsMapImpl; + + constinit ThreadTlsMap g_thread_id_to_tls_map; 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. */ @@ -202,7 +212,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. */ - ResetThreadTlsMap(); + g_thread_id_to_tls_map.ResetThreadTlsMap(); { bool got_create_process = false; svc::DebugEventInfo d; @@ -214,7 +224,7 @@ namespace ams::fatal::srv { got_create_process = true; break; case svc::DebugEvent_CreateThread: - SetThreadTls(d.info.create_thread.thread_id, d.info.create_thread.tls_address); + g_thread_id_to_tls_map.SetThreadTls(d.info.create_thread.thread_id, d.info.create_thread.tls_address); break; case svc::DebugEvent_Exception: case svc::DebugEvent_ExitProcess: @@ -250,7 +260,7 @@ namespace ams::fatal::srv { for (s32 i = 0; i < thread_count; i++) { const u64 cur_thread_id = thread_ids[i]; u64 cur_thread_tls; - if (!GetThreadTls(std::addressof(cur_thread_tls), cur_thread_id)) { + if (!g_thread_id_to_tls_map.GetThreadTls(std::addressof(cur_thread_tls), cur_thread_id)) { continue; }