From a33ace8996031810ae8893a9134d8294ef166943 Mon Sep 17 00:00:00 2001 From: Thomas Guillemard Date: Sat, 25 May 2019 12:29:18 +0200 Subject: [PATCH 1/2] 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; From bbcb3757bd4e22af2a6da7b4b0879531af443320 Mon Sep 17 00:00:00 2001 From: Thomas Guillemard Date: Tue, 28 May 2019 00:26:56 +0200 Subject: [PATCH 2/2] Address comment --- .../creport/source/creport_debug_types.hpp | 17 +++++++++-------- .../creport/source/creport_thread_info.cpp | 16 ++++++++-------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/stratosphere/creport/source/creport_debug_types.hpp b/stratosphere/creport/source/creport_debug_types.hpp index a549eb9d7..8c5661581 100644 --- a/stratosphere/creport/source/creport_debug_types.hpp +++ b/stratosphere/creport/source/creport_debug_types.hpp @@ -17,14 +17,15 @@ #pragma once #include -struct StackFrame64 { - u64 fp; - u64 lr; -}; - -struct StackFrame32 { - u32 fp; - u32 lr; +union StackFrame { + struct { + u64 fp; + u64 lr; + } frame_64; + struct { + u32 fp; + u32 lr; + } frame_32; }; struct AttachProcessInfo { diff --git a/stratosphere/creport/source/creport_thread_info.cpp b/stratosphere/creport/source/creport_thread_info.cpp index 8fc11fbc4..3c05fe124 100644 --- a/stratosphere/creport/source/creport_thread_info.cpp +++ b/stratosphere/creport/source/creport_thread_info.cpp @@ -115,14 +115,14 @@ bool ThreadInfo::ReadFromProcess(std::map &tls_map, Handle debug_handl } /* Read a new frame. */ - StackFrame64 cur_frame; - if (R_FAILED(svcReadDebugProcessMemory(&cur_frame, debug_handle, cur_fp, sizeof(StackFrame64)))) { + StackFrame cur_frame; + if (R_FAILED(svcReadDebugProcessMemory(&cur_frame, debug_handle, cur_fp, sizeof(cur_frame.frame_64)))) { break; } /* Advance to the next frame. */ - this->stack_trace[this->stack_trace_size++] = cur_frame.lr; - cur_fp = cur_frame.fp; + this->stack_trace[this->stack_trace_size++] = cur_frame.frame_64.lr; + cur_fp = cur_frame.frame_64.fp; } } else { for (unsigned int i = 0; i < sizeof(this->stack_trace)/sizeof(u64); i++) { @@ -132,14 +132,14 @@ bool ThreadInfo::ReadFromProcess(std::map &tls_map, Handle debug_handl } /* Read a new frame. */ - StackFrame32 cur_frame; - if (R_FAILED(svcReadDebugProcessMemory(&cur_frame, debug_handle, cur_fp, sizeof(StackFrame32)))) { + StackFrame cur_frame; + if (R_FAILED(svcReadDebugProcessMemory(&cur_frame, debug_handle, cur_fp, sizeof(cur_frame.frame_32)))) { break; } /* Advance to the next frame. */ - this->stack_trace[this->stack_trace_size++] = cur_frame.lr; - cur_fp = cur_frame.fp; + this->stack_trace[this->stack_trace_size++] = cur_frame.frame_32.lr; + cur_fp = cur_frame.frame_32.fp; } }