mirror of https://github.com/stella-emu/stella.git
Parse symbols.
This commit is contained in:
parent
192870dc2b
commit
ae36e141f0
|
@ -22,6 +22,8 @@
|
|||
|
||||
#include "CartELF.hxx"
|
||||
|
||||
#define DUMP_ELF
|
||||
|
||||
namespace {
|
||||
constexpr size_t TRANSACTION_QUEUE_CAPACITY = 16384;
|
||||
|
||||
|
@ -78,6 +80,22 @@ CartridgeELF::CartridgeELF(const ByteBuffer& image, size_t size, string_view md5
|
|||
std::fill_n(myLastPeekResult.get(), 0x1000, 0);
|
||||
|
||||
createRomAccessArrays(0x1000);
|
||||
|
||||
#ifdef DUMP_ELF
|
||||
cout << "ELF sections:" << std::endl << std::endl;
|
||||
|
||||
size_t i = 0;
|
||||
for (auto& section: elfParser.getSections())
|
||||
if (section.type != 0x00) cout << (i++) << " " << section << std::endl;
|
||||
|
||||
auto symbols = elfParser.getSymbols();
|
||||
cout << std::endl << "ELF symbols:" << std::endl << std::endl;
|
||||
if (symbols.size() > 0) {
|
||||
i = 0;
|
||||
for (auto& symbol: symbols)
|
||||
cout << (i++) << " " << symbol << std::endl;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -6,9 +6,11 @@ namespace {
|
|||
constexpr uInt32 ELF_MAGIC = 0x7f454c46;
|
||||
constexpr uInt8 ELF_CLASS_32 = 1;
|
||||
constexpr uInt8 ELF_VERSION = 1;
|
||||
constexpr uInt32 SYMBOL_ENTRY_SIZE = 16;
|
||||
} // namespace
|
||||
|
||||
void ElfParser::parse(const uInt8 *elfData, size_t size) {
|
||||
void ElfParser::parse(const uInt8 *elfData, size_t size)
|
||||
{
|
||||
data = elfData;
|
||||
this->size = size;
|
||||
|
||||
|
@ -36,7 +38,7 @@ void ElfParser::parse(const uInt8 *elfData, size_t size) {
|
|||
|
||||
sections.reserve(header.shNum);
|
||||
|
||||
for (uInt32 i = 0; i < header.shNum; i++)
|
||||
for (size_t i = 0; i < header.shNum; i++)
|
||||
sections.push_back(
|
||||
readSection(header.shOffset + i * header.shSize));
|
||||
|
||||
|
@ -44,10 +46,19 @@ void ElfParser::parse(const uInt8 *elfData, size_t size) {
|
|||
|
||||
if (shrstrtab.type != SHT_STRTAB) EInvalidElf::raise(".shstrtab has wrong type");
|
||||
|
||||
|
||||
for (Section §ion : sections)
|
||||
section.name = getName(shrstrtab, section.nameOffset);
|
||||
|
||||
const Section* symtab = getSymtab();
|
||||
if (symtab) {
|
||||
const Section* strtab = getStrtab();
|
||||
if (!strtab) EInvalidElf::raise("no string table to resolve symbol names");
|
||||
|
||||
symbols.reserve(symtab->size / SYMBOL_ENTRY_SIZE);
|
||||
|
||||
for (size_t i = 0; i < symtab->size / SYMBOL_ENTRY_SIZE; i++)
|
||||
symbols.push_back(readSymbol(i, *symtab, *strtab));
|
||||
}
|
||||
} catch (const EInvalidElf &e) {
|
||||
EInvalidElf::raise("failed to parse ELF: " + string(e.what()));
|
||||
}
|
||||
|
@ -57,10 +68,16 @@ const uInt8 *ElfParser::getData() const { return data; }
|
|||
|
||||
size_t ElfParser::getSize() const { return size; }
|
||||
|
||||
const vector<ElfParser::Section> &ElfParser::getSections() const {
|
||||
const vector<ElfParser::Section> &ElfParser::getSections() const
|
||||
{
|
||||
return sections;
|
||||
}
|
||||
|
||||
const vector<ElfParser::Symbol>& ElfParser::getSymbols() const
|
||||
{
|
||||
return symbols;
|
||||
}
|
||||
|
||||
const optional<ElfParser::Section>
|
||||
ElfParser::getSection(const string &name) const {
|
||||
for (const Section §ion : sections)
|
||||
|
@ -70,26 +87,29 @@ ElfParser::getSection(const string &name) const {
|
|||
return optional<Section>();
|
||||
}
|
||||
|
||||
uInt8 ElfParser::read8(uInt32 offset) {
|
||||
uInt8 ElfParser::read8(uInt32 offset) const
|
||||
{
|
||||
if (offset >= size)
|
||||
EInvalidElf::raise("reference beyond bounds");
|
||||
|
||||
return data[offset];
|
||||
}
|
||||
|
||||
uInt16 ElfParser::read16(uInt32 offset) {
|
||||
uInt16 ElfParser::read16(uInt32 offset) const
|
||||
{
|
||||
return bigEndian ? ((read8(offset) << 8) | read8(offset + 1))
|
||||
: ((read8(offset + 1) << 8) | read8(offset));
|
||||
}
|
||||
|
||||
uInt32 ElfParser::read32(uInt32 offset) {
|
||||
uInt32 ElfParser::read32(uInt32 offset) const
|
||||
{
|
||||
return bigEndian ? ((read8(offset) << 24) | (read8(offset + 1) << 16) |
|
||||
(read8(offset + 2) << 8) | read8(offset + 3))
|
||||
: ((read8(offset + 3) << 24) | (read8(offset + 2) << 16) |
|
||||
(read8(offset + 1) << 8) | read8(offset));
|
||||
}
|
||||
|
||||
ElfParser::Section ElfParser::readSection(uInt32 offset) {
|
||||
ElfParser::Section ElfParser::readSection(uInt32 offset) const {
|
||||
Section section;
|
||||
|
||||
try {
|
||||
|
@ -110,7 +130,29 @@ ElfParser::Section ElfParser::readSection(uInt32 offset) {
|
|||
return section;
|
||||
}
|
||||
|
||||
const char* ElfParser::getName(const Section& section, uInt32 offset)
|
||||
ElfParser::Symbol ElfParser::readSymbol(uInt32 index, const Section& symSec, const Section& strSec) const
|
||||
{
|
||||
Symbol sym;
|
||||
|
||||
uInt32 offset = index * SYMBOL_ENTRY_SIZE;
|
||||
if (offset + SYMBOL_ENTRY_SIZE > symSec.size) EInvalidElf::raise("symbol is beyond section");
|
||||
offset += symSec.offset;
|
||||
|
||||
sym.nameOffset = read32(offset);
|
||||
sym.value = read32(offset + 0x04);
|
||||
sym.size = read32(offset + 0x08);
|
||||
sym.info = read8(offset + 0x0c);
|
||||
sym.visibility = read8(offset + 0x0d);
|
||||
sym.section = read16(offset + 0x0e);
|
||||
|
||||
sym.name = getName(strSec, sym.nameOffset);
|
||||
sym.bind = sym.info >> 4;
|
||||
sym.type = sym.info & 0x0f;
|
||||
|
||||
return sym;
|
||||
}
|
||||
|
||||
const char* ElfParser::getName(const Section& section, uInt32 offset) const
|
||||
{
|
||||
if (offset >= section.size) EInvalidElf::raise("name out of bounds");
|
||||
const uInt32 imageOffset = offset + section.offset;
|
||||
|
@ -122,3 +164,62 @@ const char* ElfParser::getName(const Section& section, uInt32 offset)
|
|||
|
||||
return name;
|
||||
}
|
||||
|
||||
const ElfParser::Section* ElfParser::getSymtab() const
|
||||
{
|
||||
for (auto& section: sections)
|
||||
if (section.type == SHT_SYMTAB) return §ion;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ElfParser::Section* ElfParser::getStrtab() const
|
||||
{
|
||||
for (size_t i = 0; i < sections.size(); i++)
|
||||
if (sections[i].type == SHT_STRTAB && i != header.shstrIndex) return §ions[i];
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ostream& operator<<(ostream& os, const ElfParser::Section& section)
|
||||
{
|
||||
std::ios reset(nullptr);
|
||||
reset.copyfmt(os);
|
||||
|
||||
os
|
||||
<< std::hex << std::setw(4) << std::setfill('0')
|
||||
<< section.name
|
||||
<< " type=0x" << section.type
|
||||
<< " flags=0x" << section.flags
|
||||
<< " vaddr=0x" << section.virtualAddress
|
||||
<< " offset=0x" << section.offset;
|
||||
|
||||
os.copyfmt(reset);
|
||||
|
||||
os
|
||||
<< " size=" << section.size
|
||||
<< " align=" << section.align;
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
ostream& operator<<(ostream& os, const ElfParser::Symbol symbol)
|
||||
{
|
||||
std::ios reset(nullptr);
|
||||
reset.copyfmt(os);
|
||||
|
||||
os
|
||||
<< symbol.name
|
||||
<< std::hex << std::setw(4) << std::setfill('0')
|
||||
<< " value=0x" << symbol.value
|
||||
<< " size=0x" << symbol.size
|
||||
<< std::setw(1)
|
||||
<< " bind=0x" << (int)symbol.bind
|
||||
<< " type=0x" << (int)symbol.type;
|
||||
|
||||
os.copyfmt(reset);
|
||||
|
||||
os << " section=" << symbol.section;
|
||||
|
||||
return os;
|
||||
}
|
||||
|
|
|
@ -64,6 +64,19 @@ class ElfParser {
|
|||
uInt32 align;
|
||||
};
|
||||
|
||||
struct Symbol {
|
||||
uInt32 nameOffset;
|
||||
uInt32 value;
|
||||
uInt32 size;
|
||||
uInt8 info;
|
||||
uInt8 visibility;
|
||||
uInt16 section;
|
||||
|
||||
string name;
|
||||
uInt8 bind;
|
||||
uInt8 type;
|
||||
};
|
||||
|
||||
public:
|
||||
static constexpr uInt8 ENDIAN_LITTLE_ENDIAN = 0x01;
|
||||
static constexpr uInt8 ENDIAN_BIG_ENDIAN = 0x02;
|
||||
|
@ -72,6 +85,7 @@ class ElfParser {
|
|||
|
||||
static constexpr uInt16 ARCH_ARM32 = 0x28;
|
||||
|
||||
static constexpr uInt32 SHT_NULL = 0x00;
|
||||
static constexpr uInt32 SHT_PROGBITS = 0x01;
|
||||
static constexpr uInt32 SHT_SYMTAB = 0x02;
|
||||
static constexpr uInt32 SHT_STRTAB = 0x03;
|
||||
|
@ -81,6 +95,9 @@ class ElfParser {
|
|||
static constexpr uInt32 SHT_INIT_ARRAY = 0x0e;
|
||||
static constexpr uInt32 SHT_PREINIT_ARRAY = 0x10;
|
||||
|
||||
static constexpr uInt32 SHN_ABS = 0xfff1;
|
||||
static constexpr uInt32 SHN_UND = 0x00;
|
||||
|
||||
public:
|
||||
ElfParser() = default;
|
||||
|
||||
|
@ -91,15 +108,20 @@ class ElfParser {
|
|||
|
||||
const Header& getHeader() const;
|
||||
const vector<Section>& getSections() const;
|
||||
const vector<Symbol>& getSymbols() const;
|
||||
const optional<Section> getSection(const std::string &name) const;
|
||||
|
||||
private:
|
||||
uInt8 read8(uInt32 offset);
|
||||
uInt16 read16(uInt32 offset);
|
||||
uInt32 read32(uInt32 offset);
|
||||
uInt8 read8(uInt32 offset) const;
|
||||
uInt16 read16(uInt32 offset) const;
|
||||
uInt32 read32(uInt32 offset) const;
|
||||
|
||||
Section readSection(uInt32 offset);
|
||||
const char* getName(const Section& section, uInt32 offset);
|
||||
Section readSection(uInt32 offset) const;
|
||||
Symbol readSymbol(uInt32 index, const Section& symSec, const Section& strSec) const;
|
||||
const char* getName(const Section& section, uInt32 offset) const;
|
||||
|
||||
const Section* getSymtab() const;
|
||||
const Section* getStrtab() const;
|
||||
|
||||
private:
|
||||
const uInt8 *data{nullptr};
|
||||
|
@ -109,6 +131,11 @@ class ElfParser {
|
|||
|
||||
Header header;
|
||||
vector<Section> sections;
|
||||
vector<Symbol> symbols;
|
||||
};
|
||||
|
||||
ostream& operator<<(ostream& os, const ElfParser::Section& section);
|
||||
|
||||
ostream& operator<<(ostream& os, const ElfParser::Symbol symbol);
|
||||
|
||||
#endif // ELF_PARSER
|
||||
|
|
Loading…
Reference in New Issue