aboutsummaryrefslogtreecommitdiff
path: root/src/core/arm/arm_interface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/arm/arm_interface.cpp')
-rw-r--r--src/core/arm/arm_interface.cpp71
1 files changed, 68 insertions, 3 deletions
diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp
index 7e846ddd5..0951e1976 100644
--- a/src/core/arm/arm_interface.cpp
+++ b/src/core/arm/arm_interface.cpp
@@ -60,7 +60,7 @@ static_assert(sizeof(ELFSymbol) == 0x18, "ELFSymbol has incorrect size.");
using Symbols = std::vector<std::pair<ELFSymbol, std::string>>;
-Symbols GetSymbols(VAddr text_offset, Memory::Memory& memory) {
+Symbols GetSymbols(VAddr text_offset, Core::Memory::Memory& memory) {
const auto mod_offset = text_offset + memory.Read32(text_offset + 4);
if (mod_offset < text_offset || (mod_offset & 0b11) != 0 ||
@@ -123,7 +123,7 @@ Symbols GetSymbols(VAddr text_offset, Memory::Memory& memory) {
std::optional<std::string> GetSymbolName(const Symbols& symbols, VAddr func_address) {
const auto iter =
std::find_if(symbols.begin(), symbols.end(), [func_address](const auto& pair) {
- const auto& [symbol, name] = pair;
+ const auto& symbol = pair.first;
const auto end_address = symbol.value + symbol.size;
return func_address >= symbol.value && func_address < end_address;
});
@@ -139,6 +139,71 @@ std::optional<std::string> GetSymbolName(const Symbols& symbols, VAddr func_addr
constexpr u64 SEGMENT_BASE = 0x7100000000ull;
+std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktraceFromContext(
+ System& system, const ThreadContext64& ctx) {
+ std::vector<BacktraceEntry> out;
+ auto& memory = system.Memory();
+
+ auto fp = ctx.cpu_registers[29];
+ auto lr = ctx.cpu_registers[30];
+ while (true) {
+ out.push_back({
+ .module = "",
+ .address = 0,
+ .original_address = lr,
+ .offset = 0,
+ .name = {},
+ });
+
+ if (fp == 0) {
+ break;
+ }
+
+ lr = memory.Read64(fp + 8) - 4;
+ fp = memory.Read64(fp);
+ }
+
+ std::map<VAddr, std::string> modules;
+ auto& loader{system.GetAppLoader()};
+ if (loader.ReadNSOModules(modules) != Loader::ResultStatus::Success) {
+ return {};
+ }
+
+ std::map<std::string, Symbols> symbols;
+ for (const auto& module : modules) {
+ symbols.insert_or_assign(module.second, GetSymbols(module.first, memory));
+ }
+
+ for (auto& entry : out) {
+ VAddr base = 0;
+ for (auto iter = modules.rbegin(); iter != modules.rend(); ++iter) {
+ const auto& module{*iter};
+ if (entry.original_address >= module.first) {
+ entry.module = module.second;
+ base = module.first;
+ break;
+ }
+ }
+
+ entry.offset = entry.original_address - base;
+ entry.address = SEGMENT_BASE + entry.offset;
+
+ if (entry.module.empty())
+ entry.module = "unknown";
+
+ const auto symbol_set = symbols.find(entry.module);
+ if (symbol_set != symbols.end()) {
+ const auto symbol = GetSymbolName(symbol_set->second, entry.offset);
+ if (symbol.has_value()) {
+ // TODO(DarkLordZach): Add demangling of symbol names.
+ entry.name = *symbol;
+ }
+ }
+ }
+
+ return out;
+}
+
std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktrace() const {
std::vector<BacktraceEntry> out;
auto& memory = system.Memory();
@@ -146,7 +211,7 @@ std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktrace() const {
auto fp = GetReg(29);
auto lr = GetReg(30);
while (true) {
- out.push_back({"", 0, lr, 0});
+ out.push_back({"", 0, lr, 0, ""});
if (!fp) {
break;
}