committed by
GitHub
4 changed files with 231 additions and 129 deletions
-
2src/core/CMakeLists.txt
-
141src/core/arm/arm_interface.cpp
-
190src/core/arm/symbols.cpp
-
27src/core/arm/symbols.h
@ -0,0 +1,190 @@ |
|||
// Copyright 2022 yuzu Emulator Project
|
|||
// Licensed under GPLv2 or any later version
|
|||
// Refer to the license.txt file included.
|
|||
|
|||
#include "common/bit_field.h"
|
|||
#include "common/common_funcs.h"
|
|||
#include "core/arm/symbols.h"
|
|||
#include "core/core.h"
|
|||
#include "core/memory.h"
|
|||
|
|||
namespace Core { |
|||
namespace { |
|||
|
|||
constexpr u64 ELF_DYNAMIC_TAG_NULL = 0; |
|||
constexpr u64 ELF_DYNAMIC_TAG_STRTAB = 5; |
|||
constexpr u64 ELF_DYNAMIC_TAG_SYMTAB = 6; |
|||
constexpr u64 ELF_DYNAMIC_TAG_SYMENT = 11; |
|||
|
|||
enum class ELFSymbolType : u8 { |
|||
None = 0, |
|||
Object = 1, |
|||
Function = 2, |
|||
Section = 3, |
|||
File = 4, |
|||
Common = 5, |
|||
TLS = 6, |
|||
}; |
|||
|
|||
enum class ELFSymbolBinding : u8 { |
|||
Local = 0, |
|||
Global = 1, |
|||
Weak = 2, |
|||
}; |
|||
|
|||
enum class ELFSymbolVisibility : u8 { |
|||
Default = 0, |
|||
Internal = 1, |
|||
Hidden = 2, |
|||
Protected = 3, |
|||
}; |
|||
|
|||
struct ELF64Symbol { |
|||
u32 name_index; |
|||
union { |
|||
u8 info; |
|||
|
|||
BitField<0, 4, ELFSymbolType> type; |
|||
BitField<4, 4, ELFSymbolBinding> binding; |
|||
}; |
|||
ELFSymbolVisibility visibility; |
|||
u16 sh_index; |
|||
u64 value; |
|||
u64 size; |
|||
}; |
|||
static_assert(sizeof(ELF64Symbol) == 0x18, "ELF64Symbol has incorrect size."); |
|||
|
|||
struct ELF32Symbol { |
|||
u32 name_index; |
|||
u32 value; |
|||
u32 size; |
|||
union { |
|||
u8 info; |
|||
|
|||
BitField<0, 4, ELFSymbolType> type; |
|||
BitField<4, 4, ELFSymbolBinding> binding; |
|||
}; |
|||
ELFSymbolVisibility visibility; |
|||
u16 sh_index; |
|||
}; |
|||
static_assert(sizeof(ELF32Symbol) == 0x10, "ELF32Symbol has incorrect size."); |
|||
|
|||
} // Anonymous namespace
|
|||
|
|||
namespace Symbols { |
|||
|
|||
template <typename Word, typename ELFSymbol, typename ByteReader> |
|||
static Symbols GetSymbols(ByteReader ReadBytes) { |
|||
const auto Read8{[&](u64 index) { |
|||
u8 ret; |
|||
ReadBytes(&ret, index, sizeof(u8)); |
|||
return ret; |
|||
}}; |
|||
|
|||
const auto Read32{[&](u64 index) { |
|||
u32 ret; |
|||
ReadBytes(&ret, index, sizeof(u32)); |
|||
return ret; |
|||
}}; |
|||
|
|||
const auto ReadWord{[&](u64 index) { |
|||
Word ret; |
|||
ReadBytes(&ret, index, sizeof(Word)); |
|||
return ret; |
|||
}}; |
|||
|
|||
const u32 mod_offset = Read32(4); |
|||
|
|||
if (Read32(mod_offset) != Common::MakeMagic('M', 'O', 'D', '0')) { |
|||
return {}; |
|||
} |
|||
|
|||
VAddr string_table_offset{}; |
|||
VAddr symbol_table_offset{}; |
|||
u64 symbol_entry_size{}; |
|||
|
|||
const auto dynamic_offset = Read32(mod_offset + 0x4) + mod_offset; |
|||
|
|||
VAddr dynamic_index = dynamic_offset; |
|||
while (true) { |
|||
const Word tag = ReadWord(dynamic_index); |
|||
const Word value = ReadWord(dynamic_index + sizeof(Word)); |
|||
dynamic_index += 2 * sizeof(Word); |
|||
|
|||
if (tag == ELF_DYNAMIC_TAG_NULL) { |
|||
break; |
|||
} |
|||
|
|||
if (tag == ELF_DYNAMIC_TAG_STRTAB) { |
|||
string_table_offset = value; |
|||
} else if (tag == ELF_DYNAMIC_TAG_SYMTAB) { |
|||
symbol_table_offset = value; |
|||
} else if (tag == ELF_DYNAMIC_TAG_SYMENT) { |
|||
symbol_entry_size = value; |
|||
} |
|||
} |
|||
|
|||
if (string_table_offset == 0 || symbol_table_offset == 0 || symbol_entry_size == 0) { |
|||
return {}; |
|||
} |
|||
|
|||
Symbols out; |
|||
|
|||
VAddr symbol_index = symbol_table_offset; |
|||
while (symbol_index < string_table_offset) { |
|||
ELFSymbol symbol{}; |
|||
ReadBytes(&symbol, symbol_index, sizeof(ELFSymbol)); |
|||
|
|||
VAddr string_offset = string_table_offset + symbol.name_index; |
|||
std::string name; |
|||
for (u8 c = Read8(string_offset); c != 0; c = Read8(++string_offset)) { |
|||
name += static_cast<char>(c); |
|||
} |
|||
|
|||
symbol_index += symbol_entry_size; |
|||
out[name] = std::make_pair(symbol.value, symbol.size); |
|||
} |
|||
|
|||
return out; |
|||
} |
|||
|
|||
Symbols GetSymbols(VAddr base, Core::Memory::Memory& memory, bool is_64) { |
|||
const auto ReadBytes{ |
|||
[&](void* ptr, size_t offset, size_t size) { memory.ReadBlock(base + offset, ptr, size); }}; |
|||
|
|||
if (is_64) { |
|||
return GetSymbols<u64, ELF64Symbol>(ReadBytes); |
|||
} else { |
|||
return GetSymbols<u32, ELF32Symbol>(ReadBytes); |
|||
} |
|||
} |
|||
|
|||
Symbols GetSymbols(std::span<const u8> data, bool is_64) { |
|||
const auto ReadBytes{[&](void* ptr, size_t offset, size_t size) { |
|||
std::memcpy(ptr, data.data() + offset, size); |
|||
}}; |
|||
|
|||
if (is_64) { |
|||
return GetSymbols<u64, ELF64Symbol>(ReadBytes); |
|||
} else { |
|||
return GetSymbols<u32, ELF32Symbol>(ReadBytes); |
|||
} |
|||
} |
|||
|
|||
std::optional<std::string> GetSymbolName(const Symbols& symbols, VAddr addr) { |
|||
const auto iter = std::find_if(symbols.cbegin(), symbols.cend(), [addr](const auto& pair) { |
|||
const auto& [name, sym_info] = pair; |
|||
const auto& [start_address, size] = sym_info; |
|||
const auto end_address = start_address + size; |
|||
return addr >= start_address && addr < end_address; |
|||
}); |
|||
|
|||
if (iter == symbols.cend()) { |
|||
return std::nullopt; |
|||
} |
|||
|
|||
return iter->first; |
|||
} |
|||
|
|||
} // namespace Symbols
|
|||
} // namespace Core
|
|||
@ -0,0 +1,27 @@ |
|||
// Copyright 2022 yuzu Emulator Project |
|||
// Licensed under GPLv2 or any later version |
|||
// Refer to the license.txt file included. |
|||
|
|||
#pragma once |
|||
|
|||
#include <map> |
|||
#include <optional> |
|||
#include <span> |
|||
#include <string> |
|||
#include <utility> |
|||
|
|||
#include "common/common_types.h" |
|||
|
|||
namespace Core::Memory { |
|||
class Memory; |
|||
} // namespace Core::Memory |
|||
|
|||
namespace Core::Symbols { |
|||
|
|||
using Symbols = std::map<std::string, std::pair<VAddr, std::size_t>, std::less<>>; |
|||
|
|||
Symbols GetSymbols(VAddr base, Core::Memory::Memory& memory, bool is_64 = true); |
|||
Symbols GetSymbols(std::span<const u8> data, bool is_64 = true); |
|||
std::optional<std::string> GetSymbolName(const Symbols& symbols, VAddr addr); |
|||
|
|||
} // namespace Core::Symbols |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue