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"
|
#include "CartELF.hxx"
|
||||||
|
|
||||||
|
#define DUMP_ELF
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr size_t TRANSACTION_QUEUE_CAPACITY = 16384;
|
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);
|
std::fill_n(myLastPeekResult.get(), 0x1000, 0);
|
||||||
|
|
||||||
createRomAccessArrays(0x1000);
|
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 uInt32 ELF_MAGIC = 0x7f454c46;
|
||||||
constexpr uInt8 ELF_CLASS_32 = 1;
|
constexpr uInt8 ELF_CLASS_32 = 1;
|
||||||
constexpr uInt8 ELF_VERSION = 1;
|
constexpr uInt8 ELF_VERSION = 1;
|
||||||
|
constexpr uInt32 SYMBOL_ENTRY_SIZE = 16;
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void ElfParser::parse(const uInt8 *elfData, size_t size) {
|
void ElfParser::parse(const uInt8 *elfData, size_t size)
|
||||||
|
{
|
||||||
data = elfData;
|
data = elfData;
|
||||||
this->size = size;
|
this->size = size;
|
||||||
|
|
||||||
|
@ -36,7 +38,7 @@ void ElfParser::parse(const uInt8 *elfData, size_t size) {
|
||||||
|
|
||||||
sections.reserve(header.shNum);
|
sections.reserve(header.shNum);
|
||||||
|
|
||||||
for (uInt32 i = 0; i < header.shNum; i++)
|
for (size_t i = 0; i < header.shNum; i++)
|
||||||
sections.push_back(
|
sections.push_back(
|
||||||
readSection(header.shOffset + i * header.shSize));
|
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");
|
if (shrstrtab.type != SHT_STRTAB) EInvalidElf::raise(".shstrtab has wrong type");
|
||||||
|
|
||||||
|
|
||||||
for (Section §ion : sections)
|
for (Section §ion : sections)
|
||||||
section.name = getName(shrstrtab, section.nameOffset);
|
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) {
|
} catch (const EInvalidElf &e) {
|
||||||
EInvalidElf::raise("failed to parse ELF: " + string(e.what()));
|
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; }
|
size_t ElfParser::getSize() const { return size; }
|
||||||
|
|
||||||
const vector<ElfParser::Section> &ElfParser::getSections() const {
|
const vector<ElfParser::Section> &ElfParser::getSections() const
|
||||||
|
{
|
||||||
return sections;
|
return sections;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const vector<ElfParser::Symbol>& ElfParser::getSymbols() const
|
||||||
|
{
|
||||||
|
return symbols;
|
||||||
|
}
|
||||||
|
|
||||||
const optional<ElfParser::Section>
|
const optional<ElfParser::Section>
|
||||||
ElfParser::getSection(const string &name) const {
|
ElfParser::getSection(const string &name) const {
|
||||||
for (const Section §ion : sections)
|
for (const Section §ion : sections)
|
||||||
|
@ -70,26 +87,29 @@ ElfParser::getSection(const string &name) const {
|
||||||
return optional<Section>();
|
return optional<Section>();
|
||||||
}
|
}
|
||||||
|
|
||||||
uInt8 ElfParser::read8(uInt32 offset) {
|
uInt8 ElfParser::read8(uInt32 offset) const
|
||||||
|
{
|
||||||
if (offset >= size)
|
if (offset >= size)
|
||||||
EInvalidElf::raise("reference beyond bounds");
|
EInvalidElf::raise("reference beyond bounds");
|
||||||
|
|
||||||
return data[offset];
|
return data[offset];
|
||||||
}
|
}
|
||||||
|
|
||||||
uInt16 ElfParser::read16(uInt32 offset) {
|
uInt16 ElfParser::read16(uInt32 offset) const
|
||||||
|
{
|
||||||
return bigEndian ? ((read8(offset) << 8) | read8(offset + 1))
|
return bigEndian ? ((read8(offset) << 8) | read8(offset + 1))
|
||||||
: ((read8(offset + 1) << 8) | read8(offset));
|
: ((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) |
|
return bigEndian ? ((read8(offset) << 24) | (read8(offset + 1) << 16) |
|
||||||
(read8(offset + 2) << 8) | read8(offset + 3))
|
(read8(offset + 2) << 8) | read8(offset + 3))
|
||||||
: ((read8(offset + 3) << 24) | (read8(offset + 2) << 16) |
|
: ((read8(offset + 3) << 24) | (read8(offset + 2) << 16) |
|
||||||
(read8(offset + 1) << 8) | read8(offset));
|
(read8(offset + 1) << 8) | read8(offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
ElfParser::Section ElfParser::readSection(uInt32 offset) {
|
ElfParser::Section ElfParser::readSection(uInt32 offset) const {
|
||||||
Section section;
|
Section section;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -110,7 +130,29 @@ ElfParser::Section ElfParser::readSection(uInt32 offset) {
|
||||||
return section;
|
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");
|
if (offset >= section.size) EInvalidElf::raise("name out of bounds");
|
||||||
const uInt32 imageOffset = offset + section.offset;
|
const uInt32 imageOffset = offset + section.offset;
|
||||||
|
@ -122,3 +164,62 @@ const char* ElfParser::getName(const Section& section, uInt32 offset)
|
||||||
|
|
||||||
return name;
|
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;
|
uInt32 align;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Symbol {
|
||||||
|
uInt32 nameOffset;
|
||||||
|
uInt32 value;
|
||||||
|
uInt32 size;
|
||||||
|
uInt8 info;
|
||||||
|
uInt8 visibility;
|
||||||
|
uInt16 section;
|
||||||
|
|
||||||
|
string name;
|
||||||
|
uInt8 bind;
|
||||||
|
uInt8 type;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static constexpr uInt8 ENDIAN_LITTLE_ENDIAN = 0x01;
|
static constexpr uInt8 ENDIAN_LITTLE_ENDIAN = 0x01;
|
||||||
static constexpr uInt8 ENDIAN_BIG_ENDIAN = 0x02;
|
static constexpr uInt8 ENDIAN_BIG_ENDIAN = 0x02;
|
||||||
|
@ -72,6 +85,7 @@ class ElfParser {
|
||||||
|
|
||||||
static constexpr uInt16 ARCH_ARM32 = 0x28;
|
static constexpr uInt16 ARCH_ARM32 = 0x28;
|
||||||
|
|
||||||
|
static constexpr uInt32 SHT_NULL = 0x00;
|
||||||
static constexpr uInt32 SHT_PROGBITS = 0x01;
|
static constexpr uInt32 SHT_PROGBITS = 0x01;
|
||||||
static constexpr uInt32 SHT_SYMTAB = 0x02;
|
static constexpr uInt32 SHT_SYMTAB = 0x02;
|
||||||
static constexpr uInt32 SHT_STRTAB = 0x03;
|
static constexpr uInt32 SHT_STRTAB = 0x03;
|
||||||
|
@ -81,6 +95,9 @@ class ElfParser {
|
||||||
static constexpr uInt32 SHT_INIT_ARRAY = 0x0e;
|
static constexpr uInt32 SHT_INIT_ARRAY = 0x0e;
|
||||||
static constexpr uInt32 SHT_PREINIT_ARRAY = 0x10;
|
static constexpr uInt32 SHT_PREINIT_ARRAY = 0x10;
|
||||||
|
|
||||||
|
static constexpr uInt32 SHN_ABS = 0xfff1;
|
||||||
|
static constexpr uInt32 SHN_UND = 0x00;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ElfParser() = default;
|
ElfParser() = default;
|
||||||
|
|
||||||
|
@ -91,15 +108,20 @@ class ElfParser {
|
||||||
|
|
||||||
const Header& getHeader() const;
|
const Header& getHeader() const;
|
||||||
const vector<Section>& getSections() const;
|
const vector<Section>& getSections() const;
|
||||||
|
const vector<Symbol>& getSymbols() const;
|
||||||
const optional<Section> getSection(const std::string &name) const;
|
const optional<Section> getSection(const std::string &name) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uInt8 read8(uInt32 offset);
|
uInt8 read8(uInt32 offset) const;
|
||||||
uInt16 read16(uInt32 offset);
|
uInt16 read16(uInt32 offset) const;
|
||||||
uInt32 read32(uInt32 offset);
|
uInt32 read32(uInt32 offset) const;
|
||||||
|
|
||||||
Section readSection(uInt32 offset);
|
Section readSection(uInt32 offset) const;
|
||||||
const char* getName(const Section& section, uInt32 offset);
|
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:
|
private:
|
||||||
const uInt8 *data{nullptr};
|
const uInt8 *data{nullptr};
|
||||||
|
@ -109,6 +131,11 @@ class ElfParser {
|
||||||
|
|
||||||
Header header;
|
Header header;
|
||||||
vector<Section> sections;
|
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
|
#endif // ELF_PARSER
|
||||||
|
|
Loading…
Reference in New Issue