arm_interface.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  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({
  121. .module = "",
  122. .address = 0,
  123. .original_address = lr,
  124. .offset = 0,
  125. .name = "",
  126. });
  127. if (fp == 0) {
  128. break;
  129. }
  130. lr = memory.Read64(fp + 8) - 4;
  131. fp = memory.Read64(fp);
  132. }
  133. std::map<VAddr, std::string> modules;
  134. auto& loader{system.GetAppLoader()};
  135. if (loader.ReadNSOModules(modules) != Loader::ResultStatus::Success) {
  136. return {};
  137. }
  138. std::map<std::string, Symbols> symbols;
  139. for (const auto& module : modules) {
  140. symbols.insert_or_assign(module.second, GetSymbols(module.first, memory));
  141. }
  142. for (auto& entry : out) {
  143. VAddr base = 0;
  144. for (auto iter = modules.rbegin(); iter != modules.rend(); ++iter) {
  145. const auto& module{*iter};
  146. if (entry.original_address >= module.first) {
  147. entry.module = module.second;
  148. base = module.first;
  149. break;
  150. }
  151. }
  152. entry.offset = entry.original_address - base;
  153. entry.address = SEGMENT_BASE + entry.offset;
  154. if (entry.module.empty())
  155. entry.module = "unknown";
  156. const auto symbol_set = symbols.find(entry.module);
  157. if (symbol_set != symbols.end()) {
  158. const auto symbol = GetSymbolName(symbol_set->second, entry.offset);
  159. if (symbol.has_value()) {
  160. // TODO(DarkLordZach): Add demangling of symbol names.
  161. entry.name = *symbol;
  162. }
  163. }
  164. }
  165. return out;
  166. }
  167. std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktrace() const {
  168. std::vector<BacktraceEntry> out;
  169. auto& memory = system.Memory();
  170. auto fp = GetReg(29);
  171. auto lr = GetReg(30);
  172. while (true) {
  173. out.push_back({
  174. .module = "",
  175. .address = 0,
  176. .original_address = lr,
  177. .offset = 0,
  178. .name = "",
  179. });
  180. if (fp == 0) {
  181. break;
  182. }
  183. lr = memory.Read64(fp + 8) - 4;
  184. fp = memory.Read64(fp);
  185. }
  186. std::map<VAddr, std::string> modules;
  187. auto& loader{system.GetAppLoader()};
  188. if (loader.ReadNSOModules(modules) != Loader::ResultStatus::Success) {
  189. return {};
  190. }
  191. std::map<std::string, Symbols> symbols;
  192. for (const auto& module : modules) {
  193. symbols.insert_or_assign(module.second, GetSymbols(module.first, memory));
  194. }
  195. for (auto& entry : out) {
  196. VAddr base = 0;
  197. for (auto iter = modules.rbegin(); iter != modules.rend(); ++iter) {
  198. const auto& module{*iter};
  199. if (entry.original_address >= module.first) {
  200. entry.module = module.second;
  201. base = module.first;
  202. break;
  203. }
  204. }
  205. entry.offset = entry.original_address - base;
  206. entry.address = SEGMENT_BASE + entry.offset;
  207. if (entry.module.empty())
  208. entry.module = "unknown";
  209. const auto symbol_set = symbols.find(entry.module);
  210. if (symbol_set != symbols.end()) {
  211. const auto symbol = GetSymbolName(symbol_set->second, entry.offset);
  212. if (symbol.has_value()) {
  213. // TODO(DarkLordZach): Add demangling of symbol names.
  214. entry.name = *symbol;
  215. }
  216. }
  217. }
  218. return out;
  219. }
  220. void ARM_Interface::LogBacktrace() const {
  221. const VAddr sp = GetReg(13);
  222. const VAddr pc = GetPC();
  223. LOG_ERROR(Core_ARM, "Backtrace, sp={:016X}, pc={:016X}", sp, pc);
  224. LOG_ERROR(Core_ARM, "{:20}{:20}{:20}{:20}{}", "Module Name", "Address", "Original Address",
  225. "Offset", "Symbol");
  226. LOG_ERROR(Core_ARM, "");
  227. const auto backtrace = GetBacktrace();
  228. for (const auto& entry : backtrace) {
  229. LOG_ERROR(Core_ARM, "{:20}{:016X} {:016X} {:016X} {}", entry.module, entry.address,
  230. entry.original_address, entry.offset, entry.name);
  231. }
  232. }
  233. } // namespace Core