From a33ace8996031810ae8893a9134d8294ef166943 Mon Sep 17 00:00:00 2001 From: Thomas Guillemard Date: Sat, 25 May 2019 12:29:18 +0200 Subject: [PATCH] creport: Add 32 bits stack frames parsing support Also fix FP, SP and LR registers being set wrongly by svcGetDebugThreadParam for 32 bits processes. --- .../creport/source/creport_debug_types.hpp | 7 ++- .../creport/source/creport_thread_info.cpp | 52 +++++++++++++------ 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/stratosphere/creport/source/creport_debug_types.hpp b/stratosphere/creport/source/creport_debug_types.hpp index e39520fc4..a549eb9d7 100644 --- a/stratosphere/creport/source/creport_debug_types.hpp +++ b/stratosphere/creport/source/creport_debug_types.hpp @@ -17,11 +17,16 @@ #pragma once #include -struct StackFrame { +struct StackFrame64 { u64 fp; u64 lr; }; +struct StackFrame32 { + u32 fp; + u32 lr; +}; + struct AttachProcessInfo { u64 title_id; u64 process_id; diff --git a/stratosphere/creport/source/creport_thread_info.cpp b/stratosphere/creport/source/creport_thread_info.cpp index 7f9e3f69a..8fc11fbc4 100644 --- a/stratosphere/creport/source/creport_thread_info.cpp +++ b/stratosphere/creport/source/creport_thread_info.cpp @@ -75,9 +75,11 @@ bool ThreadInfo::ReadFromProcess(std::map &tls_map, Handle debug_handl return false; } - /* Don't try to parse stack frames if 32-bit. */ + /* In AArch32 mode the LR, FP, and SP registers aren't set correctly in the ThreadContext by svcGetDebugThreadParam... */ if (!is_64_bit) { - return true; + this->context.fp = this->context.cpu_gprs[11].x; + this->context.sp = this->context.cpu_gprs[13].x; + this->context.lr = this->context.cpu_gprs[14].x; } /* Parse information from TLS if present. */ @@ -104,21 +106,41 @@ bool ThreadInfo::ReadFromProcess(std::map &tls_map, Handle debug_handl TryGetStackInfo(debug_handle); u64 cur_fp = this->context.fp; - for (unsigned int i = 0; i < sizeof(this->stack_trace)/sizeof(u64); i++) { - /* Validate the current frame. */ - if (cur_fp == 0 || (cur_fp & 0xF)) { - break; - } - /* Read a new frame. */ - StackFrame cur_frame; - if (R_FAILED(svcReadDebugProcessMemory(&cur_frame, debug_handle, cur_fp, sizeof(StackFrame)))) { - break; - } + if (is_64_bit) { + for (unsigned int i = 0; i < sizeof(this->stack_trace)/sizeof(u64); i++) { + /* Validate the current frame. */ + if (cur_fp == 0 || (cur_fp & 0xF)) { + break; + } - /* Advance to the next frame. */ - this->stack_trace[this->stack_trace_size++] = cur_frame.lr; - cur_fp = cur_frame.fp; + /* Read a new frame. */ + StackFrame64 cur_frame; + if (R_FAILED(svcReadDebugProcessMemory(&cur_frame, debug_handle, cur_fp, sizeof(StackFrame64)))) { + break; + } + + /* Advance to the next frame. */ + this->stack_trace[this->stack_trace_size++] = cur_frame.lr; + cur_fp = cur_frame.fp; + } + } else { + for (unsigned int i = 0; i < sizeof(this->stack_trace)/sizeof(u64); i++) { + /* Validate the current frame. */ + if (cur_fp == 0 || (cur_fp & 0x7)) { + break; + } + + /* Read a new frame. */ + StackFrame32 cur_frame; + if (R_FAILED(svcReadDebugProcessMemory(&cur_frame, debug_handle, cur_fp, sizeof(StackFrame32)))) { + break; + } + + /* Advance to the next frame. */ + this->stack_trace[this->stack_trace_size++] = cur_frame.lr; + cur_fp = cur_frame.fp; + } } return true;