mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-26 13:52:21 +00:00
creport: update for new sf semantics
This commit is contained in:
parent
204539664b
commit
eb1e979257
6 changed files with 127 additions and 37 deletions
|
@ -219,7 +219,7 @@ namespace ams::creport {
|
||||||
|
|
||||||
void CrashReport::HandleDebugEventInfoCreateThread(const svc::DebugEventInfo &d) {
|
void CrashReport::HandleDebugEventInfoCreateThread(const svc::DebugEventInfo &d) {
|
||||||
/* Save info on the thread's TLS address for later. */
|
/* 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) {
|
void CrashReport::HandleDebugEventInfoException(const svc::DebugEventInfo &d) {
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace ams::creport {
|
||||||
Result result = ResultIncompleteReport();
|
Result result = ResultIncompleteReport();
|
||||||
|
|
||||||
/* Meta, used for building module/thread list. */
|
/* Meta, used for building module/thread list. */
|
||||||
std::map<u64, u64> thread_tls_map;
|
ThreadTlsMap thread_tls_map = {};
|
||||||
|
|
||||||
/* Attach process info. */
|
/* Attach process info. */
|
||||||
svc::DebugInfoCreateProcess process_info = {};
|
svc::DebugInfoCreateProcess process_info = {};
|
||||||
|
@ -49,9 +49,11 @@ namespace ams::creport {
|
||||||
ThreadList *thread_list = nullptr;
|
ThreadList *thread_list = nullptr;
|
||||||
|
|
||||||
/* Memory heap. */
|
/* Memory heap. */
|
||||||
lmem::HeapHandle heap_handle;
|
lmem::HeapHandle heap_handle = nullptr;
|
||||||
u8 heap_storage[MemoryHeapSize];
|
u8 heap_storage[MemoryHeapSize] = {};
|
||||||
public:
|
public:
|
||||||
|
constexpr CrashReport() = default;
|
||||||
|
|
||||||
Result GetResult() const {
|
Result GetResult() const {
|
||||||
return this->result;
|
return this->result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ extern "C" {
|
||||||
u32 __nx_applet_type = AppletType_None;
|
u32 __nx_applet_type = AppletType_None;
|
||||||
u32 __nx_fs_num_sessions = 1;
|
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;
|
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||||
|
|
||||||
|
@ -68,9 +68,32 @@ void __libnx_initheap(void) {
|
||||||
fake_heap_end = (char*)addr + size;
|
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) {
|
void __appInit(void) {
|
||||||
hos::InitializeForStratosphere();
|
hos::InitializeForStratosphere();
|
||||||
|
|
||||||
|
InitializeFsHeap();
|
||||||
|
fs::SetAllocator(AllocateForFs, DeallocateForFs);
|
||||||
|
|
||||||
sm::DoWithSession([&]() {
|
sm::DoWithSession([&]() {
|
||||||
R_ABORT_UNLESS(fsInitialize());
|
R_ABORT_UNLESS(fsInitialize());
|
||||||
});
|
});
|
||||||
|
@ -83,7 +106,31 @@ void __appExit(void) {
|
||||||
fsExit();
|
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) {
|
int main(int argc, char **argv) {
|
||||||
/* Set thread name. */
|
/* Set thread name. */
|
||||||
|
|
|
@ -113,7 +113,7 @@ namespace ams::creport {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ThreadInfo::ReadFromProcess(Handle debug_handle, std::map<u64, u64> &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. */
|
/* Set thread id. */
|
||||||
this->thread_id = thread_id;
|
this->thread_id = thread_id;
|
||||||
|
|
||||||
|
@ -145,8 +145,8 @@ namespace ams::creport {
|
||||||
|
|
||||||
/* Read TLS, if present. */
|
/* Read TLS, if present. */
|
||||||
/* TODO: struct definitions for nnSdk's ThreadType/TLS Layout? */
|
/* TODO: struct definitions for nnSdk's ThreadType/TLS Layout? */
|
||||||
if (tls_map.find(thread_id) != tls_map.end()) {
|
this->tls_address = 0;
|
||||||
this->tls_address = tls_map[thread_id];
|
if (tls_map.GetThreadTls(std::addressof(this->tls_address), thread_id)) {
|
||||||
u8 thread_tls[0x200];
|
u8 thread_tls[0x200];
|
||||||
if (R_SUCCEEDED(svcReadDebugProcessMemory(thread_tls, debug_handle, this->tls_address, sizeof(thread_tls)))) {
|
if (R_SUCCEEDED(svcReadDebugProcessMemory(thread_tls, debug_handle, this->tls_address, sizeof(thread_tls)))) {
|
||||||
std::memcpy(this->tls, thread_tls, sizeof(this->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<u64, u64> &tls_map, bool is_64_bit) {
|
void ThreadList::ReadFromProcess(Handle debug_handle, ThreadTlsMap &tls_map, bool is_64_bit) {
|
||||||
this->thread_count = 0;
|
this->thread_count = 0;
|
||||||
|
|
||||||
/* Get thread list. */
|
/* Get thread list. */
|
||||||
|
|
|
@ -22,6 +22,39 @@ namespace ams::creport {
|
||||||
/* Forward declare ModuleList class. */
|
/* Forward declare ModuleList class. */
|
||||||
class ModuleList;
|
class ModuleList;
|
||||||
|
|
||||||
|
static constexpr size_t ThreadCountMax = 0x60;
|
||||||
|
|
||||||
|
template<size_t MaxThreadCount>
|
||||||
|
class ThreadTlsMapImpl {
|
||||||
|
private:
|
||||||
|
std::pair<u64, u64> 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<ThreadCountMax>;
|
||||||
|
|
||||||
class ThreadInfo {
|
class ThreadInfo {
|
||||||
private:
|
private:
|
||||||
static constexpr size_t StackTraceSizeMax = 0x20;
|
static constexpr size_t StackTraceSizeMax = 0x20;
|
||||||
|
@ -76,7 +109,7 @@ namespace ams::creport {
|
||||||
this->module_list = ml;
|
this->module_list = ml;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReadFromProcess(Handle debug_handle, std::map<u64, u64> &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 SaveToFile(ScopedFile &file);
|
||||||
void DumpBinary(ScopedFile &file);
|
void DumpBinary(ScopedFile &file);
|
||||||
private:
|
private:
|
||||||
|
@ -84,8 +117,6 @@ namespace ams::creport {
|
||||||
};
|
};
|
||||||
|
|
||||||
class ThreadList {
|
class ThreadList {
|
||||||
private:
|
|
||||||
static constexpr size_t ThreadCountMax = 0x60;
|
|
||||||
private:
|
private:
|
||||||
size_t thread_count = 0;
|
size_t thread_count = 0;
|
||||||
ThreadInfo threads[ThreadCountMax];
|
ThreadInfo threads[ThreadCountMax];
|
||||||
|
@ -104,7 +135,7 @@ namespace ams::creport {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadFromProcess(Handle debug_handle, std::map<u64, u64> &tls_map, bool is_64_bit);
|
void ReadFromProcess(Handle debug_handle, ThreadTlsMap &tls_map, bool is_64_bit);
|
||||||
void SaveToFile(ScopedFile &file);
|
void SaveToFile(ScopedFile &file);
|
||||||
void DumpBinary(ScopedFile &file, u64 crashed_thread_id);
|
void DumpBinary(ScopedFile &file, u64 crashed_thread_id);
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,28 +30,38 @@ namespace ams::fatal::srv {
|
||||||
|
|
||||||
constexpr inline size_t MaxThreads = 0x60;
|
constexpr inline size_t MaxThreads = 0x60;
|
||||||
|
|
||||||
constinit std::pair<u64, u64> g_thread_id_to_tls_map[MaxThreads];
|
template<size_t MaxThreadCount>
|
||||||
constinit size_t g_tls_map_index = 0;
|
class ThreadTlsMapImpl {
|
||||||
|
private:
|
||||||
|
std::pair<u64, u64> m_map[MaxThreadCount];
|
||||||
|
size_t m_index;
|
||||||
|
public:
|
||||||
|
constexpr ThreadTlsMapImpl() : m_map(), m_index(0) { /* ... */ }
|
||||||
|
|
||||||
void ResetThreadTlsMap() {
|
constexpr void ResetThreadTlsMap() {
|
||||||
g_tls_map_index = 0;
|
m_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;
|
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<MaxThreads>;
|
||||||
|
|
||||||
|
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) {
|
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. */
|
/* 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)); };
|
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. */
|
/* 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;
|
bool got_create_process = false;
|
||||||
svc::DebugEventInfo d;
|
svc::DebugEventInfo d;
|
||||||
|
@ -214,7 +224,7 @@ namespace ams::fatal::srv {
|
||||||
got_create_process = true;
|
got_create_process = true;
|
||||||
break;
|
break;
|
||||||
case svc::DebugEvent_CreateThread:
|
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;
|
break;
|
||||||
case svc::DebugEvent_Exception:
|
case svc::DebugEvent_Exception:
|
||||||
case svc::DebugEvent_ExitProcess:
|
case svc::DebugEvent_ExitProcess:
|
||||||
|
@ -250,7 +260,7 @@ namespace ams::fatal::srv {
|
||||||
for (s32 i = 0; i < thread_count; i++) {
|
for (s32 i = 0; i < thread_count; i++) {
|
||||||
const u64 cur_thread_id = thread_ids[i];
|
const u64 cur_thread_id = thread_ids[i];
|
||||||
u64 cur_thread_tls;
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue