From 71493327121038696c887158cb34f94e2f225e0f Mon Sep 17 00:00:00 2001
From: David Marcec <dmarcecguzman@gmail.com>
Date: Mon, 3 Dec 2018 19:12:09 +1100
Subject: [PATCH] Print backtrace on svcBreak

When we get an svcBreak we get a backtrace now
---
 src/core/hle/kernel/svc.cpp    |  2 ++
 src/core/hle/kernel/thread.cpp | 17 +++++++++++++++++
 src/core/hle/kernel/thread.h   |  5 +++++
 3 files changed, 24 insertions(+)

diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 3339777c15..2273f0bcff 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -625,6 +625,8 @@ static void Break(u32 reason, u64 info1, u64 info2) {
             "Emulated program broke execution! reason=0x{:016X}, info1=0x{:016X}, info2=0x{:016X}",
             reason, info1, info2);
         handle_debug_buffer(info1, info2);
+        GetCurrentThread()->LogBacktrace();
+
         ASSERT(false);
 
         Core::CurrentProcess()->PrepareForTermination();
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 4ffb768183..a044db6e71 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -388,6 +388,23 @@ bool Thread::InvokeWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thread> t
     return wakeup_callback(reason, std::move(thread), std::move(object), index);
 }
 
+void Thread::LogBacktrace() {
+    auto& system = Core::System::GetInstance();
+    VAddr fp = system.ArmInterface(processor_id).GetReg(29);
+    VAddr lr = system.ArmInterface(processor_id).GetReg(30);
+    VAddr sp = system.ArmInterface(processor_id).GetReg(13);
+    VAddr pc = system.ArmInterface(processor_id).GetPC();
+    LOG_ERROR(Debug, "Backtrace, sp={:016X}, pc={:016X}", sp, pc);
+    for (std::size_t i = 0; i < 256; i++) {
+        LOG_ERROR(Debug, "{:016X}", lr - 4);
+        if (!fp) {
+            break;
+        }
+        lr = Memory::Read64(fp + 8);
+        fp = Memory::Read64(fp);
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 
 /**
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index d384d50dbc..469f8a56db 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -240,6 +240,11 @@ public:
         return status == ThreadStatus::WaitSynchAll;
     }
 
+    /**
+     * Logs the backtrace for the current thread
+     */
+    void LogBacktrace();
+
     ThreadContext& GetContext() {
         return context;
     }