forked from eden-emu/eden
		
	core/arm: better support for backtrace generation
This commit is contained in:
		
							parent
							
								
									95b844dbae
								
							
						
					
					
						commit
						8f8c0b69dc
					
				
					 5 changed files with 51 additions and 15 deletions
				
			
		|  | @ -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 | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -409,18 +409,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
 | ||||
|  |  | |||
|  | @ -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 = | ||||
|  |  | |||
|  | @ -480,22 +480,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); | ||||
|     } | ||||
| 
 | ||||
|  | @ -506,11 +506,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
 | ||||
|  |  | |||
|  | @ -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 = | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Liam
						Liam