arm_interface.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <map>
  5. #include <optional>
  6. #include "common/bit_field.h"
  7. #include "common/common_types.h"
  8. #include "common/logging/log.h"
  9. #include "core/arm/arm_interface.h"
  10. #include "core/core.h"
  11. #include "core/loader/loader.h"
  12. #include "core/memory.h"
  13. namespace Core {
  14. namespace {
  15. constexpr u64 ELF_DYNAMIC_TAG_NULL = 0;
  16. constexpr u64 ELF_DYNAMIC_TAG_STRTAB = 5;
  17. constexpr u64 ELF_DYNAMIC_TAG_SYMTAB = 6;
  18. constexpr u64 ELF_DYNAMIC_TAG_SYMENT = 11;
  19. enum class ELFSymbolType : u8 {
  20. None = 0,
  21. Object = 1,
  22. Function = 2,
  23. Section = 3,
  24. File = 4,
  25. Common = 5,
  26. TLS = 6,
  27. };
  28. enum class ELFSymbolBinding : u8 {
  29. Local = 0,
  30. Global = 1,
  31. Weak = 2,
  32. };
  33. enum class ELFSymbolVisibility : u8 {
  34. Default = 0,
  35. Internal = 1,
  36. Hidden = 2,
  37. Protected = 3,
  38. };
  39. struct ELFSymbol {
  40. u32 name_index;
  41. union {
  42. u8 info;
  43. BitField<0, 4, ELFSymbolType> type;
  44. BitField<4, 4, ELFSymbolBinding> binding;
  45. };
  46. ELFSymbolVisibility visibility;
  47. u16 sh_index;
  48. u64 value;
  49. u64 size;
  50. };
  51. static_assert(sizeof(ELFSymbol) == 0x18, "ELFSymbol has incorrect size.");
  52. using Symbols = std::vector<std::pair<ELFSymbol, std::string>>;
  53. Symbols GetSymbols(VAddr text_offset, Core::Memory::Memory& memory) {
  54. const auto mod_offset = text_offset + memory.Read32(text_offset + 4);
  55. if (mod_offset < text_offset || (mod_offset & 0b11) != 0 ||
  56. memory.Read32(mod_offset) != Common::MakeMagic('M', 'O', 'D', '0')) {
  57. return {};
  58. }
  59. const auto dynamic_offset = memory.Read32(mod_offset + 0x4) + mod_offset;
  60. VAddr string_table_offset{};
  61. VAddr symbol_table_offset{};
  62. u64 symbol_entry_size{};
  63. VAddr dynamic_index = dynamic_offset;
  64. while (true) {
  65. const u64 tag = memory.Read64(dynamic_index);
  66. const u64 value = memory.Read64(dynamic_index + 0x8);
  67. dynamic_index += 0x10;
  68. if (tag == ELF_DYNAMIC_TAG_NULL) {
  69. break;
  70. }
  71. if (tag == ELF_DYNAMIC_TAG_STRTAB) {
  72. string_table_offset = value;
  73. } else if (tag == ELF_DYNAMIC_TAG_SYMTAB) {
  74. symbol_table_offset = value;
  75. } else if (tag == ELF_DYNAMIC_TAG_SYMENT) {
  76. symbol_entry_size = value;
  77. }
  78. }
  79. if (string_table_offset == 0 || symbol_table_offset == 0 || symbol_entry_size == 0) {
  80. return {};
  81. }
  82. const auto string_table_address = text_offset + string_table_offset;
  83. const auto symbol_table_address = text_offset + symbol_table_offset;
  84. Symbols out;
  85. VAddr symbol_index = symbol_table_address;
  86. while (symbol_index < string_table_address) {
  87. ELFSymbol symbol{};
  88. memory.ReadBlock(symbol_index, &symbol, sizeof(ELFSymbol));
  89. VAddr string_offset = string_table_address + symbol.name_index;
  90. std::string name;
  91. for (u8 c = memory.Read8(string_offset); c != 0; c = memory.Read8(++string_offset)) {
  92. name += static_cast<char>(c);
  93. }
  94. symbol_index += symbol_entry_size;
  95. out.push_back({symbol, name});
  96. }
  97. return out;
  98. }
  99. std::optional<std::string> GetSymbolName(const Symbols& symbols, VAddr func_address) {
  100. const auto iter =
  101. std::find_if(symbols.begin(), symbols.end(), [func_address](const auto& pair) {
  102. const auto& symbol = pair.first;
  103. const auto end_address = symbol.value + symbol.size;
  104. return func_address >= symbol.value && func_address < end_address;
  105. });
  106. if (iter == symbols.end()) {
  107. return std::nullopt;
  108. }
  109. return iter->second;
  110. }
  111. } // Anonymous namespace
  112. constexpr u64 SEGMENT_BASE = 0x7100000000ull;
  113. std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktraceFromContext(
  114. System& system, const ThreadContext64& ctx) {
  115. std::vector<BacktraceEntry> out;
  116. auto& memory = system.Memory();
  117. auto fp = ctx.cpu_registers[29];
  118. auto lr = ctx.cpu_registers[30];
  119. while (true) {
  120. out.push_back({"", 0, lr, 0});
  121. if (!fp) {
  122. break;
  123. }
  124. lr = memory.Read64(fp + 8) - 4;
  125. fp = memory.Read64(fp);
  126. }
  127. std::map<VAddr, std::string> modules;
  128. auto& loader{system.GetAppLoader()};
  129. if (loader.ReadNSOModules(modules) != Loader::ResultStatus::Success) {
  130. return {};
  131. }
  132. std::map<std::string, Symbols> symbols;
  133. for (const auto& module : modules) {
  134. symbols.insert_or_assign(module.second, GetSymbols(module.first, memory));
  135. }
  136. for (auto& entry : out) {
  137. VAddr base = 0;
  138. for (auto iter = modules.rbegin(); iter != modules.rend(); ++iter) {
  139. const auto& module{*iter};
  140. if (entry.original_address >= module.first) {
  141. entry.module = module.second;
  142. base = module.first;
  143. break;
  144. }
  145. }
  146. entry.offset = entry.original_address - base;
  147. entry.address = SEGMENT_BASE + entry.offset;
  148. if (entry.module.empty())
  149. entry.module = "unknown";
  150. const auto symbol_set = symbols.find(entry.module);
  151. if (symbol_set != symbols.end()) {
  152. const auto symbol = GetSymbolName(symbol_set->second, entry.offset);
  153. if (symbol.has_value()) {
  154. // TODO(DarkLordZach): Add demangling of symbol names.
  155. entry.name = *symbol;
  156. }
  157. }
  158. }
  159. return out;
  160. }
  161. std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktrace() const {
  162. std::vector<BacktraceEntry> out;
  163. auto& memory = system.Memory();
  164. auto fp = GetReg(29);
  165. auto lr = GetReg(30);
  166. while (true) {
  167. out.push_back({"", 0, lr, 0, ""});
  168. if (!fp) {
  169. break;
  170. }
  171. lr = memory.Read64(fp + 8) - 4;
  172. fp = memory.Read64(fp);
  173. }
  174. std::map<VAddr, std::string> modules;
  175. auto& loader{system.GetAppLoader()};
  176. if (loader.ReadNSOModules(modules) != Loader::ResultStatus::Success) {
  177. return {};
  178. }
  179. std::map<std::string, Symbols> symbols;
  180. for (const auto& module : modules) {
  181. symbols.insert_or_assign(module.second, GetSymbols(module.first, memory));
  182. }
  183. for (auto& entry : out) {
  184. VAddr base = 0;
  185. for (auto iter = modules.rbegin(); iter != modules.rend(); ++iter) {
  186. const auto& module{*iter};
  187. if (entry.original_address >= module.first) {
  188. entry.module = module.second;
  189. base = module.first;
  190. break;
  191. }
  192. }
  193. entry.offset = entry.original_address - base;
  194. entry.address = SEGMENT_BASE + entry.offset;
  195. if (entry.module.empty())
  196. entry.module = "unknown";
  197. const auto symbol_set = symbols.find(entry.module);
  198. if (symbol_set != symbols.end()) {
  199. const auto symbol = GetSymbolName(symbol_set->second, entry.offset);
  200. if (symbol.has_value()) {
  201. // TODO(DarkLordZach): Add demangling of symbol names.
  202. entry.name = *symbol;
  203. }
  204. }
  205. }
  206. return out;
  207. }
  208. void ARM_Interface::LogBacktrace() const {
  209. const VAddr sp = GetReg(13);
  210. const VAddr pc = GetPC();
  211. LOG_ERROR(Core_ARM, "Backtrace, sp={:016X}, pc={:016X}", sp, pc);
  212. LOG_ERROR(Core_ARM, "{:20}{:20}{:20}{:20}{}", "Module Name", "Address", "Original Address",
  213. "Offset", "Symbol");
  214. LOG_ERROR(Core_ARM, "");
  215. const auto backtrace = GetBacktrace();
  216. for (const auto& entry : backtrace) {
  217. LOG_ERROR(Core_ARM, "{:20}{:016X} {:016X} {:016X} {}", entry.module, entry.address,
  218. entry.original_address, entry.offset, entry.name);
  219. }
  220. }
  221. } // namespace Core