diff options
Diffstat (limited to 'src/core/arm')
-rw-r--r-- | src/core/arm/arm_interface.cpp | 19 | ||||
-rw-r--r-- | src/core/arm/arm_interface.h | 7 | ||||
-rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_32.cpp | 40 | ||||
-rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_32.h | 2 | ||||
-rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_64.cpp | 27 | ||||
-rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_64.h | 2 | ||||
-rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_cp15.cpp | 5 | ||||
-rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_cp15.h | 5 |
8 files changed, 68 insertions, 39 deletions
diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp index 0efc3732f..953d96439 100644 --- a/src/core/arm/arm_interface.cpp +++ b/src/core/arm/arm_interface.cpp @@ -1,6 +1,10 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#ifndef _MSC_VER +#include <cxxabi.h> +#endif + #include <map> #include <optional> #include "common/bit_field.h" @@ -68,8 +72,19 @@ void ARM_Interface::SymbolicateBacktrace(Core::System& system, std::vector<Backt if (symbol_set != symbols.end()) { const auto symbol = Symbols::GetSymbolName(symbol_set->second, entry.offset); if (symbol.has_value()) { +#ifdef _MSC_VER // TODO(DarkLordZach): Add demangling of symbol names. entry.name = *symbol; +#else + int status{-1}; + char* demangled{abi::__cxa_demangle(symbol->c_str(), nullptr, nullptr, &status)}; + if (status == 0 && demangled != nullptr) { + entry.name = demangled; + std::free(demangled); + } else { + entry.name = *symbol; + } +#endif } } } @@ -132,7 +147,6 @@ void ARM_Interface::Run() { // Notify the debugger and go to sleep if a watchpoint was hit. if (Has(hr, watchpoint)) { - RewindBreakpointInstruction(); if (system.DebuggerEnabled()) { system.GetDebugger().NotifyThreadWatchpoint(current_thread, *HaltedWatchpoint()); } @@ -140,9 +154,10 @@ void ARM_Interface::Run() { break; } - // Handle syscalls and scheduling (this may change the current thread) + // Handle syscalls and scheduling (this may change the current thread/core) if (Has(hr, svc_call)) { Kernel::Svc::Call(system, GetSvcNumber()); + break; } if (Has(hr, break_loop) || !uses_wall_clock) { break; diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index 8a066ed91..73f259525 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h @@ -1,6 +1,5 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once @@ -203,7 +202,7 @@ public: static constexpr Dynarmic::HaltReason break_loop = Dynarmic::HaltReason::UserDefined2; static constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3; static constexpr Dynarmic::HaltReason breakpoint = Dynarmic::HaltReason::UserDefined4; - static constexpr Dynarmic::HaltReason watchpoint = Dynarmic::HaltReason::UserDefined5; + static constexpr Dynarmic::HaltReason watchpoint = Dynarmic::HaltReason::MemoryAbort; static constexpr Dynarmic::HaltReason no_execute = Dynarmic::HaltReason::UserDefined6; protected: diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 10cf72a45..b8d2ce224 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -52,7 +52,7 @@ public: if (!memory.IsValidVirtualAddressRange(vaddr, sizeof(u32))) { return std::nullopt; } - return MemoryRead32(vaddr); + return memory.Read32(vaddr); } void MemoryWrite8(u32 vaddr, u8 value) override { @@ -97,7 +97,7 @@ public: parent.LogBacktrace(); LOG_ERROR(Core_ARM, "Unimplemented instruction @ 0x{:X} for {} instructions (instr = {:08X})", pc, - num_instructions, MemoryRead32(pc)); + num_instructions, memory.Read32(pc)); } void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override { @@ -115,7 +115,7 @@ public: parent.LogBacktrace(); LOG_CRITICAL(Core_ARM, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X}, thumb = {})", - exception, pc, MemoryRead32(pc), parent.IsInThumbMode()); + exception, pc, memory.Read32(pc), parent.IsInThumbMode()); } } @@ -155,7 +155,7 @@ public: const auto match{parent.MatchingWatchpoint(addr, size, type)}; if (match) { parent.halted_watchpoint = match; - ReturnException(parent.jit.load()->Regs()[15], ARM_Interface::watchpoint); + parent.jit.load()->HaltExecution(ARM_Interface::watchpoint); return false; } @@ -204,7 +204,6 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* // Code cache size config.code_cache_size = 512_MiB; - config.far_code_offset = 400_MiB; // Allow memory fault handling to work if (system.DebuggerEnabled()) { @@ -215,7 +214,6 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* if (!page_table) { // Don't waste too much memory on null_jit config.code_cache_size = 8_MiB; - config.far_code_offset = 4_MiB; } // Safe optimizations @@ -427,18 +425,38 @@ void ARM_Dynarmic_32::PageTableChanged(Common::PageTable& page_table, } std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktrace(Core::System& system, - u64 sp, u64 lr) { - // No way to get accurate stack traces in A32 yet - return {}; + u64 fp, u64 lr, u64 pc) { + std::vector<BacktraceEntry> out; + auto& memory = system.Memory(); + + out.push_back({"", 0, pc, 0, ""}); + + // fp (= r11) points to the last frame record. + // Frame records are two words long: + // fp+0 : pointer to previous frame record + // fp+4 : value of lr for frame + while (true) { + out.push_back({"", 0, lr, 0, ""}); + if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 8)) { + break; + } + lr = memory.Read32(fp + 4); + fp = memory.Read32(fp); + } + + SymbolicateBacktrace(system, out); + + return out; } std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktraceFromContext( System& system, const ThreadContext32& ctx) { - return GetBacktrace(system, ctx.cpu_registers[13], ctx.cpu_registers[14]); + const auto& reg = ctx.cpu_registers; + return GetBacktrace(system, reg[11], reg[14], reg[15]); } std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktrace() const { - return GetBacktrace(system, GetReg(13), GetReg(14)); + return GetBacktrace(system, GetReg(11), GetReg(14), GetReg(15)); } } // namespace Core diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h index fcbe24f0c..346e9abf8 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.h +++ b/src/core/arm/dynarmic/arm_dynarmic_32.h @@ -78,7 +78,7 @@ protected: private: std::shared_ptr<Dynarmic::A32::Jit> MakeJit(Common::PageTable* page_table) const; - static std::vector<BacktraceEntry> GetBacktrace(Core::System& system, u64 sp, u64 lr); + static std::vector<BacktraceEntry> GetBacktrace(Core::System& system, u64 fp, u64 lr, u64 pc); using JitCacheKey = std::pair<Common::PageTable*, std::size_t>; using JitCacheType = diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 92266aa9e..1a4d37cbc 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -56,7 +56,7 @@ public: if (!memory.IsValidVirtualAddressRange(vaddr, sizeof(u32))) { return std::nullopt; } - return MemoryRead32(vaddr); + return memory.Read32(vaddr); } void MemoryWrite8(u64 vaddr, u8 value) override { @@ -111,7 +111,7 @@ public: parent.LogBacktrace(); LOG_ERROR(Core_ARM, "Unimplemented instruction @ 0x{:X} for {} instructions (instr = {:08X})", pc, - num_instructions, MemoryRead32(pc)); + num_instructions, memory.Read32(pc)); } void InstructionCacheOperationRaised(Dynarmic::A64::InstructionCacheOperation op, @@ -156,7 +156,7 @@ public: parent.LogBacktrace(); LOG_CRITICAL(Core_ARM, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})", - static_cast<std::size_t>(exception), pc, MemoryRead32(pc)); + static_cast<std::size_t>(exception), pc, memory.Read32(pc)); } } @@ -198,7 +198,7 @@ public: const auto match{parent.MatchingWatchpoint(addr, size, type)}; if (match) { parent.halted_watchpoint = match; - ReturnException(parent.jit.load()->GetPC(), ARM_Interface::watchpoint); + parent.jit.load()->HaltExecution(ARM_Interface::watchpoint); return false; } @@ -264,7 +264,6 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* // Code cache size config.code_cache_size = 512_MiB; - config.far_code_offset = 400_MiB; // Allow memory fault handling to work if (system.DebuggerEnabled()) { @@ -275,7 +274,6 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* if (!page_table) { // Don't waste too much memory on null_jit config.code_cache_size = 8_MiB; - config.far_code_offset = 4_MiB; } // Safe optimizations @@ -494,22 +492,22 @@ void ARM_Dynarmic_64::PageTableChanged(Common::PageTable& page_table, } std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace(Core::System& system, - u64 fp, u64 lr) { + u64 fp, u64 lr, u64 pc) { std::vector<BacktraceEntry> out; auto& memory = system.Memory(); - // fp (= r29) points to the last frame record. - // Note that this is the frame record for the *previous* frame, not the current one. - // Note we need to subtract 4 from our last read to get the proper address + out.push_back({"", 0, pc, 0, ""}); + + // fp (= x29) points to the previous frame record. // Frame records are two words long: // fp+0 : pointer to previous frame record // fp+8 : value of lr for frame while (true) { out.push_back({"", 0, lr, 0, ""}); - if (!fp) { + if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 16)) { break; } - lr = memory.Read64(fp + 8) - 4; + lr = memory.Read64(fp + 8); fp = memory.Read64(fp); } @@ -520,11 +518,12 @@ std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace(Core::S std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktraceFromContext( System& system, const ThreadContext64& ctx) { - return GetBacktrace(system, ctx.cpu_registers[29], ctx.cpu_registers[30]); + const auto& reg = ctx.cpu_registers; + return GetBacktrace(system, reg[29], reg[30], ctx.pc); } std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace() const { - return GetBacktrace(system, GetReg(29), GetReg(30)); + return GetBacktrace(system, GetReg(29), GetReg(30), GetPC()); } } // namespace Core diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h index 71dbaac5e..c77a83ad7 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.h +++ b/src/core/arm/dynarmic/arm_dynarmic_64.h @@ -73,7 +73,7 @@ private: std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable* page_table, std::size_t address_space_bits) const; - static std::vector<BacktraceEntry> GetBacktrace(Core::System& system, u64 fp, u64 lr); + static std::vector<BacktraceEntry> GetBacktrace(Core::System& system, u64 fp, u64 lr, u64 pc); using JitCacheKey = std::pair<Common::PageTable*, std::size_t>; using JitCacheType = diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp b/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp index 6aae79c48..e9123c13d 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp @@ -1,6 +1,5 @@ -// Copyright 2017 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2017 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #include <fmt/format.h> #include "common/logging/log.h" diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.h b/src/core/arm/dynarmic/arm_dynarmic_cp15.h index f271b2070..5b2a51636 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_cp15.h +++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.h @@ -1,6 +1,5 @@ -// Copyright 2017 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2017 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once |