symbols.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "common/bit_field.h"
  4. #include "common/common_funcs.h"
  5. #include "common/elf.h"
  6. #include "core/arm/symbols.h"
  7. #include "core/core.h"
  8. #include "core/memory.h"
  9. using namespace Common::ELF;
  10. namespace Core {
  11. namespace Symbols {
  12. template <typename Word, typename ELFSymbol, typename ByteReader>
  13. static Symbols GetSymbols(ByteReader ReadBytes) {
  14. const auto Read8{[&](u64 index) {
  15. u8 ret;
  16. ReadBytes(&ret, index, sizeof(u8));
  17. return ret;
  18. }};
  19. const auto Read32{[&](u64 index) {
  20. u32 ret;
  21. ReadBytes(&ret, index, sizeof(u32));
  22. return ret;
  23. }};
  24. const auto ReadWord{[&](u64 index) {
  25. Word ret;
  26. ReadBytes(&ret, index, sizeof(Word));
  27. return ret;
  28. }};
  29. const u32 mod_offset = Read32(4);
  30. if (Read32(mod_offset) != Common::MakeMagic('M', 'O', 'D', '0')) {
  31. return {};
  32. }
  33. VAddr string_table_offset{};
  34. VAddr symbol_table_offset{};
  35. u64 symbol_entry_size{};
  36. const auto dynamic_offset = Read32(mod_offset + 0x4) + mod_offset;
  37. VAddr dynamic_index = dynamic_offset;
  38. while (true) {
  39. const Word tag = ReadWord(dynamic_index);
  40. const Word value = ReadWord(dynamic_index + sizeof(Word));
  41. dynamic_index += 2 * sizeof(Word);
  42. if (tag == ElfDtNull) {
  43. break;
  44. }
  45. if (tag == ElfDtStrtab) {
  46. string_table_offset = value;
  47. } else if (tag == ElfDtSymtab) {
  48. symbol_table_offset = value;
  49. } else if (tag == ElfDtSyment) {
  50. symbol_entry_size = value;
  51. }
  52. }
  53. if (string_table_offset == 0 || symbol_table_offset == 0 || symbol_entry_size == 0) {
  54. return {};
  55. }
  56. Symbols out;
  57. VAddr symbol_index = symbol_table_offset;
  58. while (symbol_index < string_table_offset) {
  59. ELFSymbol symbol{};
  60. ReadBytes(&symbol, symbol_index, sizeof(ELFSymbol));
  61. VAddr string_offset = string_table_offset + symbol.st_name;
  62. std::string name;
  63. for (u8 c = Read8(string_offset); c != 0; c = Read8(++string_offset)) {
  64. name += static_cast<char>(c);
  65. }
  66. symbol_index += symbol_entry_size;
  67. out[name] = std::make_pair(symbol.st_value, symbol.st_size);
  68. }
  69. return out;
  70. }
  71. Symbols GetSymbols(VAddr base, Core::Memory::Memory& memory, bool is_64) {
  72. const auto ReadBytes{
  73. [&](void* ptr, size_t offset, size_t size) { memory.ReadBlock(base + offset, ptr, size); }};
  74. if (is_64) {
  75. return GetSymbols<u64, Elf64_Sym>(ReadBytes);
  76. } else {
  77. return GetSymbols<u32, Elf32_Sym>(ReadBytes);
  78. }
  79. }
  80. Symbols GetSymbols(std::span<const u8> data, bool is_64) {
  81. const auto ReadBytes{[&](void* ptr, size_t offset, size_t size) {
  82. std::memcpy(ptr, data.data() + offset, size);
  83. }};
  84. if (is_64) {
  85. return GetSymbols<u64, Elf64_Sym>(ReadBytes);
  86. } else {
  87. return GetSymbols<u32, Elf32_Sym>(ReadBytes);
  88. }
  89. }
  90. std::optional<std::string> GetSymbolName(const Symbols& symbols, VAddr addr) {
  91. const auto iter = std::find_if(symbols.cbegin(), symbols.cend(), [addr](const auto& pair) {
  92. const auto& [name, sym_info] = pair;
  93. const auto& [start_address, size] = sym_info;
  94. const auto end_address = start_address + size;
  95. return addr >= start_address && addr < end_address;
  96. });
  97. if (iter == symbols.cend()) {
  98. return std::nullopt;
  99. }
  100. return iter->first;
  101. }
  102. } // namespace Symbols
  103. } // namespace Core