Skip to content

Commit

Permalink
Parse symbols.
Browse files Browse the repository at this point in the history
  • Loading branch information
DirtyHairy committed Jul 4, 2024
1 parent 192870d commit ae36e14
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 14 deletions.
18 changes: 18 additions & 0 deletions src/emucore/CartELF.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

#include "CartELF.hxx"

#define DUMP_ELF

namespace {
constexpr size_t TRANSACTION_QUEUE_CAPACITY = 16384;

Expand Down Expand Up @@ -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
}


Expand Down
119 changes: 110 additions & 9 deletions src/emucore/elf/ElfParser.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -36,18 +38,27 @@ 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));

const Section &shrstrtab(sections[header.shstrIndex]);

if (shrstrtab.type != SHT_STRTAB) EInvalidElf::raise(".shstrtab has wrong type");


for (Section &section : 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()));
}
Expand All @@ -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 &section : sections)
Expand All @@ -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 {
Expand All @@ -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;
Expand All @@ -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 &section;

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 &sections[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;
}
37 changes: 32 additions & 5 deletions src/emucore/elf/ElfParser.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;

Expand All @@ -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;
Symbol readSymbol(uInt32 index, const Section& symSec, const Section& strSec) const;
const char* getName(const Section& section, uInt32 offset) const;

Section readSection(uInt32 offset);
const char* getName(const Section& section, uInt32 offset);
const Section* getSymtab() const;
const Section* getStrtab() const;

private:
const uInt8 *data{nullptr};
Expand All @@ -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

0 comments on commit ae36e14

Please sign in to comment.