mirror of https://github.com/stella-emu/stella.git
Refactor to prepare for unit tests.
This commit is contained in:
parent
0978806ae4
commit
4d722c4622
|
@ -33,17 +33,17 @@ namespace {
|
||||||
constexpr size_t TRANSACTION_QUEUE_CAPACITY = 16384;
|
constexpr size_t TRANSACTION_QUEUE_CAPACITY = 16384;
|
||||||
|
|
||||||
#ifdef DUMP_ELF
|
#ifdef DUMP_ELF
|
||||||
void dumpElf(const ElfParser& parser)
|
void dumpElf(const ElfFile& elf)
|
||||||
{
|
{
|
||||||
cout << std::endl << "ELF sections:" << std::endl << std::endl;
|
cout << std::endl << "ELF sections:" << std::endl << std::endl;
|
||||||
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (auto& section: parser.getSections()) {
|
for (auto& section: elf.getSections()) {
|
||||||
if (section.type != 0x00) cout << i << " " << section << std::endl;
|
if (section.type != 0x00) cout << i << " " << section << std::endl;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto symbols = parser.getSymbols();
|
auto symbols = elf.getSymbols();
|
||||||
cout << std::endl << "ELF symbols:" << std::endl << std::endl;
|
cout << std::endl << "ELF symbols:" << std::endl << std::endl;
|
||||||
if (symbols.size() > 0) {
|
if (symbols.size() > 0) {
|
||||||
i = 0;
|
i = 0;
|
||||||
|
@ -52,8 +52,8 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
for (auto& section: parser.getSections()) {
|
for (auto& section: elf.getSections()) {
|
||||||
auto rels = parser.getRelocations(i++);
|
auto rels = elf.getRelocations(i++);
|
||||||
if (!rels) continue;
|
if (!rels) continue;
|
||||||
|
|
||||||
cout
|
cout
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// SSSS tt lll lll
|
||||||
|
// SS SS tt ll ll
|
||||||
|
// SS tttttt eeee ll ll aaaa
|
||||||
|
// SSSS tt ee ee ll ll aa
|
||||||
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||||
|
// SS SS tt ee ll ll aa aa
|
||||||
|
// SSSS ttt eeeee llll llll aaaaa
|
||||||
|
//
|
||||||
|
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||||
|
// and the Stella Team
|
||||||
|
//
|
||||||
|
// See the file "License.txt" for information on usage and redistribution of
|
||||||
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
#ifndef ELF_FILE
|
||||||
|
#define ELF_FILE
|
||||||
|
|
||||||
|
#include "bspf.hxx"
|
||||||
|
|
||||||
|
class ElfFile {
|
||||||
|
public:
|
||||||
|
struct Section {
|
||||||
|
uInt32 nameOffset;
|
||||||
|
string name;
|
||||||
|
|
||||||
|
uInt32 type;
|
||||||
|
uInt32 flags;
|
||||||
|
|
||||||
|
uInt32 virtualAddress;
|
||||||
|
uInt32 offset;
|
||||||
|
uInt32 size;
|
||||||
|
|
||||||
|
uInt32 info;
|
||||||
|
uInt32 align;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Symbol {
|
||||||
|
uInt32 nameOffset;
|
||||||
|
uInt32 value;
|
||||||
|
uInt32 size;
|
||||||
|
uInt8 info;
|
||||||
|
uInt8 visibility;
|
||||||
|
uInt16 section;
|
||||||
|
|
||||||
|
string name;
|
||||||
|
uInt8 bind;
|
||||||
|
uInt8 type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Relocation {
|
||||||
|
uInt32 offset;
|
||||||
|
uInt32 info;
|
||||||
|
optional<uInt32> addend;
|
||||||
|
|
||||||
|
uInt32 symbol;
|
||||||
|
uInt8 type;
|
||||||
|
string symbolName;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~ElfFile() = default;
|
||||||
|
|
||||||
|
virtual const uInt8 *getData() const = 0;
|
||||||
|
virtual size_t getSize() const = 0;
|
||||||
|
|
||||||
|
virtual const vector<Section>& getSections() const = 0;
|
||||||
|
virtual const vector<Symbol>& getSymbols() const = 0;
|
||||||
|
virtual const optional<vector<Relocation>> getRelocations(size_t section) const = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr uInt8 ENDIAN_LITTLE_ENDIAN = 0x01;
|
||||||
|
static constexpr uInt8 ENDIAN_BIG_ENDIAN = 0x02;
|
||||||
|
|
||||||
|
static constexpr uInt16 ET_REL = 0x01;
|
||||||
|
|
||||||
|
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;
|
||||||
|
static constexpr uInt32 SHT_RELA = 0x04;
|
||||||
|
static constexpr uInt32 SHT_NOBITS = 0x08;
|
||||||
|
static constexpr uInt32 SHT_REL = 0x09;
|
||||||
|
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;
|
||||||
|
|
||||||
|
static constexpr uInt32 STT_SECTION = 0x03;
|
||||||
|
|
||||||
|
static constexpr uInt32 R_ARM_ABS32 = 0x02;
|
||||||
|
static constexpr uInt32 R_ARM_THM_CALL = 0x0a;
|
||||||
|
static constexpr uInt32 R_ARM_THM_JUMP24 = 0x1e;
|
||||||
|
static constexpr uInt32 R_ARM_TARGET1 = 0x26;
|
||||||
|
|
||||||
|
static constexpr uInt32 STT_FUNC = 0x02;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ELF_FILE
|
|
@ -24,17 +24,17 @@
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
std::optional<ElfLinker::SegmentType> determineSegmentType(const ElfParser::Section& section)
|
std::optional<ElfLinker::SegmentType> determineSegmentType(const ElfFile::Section& section)
|
||||||
{
|
{
|
||||||
switch (section.type) {
|
switch (section.type) {
|
||||||
case ElfParser::SHT_PROGBITS:
|
case ElfFile::SHT_PROGBITS:
|
||||||
if (section.name.starts_with(".text")) return ElfLinker::SegmentType::text;
|
if (section.name.starts_with(".text")) return ElfLinker::SegmentType::text;
|
||||||
|
|
||||||
if (section.name.starts_with(".rodata")) return ElfLinker::SegmentType::rodata;
|
if (section.name.starts_with(".rodata")) return ElfLinker::SegmentType::rodata;
|
||||||
|
|
||||||
return ElfLinker::SegmentType::data;
|
return ElfLinker::SegmentType::data;
|
||||||
|
|
||||||
case ElfParser::SHT_NOBITS:
|
case ElfFile::SHT_NOBITS:
|
||||||
return ElfLinker::SegmentType::data;
|
return ElfLinker::SegmentType::data;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -49,8 +49,8 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
ElfLinker::ElfLinker(uInt32 textBase, uInt32 dataBase, uInt32 rodataBase, const ElfParser& parser)
|
ElfLinker::ElfLinker(uInt32 textBase, uInt32 dataBase, uInt32 rodataBase, const ElfFile& elf)
|
||||||
: myTextBase(textBase), myDataBase(dataBase), myRodataBase(rodataBase), myParser(parser)
|
: myTextBase(textBase), myDataBase(dataBase), myRodataBase(rodataBase), myElf(elf)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -148,7 +148,7 @@ const vector<uInt32>& ElfLinker::getPreinitArray() const
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
ElfLinker::RelocatedSymbol ElfLinker::findRelocatedSymbol(string_view name) const
|
ElfLinker::RelocatedSymbol ElfLinker::findRelocatedSymbol(string_view name) const
|
||||||
{
|
{
|
||||||
const auto& symbols = myParser.getSymbols();
|
const auto& symbols = myElf.getSymbols();
|
||||||
for (size_t i = 0; i < symbols.size(); i++) {
|
for (size_t i = 0; i < symbols.size(); i++) {
|
||||||
if (symbols[i].name != name) continue;
|
if (symbols[i].name != name) continue;
|
||||||
|
|
||||||
|
@ -212,7 +212,7 @@ unique_ptr<uInt8[]>& ElfLinker::getSegmentDataRef(SegmentType type)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void ElfLinker::relocateSections()
|
void ElfLinker::relocateSections()
|
||||||
{
|
{
|
||||||
auto& sections = myParser.getSections();
|
auto& sections = myElf.getSections();
|
||||||
myRelocatedSections.resize(sections.size(), std::nullopt);
|
myRelocatedSections.resize(sections.size(), std::nullopt);
|
||||||
|
|
||||||
// relocate everything that is not .bss
|
// relocate everything that is not .bss
|
||||||
|
@ -220,7 +220,7 @@ void ElfLinker::relocateSections()
|
||||||
const auto& section = sections[i];
|
const auto& section = sections[i];
|
||||||
|
|
||||||
const auto segmentType = determineSegmentType(section);
|
const auto segmentType = determineSegmentType(section);
|
||||||
if (!segmentType || section.type == ElfParser::SHT_NOBITS) continue;
|
if (!segmentType || section.type == ElfFile::SHT_NOBITS) continue;
|
||||||
|
|
||||||
uInt32& segmentSize = getSegmentSizeRef(*segmentType);
|
uInt32& segmentSize = getSegmentSizeRef(*segmentType);
|
||||||
|
|
||||||
|
@ -235,7 +235,7 @@ void ElfLinker::relocateSections()
|
||||||
for (size_t i = 0; i < sections.size(); i++) {
|
for (size_t i = 0; i < sections.size(); i++) {
|
||||||
const auto& section = sections[i];
|
const auto& section = sections[i];
|
||||||
|
|
||||||
if (section.type == ElfParser::SHT_NOBITS) {
|
if (section.type == ElfFile::SHT_NOBITS) {
|
||||||
if (myDataSize % section.align)
|
if (myDataSize % section.align)
|
||||||
myDataSize = (myDataSize / section.align + 1) * section.align;
|
myDataSize = (myDataSize / section.align + 1) * section.align;
|
||||||
|
|
||||||
|
@ -269,14 +269,14 @@ void ElfLinker::relocateSections()
|
||||||
if (!relocatedSection) continue;
|
if (!relocatedSection) continue;
|
||||||
|
|
||||||
const auto& section = sections[i];
|
const auto& section = sections[i];
|
||||||
if (section.type == ElfParser::SHT_NOBITS) continue;
|
if (section.type == ElfFile::SHT_NOBITS) continue;
|
||||||
|
|
||||||
const auto segmentType = determineSegmentType(section);
|
const auto segmentType = determineSegmentType(section);
|
||||||
if (!segmentType) continue;
|
if (!segmentType) continue;
|
||||||
|
|
||||||
std::memcpy(
|
std::memcpy(
|
||||||
getSegmentDataRef(*segmentType).get() + relocatedSection->offset,
|
getSegmentDataRef(*segmentType).get() + relocatedSection->offset,
|
||||||
myParser.getData() + section.offset,
|
myElf.getData() + section.offset,
|
||||||
section.size
|
section.size
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -285,7 +285,7 @@ void ElfLinker::relocateSections()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void ElfLinker::relocateInitArrays()
|
void ElfLinker::relocateInitArrays()
|
||||||
{
|
{
|
||||||
const auto& sections = myParser.getSections();
|
const auto& sections = myElf.getSections();
|
||||||
uInt32 initArraySize = 0;
|
uInt32 initArraySize = 0;
|
||||||
uInt32 preinitArraySize = 0;
|
uInt32 preinitArraySize = 0;
|
||||||
|
|
||||||
|
@ -297,7 +297,7 @@ void ElfLinker::relocateInitArrays()
|
||||||
const auto& section = sections[i];
|
const auto& section = sections[i];
|
||||||
|
|
||||||
switch (section.type) {
|
switch (section.type) {
|
||||||
case ElfParser::SHT_INIT_ARRAY:
|
case ElfFile::SHT_INIT_ARRAY:
|
||||||
if (section.size % 4) ElfLinkError::raise("invalid init array");
|
if (section.size % 4) ElfLinkError::raise("invalid init array");
|
||||||
|
|
||||||
relocatedInitArrays[i] = initArraySize;
|
relocatedInitArrays[i] = initArraySize;
|
||||||
|
@ -305,7 +305,7 @@ void ElfLinker::relocateInitArrays()
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ElfParser::SHT_PREINIT_ARRAY:
|
case ElfFile::SHT_PREINIT_ARRAY:
|
||||||
if (section.size % 4) ElfLinkError::raise("invalid preinit array");
|
if (section.size % 4) ElfLinkError::raise("invalid preinit array");
|
||||||
|
|
||||||
relocatedPreinitArrays[i] = preinitArraySize;
|
relocatedPreinitArrays[i] = preinitArraySize;
|
||||||
|
@ -321,8 +321,8 @@ void ElfLinker::relocateInitArrays()
|
||||||
copyInitArrays(myInitArray, relocatedInitArrays);
|
copyInitArrays(myInitArray, relocatedInitArrays);
|
||||||
copyInitArrays(myPreinitArray, relocatedPreinitArrays);
|
copyInitArrays(myPreinitArray, relocatedPreinitArrays);
|
||||||
|
|
||||||
applyRelocationsToInitArrays(ElfParser::SHT_INIT_ARRAY, myInitArray, relocatedInitArrays);
|
applyRelocationsToInitArrays(ElfFile::SHT_INIT_ARRAY, myInitArray, relocatedInitArrays);
|
||||||
applyRelocationsToInitArrays(ElfParser::SHT_PREINIT_ARRAY, myPreinitArray, relocatedPreinitArrays);
|
applyRelocationsToInitArrays(ElfFile::SHT_PREINIT_ARRAY, myPreinitArray, relocatedPreinitArrays);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -334,19 +334,19 @@ void ElfLinker::relocateSymbols(const vector<ExternalSymbol>& externalSymbols)
|
||||||
externalSymbolLookup[externalSymbol.name] = &externalSymbol;
|
externalSymbolLookup[externalSymbol.name] = &externalSymbol;
|
||||||
|
|
||||||
// relocate symbols
|
// relocate symbols
|
||||||
const auto& symbols = myParser.getSymbols();
|
const auto& symbols = myElf.getSymbols();
|
||||||
myRelocatedSymbols.resize(symbols.size(), std::nullopt);
|
myRelocatedSymbols.resize(symbols.size(), std::nullopt);
|
||||||
|
|
||||||
for (size_t i = 0; i < symbols.size(); i++) {
|
for (size_t i = 0; i < symbols.size(); i++) {
|
||||||
const auto& symbol = symbols[i];
|
const auto& symbol = symbols[i];
|
||||||
|
|
||||||
if (symbol.section == ElfParser::SHN_ABS) {
|
if (symbol.section == ElfFile::SHN_ABS) {
|
||||||
myRelocatedSymbols[i] = {std::nullopt, symbol.value, false};
|
myRelocatedSymbols[i] = {std::nullopt, symbol.value, false};
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (symbol.section == ElfParser::SHN_UND) {
|
if (symbol.section == ElfFile::SHN_UND) {
|
||||||
if (externalSymbolLookup.contains(symbol.name))
|
if (externalSymbolLookup.contains(symbol.name))
|
||||||
myRelocatedSymbols[i] = {std::nullopt, externalSymbolLookup[symbol.name]->value, false};
|
myRelocatedSymbols[i] = {std::nullopt, externalSymbolLookup[symbol.name]->value, false};
|
||||||
|
|
||||||
|
@ -360,7 +360,7 @@ void ElfLinker::relocateSymbols(const vector<ExternalSymbol>& externalSymbols)
|
||||||
if (!relocatedSection) continue;
|
if (!relocatedSection) continue;
|
||||||
|
|
||||||
uInt32 value = getSegmentBase(relocatedSection->segment) + relocatedSection->offset;
|
uInt32 value = getSegmentBase(relocatedSection->segment) + relocatedSection->offset;
|
||||||
if (symbol.type != ElfParser::STT_SECTION) value += symbol.value;
|
if (symbol.type != ElfFile::STT_SECTION) value += symbol.value;
|
||||||
|
|
||||||
myRelocatedSymbols[i] = {relocatedSection->segment, value, false};
|
myRelocatedSymbols[i] = {relocatedSection->segment, value, false};
|
||||||
}
|
}
|
||||||
|
@ -369,11 +369,11 @@ void ElfLinker::relocateSymbols(const vector<ExternalSymbol>& externalSymbols)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void ElfLinker::applyRelocationsToSections()
|
void ElfLinker::applyRelocationsToSections()
|
||||||
{
|
{
|
||||||
auto& sections = myParser.getSections();
|
auto& sections = myElf.getSections();
|
||||||
|
|
||||||
// apply relocations
|
// apply relocations
|
||||||
for (size_t iSection = 0; iSection < sections.size(); iSection++) {
|
for (size_t iSection = 0; iSection < sections.size(); iSection++) {
|
||||||
const auto& relocations = myParser.getRelocations(iSection);
|
const auto& relocations = myElf.getRelocations(iSection);
|
||||||
if (!relocations) continue;
|
if (!relocations) continue;
|
||||||
if (!myRelocatedSections[iSection]) continue;
|
if (!myRelocatedSections[iSection]) continue;
|
||||||
|
|
||||||
|
@ -385,8 +385,8 @@ void ElfLinker::applyRelocationsToSections()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void ElfLinker::copyInitArrays(vector<uInt32>& initArray, std::unordered_map<uInt32, uInt32> relocatedInitArrays)
|
void ElfLinker::copyInitArrays(vector<uInt32>& initArray, std::unordered_map<uInt32, uInt32> relocatedInitArrays)
|
||||||
{
|
{
|
||||||
const uInt8* elfData = myParser.getData();
|
const uInt8* elfData = myElf.getData();
|
||||||
const auto& sections = myParser.getSections();
|
const auto& sections = myElf.getSections();
|
||||||
|
|
||||||
// Copy init arrays
|
// Copy init arrays
|
||||||
for (const auto [iSection, offset]: relocatedInitArrays) {
|
for (const auto [iSection, offset]: relocatedInitArrays) {
|
||||||
|
@ -398,11 +398,11 @@ void ElfLinker::copyInitArrays(vector<uInt32>& initArray, std::unordered_map<uI
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void ElfLinker::applyRelocationToSection(const ElfParser::Relocation& relocation, size_t iSection)
|
void ElfLinker::applyRelocationToSection(const ElfFile::Relocation& relocation, size_t iSection)
|
||||||
{
|
{
|
||||||
const auto& targetSection = myParser.getSections()[iSection];
|
const auto& targetSection = myElf.getSections()[iSection];
|
||||||
const auto& targetSectionRelocated = *myRelocatedSections[iSection];
|
const auto& targetSectionRelocated = *myRelocatedSections[iSection];
|
||||||
const auto& symbol = myParser.getSymbols()[relocation.symbol];
|
const auto& symbol = myElf.getSymbols()[relocation.symbol];
|
||||||
const auto& relocatedSymbol = myRelocatedSymbols[relocation.symbol];
|
const auto& relocatedSymbol = myRelocatedSymbols[relocation.symbol];
|
||||||
|
|
||||||
if (!relocatedSymbol) ElfLinkError::raise(
|
if (!relocatedSymbol) ElfLinkError::raise(
|
||||||
|
@ -422,17 +422,17 @@ void ElfLinker::applyRelocationToSection(const ElfParser::Relocation& relocation
|
||||||
relocation.offset;
|
relocation.offset;
|
||||||
|
|
||||||
switch (relocation.type) {
|
switch (relocation.type) {
|
||||||
case ElfParser::R_ARM_ABS32:
|
case ElfFile::R_ARM_ABS32:
|
||||||
case ElfParser::R_ARM_TARGET1:
|
case ElfFile::R_ARM_TARGET1:
|
||||||
{
|
{
|
||||||
const uInt32 value = relocatedSymbol->value + relocation.addend.value_or(read32(target));
|
const uInt32 value = relocatedSymbol->value + relocation.addend.value_or(read32(target));
|
||||||
write32(target, value | (symbol.type == ElfParser::STT_FUNC ? 0x01 : 0));
|
write32(target, value | (symbol.type == ElfFile::STT_FUNC ? 0x01 : 0));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ElfParser::R_ARM_THM_CALL:
|
case ElfFile::R_ARM_THM_CALL:
|
||||||
case ElfParser::R_ARM_THM_JUMP24:
|
case ElfFile::R_ARM_THM_JUMP24:
|
||||||
{
|
{
|
||||||
const uInt32 op = read32(target);
|
const uInt32 op = read32(target);
|
||||||
|
|
||||||
|
@ -444,7 +444,7 @@ void ElfLinker::applyRelocationToSection(const ElfParser::Relocation& relocation
|
||||||
if ((offset >> 24) != -1 && (offset >> 24) != 0)
|
if ((offset >> 24) != -1 && (offset >> 24) != 0)
|
||||||
ElfLinkError::raise("unable to relocate jump: offset out of bounds");
|
ElfLinkError::raise("unable to relocate jump: offset out of bounds");
|
||||||
|
|
||||||
write32(target, elfUtil::encode_B_BL(offset, relocation.type == ElfParser::R_ARM_THM_CALL));
|
write32(target, elfUtil::encode_B_BL(offset, relocation.type == ElfFile::R_ARM_THM_CALL));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -453,18 +453,18 @@ void ElfLinker::applyRelocationToSection(const ElfParser::Relocation& relocation
|
||||||
void ElfLinker::applyRelocationsToInitArrays(uInt8 initArrayType, vector<uInt32>& initArray,
|
void ElfLinker::applyRelocationsToInitArrays(uInt8 initArrayType, vector<uInt32>& initArray,
|
||||||
const std::unordered_map<uInt32, uInt32>& relocatedInitArrays)
|
const std::unordered_map<uInt32, uInt32>& relocatedInitArrays)
|
||||||
{
|
{
|
||||||
const auto& symbols = myParser.getSymbols();
|
const auto& symbols = myElf.getSymbols();
|
||||||
const auto& sections = myParser.getSections();
|
const auto& sections = myElf.getSections();
|
||||||
|
|
||||||
for (size_t iSection = 0; iSection < sections.size(); iSection++) {
|
for (size_t iSection = 0; iSection < sections.size(); iSection++) {
|
||||||
const auto& section = sections[iSection];
|
const auto& section = sections[iSection];
|
||||||
if (section.type != initArrayType) continue;
|
if (section.type != initArrayType) continue;
|
||||||
|
|
||||||
const auto& relocations = myParser.getRelocations(iSection);
|
const auto& relocations = myElf.getRelocations(iSection);
|
||||||
if (!relocations) continue;
|
if (!relocations) continue;
|
||||||
|
|
||||||
for (const auto& relocation: *relocations) {
|
for (const auto& relocation: *relocations) {
|
||||||
if (relocation.type != ElfParser::R_ARM_ABS32 && relocation.type != ElfParser::R_ARM_TARGET1)
|
if (relocation.type != ElfFile::R_ARM_ABS32 && relocation.type != ElfFile::R_ARM_TARGET1)
|
||||||
ElfLinkError::raise("unsupported relocation for init array");
|
ElfLinkError::raise("unsupported relocation for init array");
|
||||||
|
|
||||||
const auto& relocatedSymbol = myRelocatedSymbols[relocation.symbol];
|
const auto& relocatedSymbol = myRelocatedSymbols[relocation.symbol];
|
||||||
|
@ -481,7 +481,7 @@ void ElfLinker::applyRelocationsToInitArrays(uInt8 initArrayType, vector<uInt32>
|
||||||
|
|
||||||
const uInt32 index = (relocatedInitArrays.at(iSection) + relocation.offset) >> 2;
|
const uInt32 index = (relocatedInitArrays.at(iSection) + relocation.offset) >> 2;
|
||||||
const uInt32 value = relocatedSymbol->value + relocation.addend.value_or(initArray[index]);
|
const uInt32 value = relocatedSymbol->value + relocation.addend.value_or(initArray[index]);
|
||||||
initArray[index] = value | (symbols[relocation.symbol].type == ElfParser::STT_FUNC ? 1 : 0);
|
initArray[index] = value | (symbols[relocation.symbol].type == ElfFile::STT_FUNC ? 1 : 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#define ELF_LINKER
|
#define ELF_LINKER
|
||||||
|
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "ElfParser.hxx"
|
#include "ElfFile.hxx"
|
||||||
|
|
||||||
class ElfLinker {
|
class ElfLinker {
|
||||||
public:
|
public:
|
||||||
|
@ -76,7 +76,7 @@ class ElfLinker {
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ElfLinker(uInt32 textBase, uInt32 dataBase, uInt32 rodataBase, const ElfParser& parser);
|
ElfLinker(uInt32 textBase, uInt32 dataBase, uInt32 rodataBase, const ElfFile& elf);
|
||||||
|
|
||||||
ElfLinker& setUndefinedSymbolDefault(uInt32 defaultValue);
|
ElfLinker& setUndefinedSymbolDefault(uInt32 defaultValue);
|
||||||
void link(const vector<ExternalSymbol>& externalSymbols);
|
void link(const vector<ExternalSymbol>& externalSymbols);
|
||||||
|
@ -103,7 +103,7 @@ class ElfLinker {
|
||||||
void applyRelocationsToSections();
|
void applyRelocationsToSections();
|
||||||
void copyInitArrays(vector<uInt32>& initArray, std::unordered_map<uInt32, uInt32> relocatedInitArrays);
|
void copyInitArrays(vector<uInt32>& initArray, std::unordered_map<uInt32, uInt32> relocatedInitArrays);
|
||||||
|
|
||||||
void applyRelocationToSection(const ElfParser::Relocation& relocation, size_t iSection);
|
void applyRelocationToSection(const ElfFile::Relocation& relocation, size_t iSection);
|
||||||
void applyRelocationsToInitArrays(uInt8 initArrayType, vector<uInt32>& initArray,
|
void applyRelocationsToInitArrays(uInt8 initArrayType, vector<uInt32>& initArray,
|
||||||
const std::unordered_map<uInt32, uInt32>& relocatedInitArrays);
|
const std::unordered_map<uInt32, uInt32>& relocatedInitArrays);
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ class ElfLinker {
|
||||||
const uInt32 myTextBase{0};
|
const uInt32 myTextBase{0};
|
||||||
const uInt32 myDataBase{0};
|
const uInt32 myDataBase{0};
|
||||||
const uInt32 myRodataBase{0};
|
const uInt32 myRodataBase{0};
|
||||||
const ElfParser& myParser;
|
const ElfFile& myElf;
|
||||||
|
|
||||||
uInt32 myTextSize{0};
|
uInt32 myTextSize{0};
|
||||||
uInt32 myDataSize{0};
|
uInt32 myDataSize{0};
|
||||||
|
|
|
@ -126,16 +126,6 @@ const vector<ElfParser::Symbol>& ElfParser::getSymbols() const
|
||||||
return mySymbols;
|
return mySymbols;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
const optional<ElfParser::Section>
|
|
||||||
ElfParser::getSection(const string &name) const {
|
|
||||||
for (const Section §ion : mySections)
|
|
||||||
if (section.name == name)
|
|
||||||
return section;
|
|
||||||
|
|
||||||
return optional<Section>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
const optional<vector<ElfParser::Relocation>> ElfParser::getRelocations(size_t section) const
|
const optional<vector<ElfParser::Relocation>> ElfParser::getRelocations(size_t section) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,9 +20,10 @@
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "ElfFile.hxx"
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
|
|
||||||
class ElfParser {
|
class ElfParser : public ElfFile {
|
||||||
public:
|
public:
|
||||||
class ElfParseError : public std::exception {
|
class ElfParseError : public std::exception {
|
||||||
friend ElfParser;
|
friend ElfParser;
|
||||||
|
@ -41,6 +42,19 @@ class ElfParser {
|
||||||
const string myReason;
|
const string myReason;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
ElfParser() = default;
|
||||||
|
|
||||||
|
void parse(const uInt8 *elfData, size_t size);
|
||||||
|
|
||||||
|
const uInt8 *getData() const override;
|
||||||
|
size_t getSize() const override;
|
||||||
|
|
||||||
|
const vector<Section>& getSections() const override;
|
||||||
|
const vector<Symbol>& getSymbols() const override;
|
||||||
|
const optional<vector<Relocation>> getRelocations(size_t section) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
struct Header {
|
struct Header {
|
||||||
uInt16 type;
|
uInt16 type;
|
||||||
uInt16 arch;
|
uInt16 arch;
|
||||||
|
@ -52,88 +66,6 @@ class ElfParser {
|
||||||
uInt16 shstrIndex;
|
uInt16 shstrIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Section {
|
|
||||||
uInt32 nameOffset;
|
|
||||||
string name;
|
|
||||||
|
|
||||||
uInt32 type;
|
|
||||||
uInt32 flags;
|
|
||||||
|
|
||||||
uInt32 virtualAddress;
|
|
||||||
uInt32 offset;
|
|
||||||
uInt32 size;
|
|
||||||
|
|
||||||
uInt32 info;
|
|
||||||
uInt32 align;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Symbol {
|
|
||||||
uInt32 nameOffset;
|
|
||||||
uInt32 value;
|
|
||||||
uInt32 size;
|
|
||||||
uInt8 info;
|
|
||||||
uInt8 visibility;
|
|
||||||
uInt16 section;
|
|
||||||
|
|
||||||
string name;
|
|
||||||
uInt8 bind;
|
|
||||||
uInt8 type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Relocation {
|
|
||||||
uInt32 offset;
|
|
||||||
uInt32 info;
|
|
||||||
optional<uInt32> addend;
|
|
||||||
|
|
||||||
uInt32 symbol;
|
|
||||||
uInt8 type;
|
|
||||||
string symbolName;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
static constexpr uInt8 ENDIAN_LITTLE_ENDIAN = 0x01;
|
|
||||||
static constexpr uInt8 ENDIAN_BIG_ENDIAN = 0x02;
|
|
||||||
|
|
||||||
static constexpr uInt16 ET_REL = 0x01;
|
|
||||||
|
|
||||||
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;
|
|
||||||
static constexpr uInt32 SHT_RELA = 0x04;
|
|
||||||
static constexpr uInt32 SHT_NOBITS = 0x08;
|
|
||||||
static constexpr uInt32 SHT_REL = 0x09;
|
|
||||||
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;
|
|
||||||
|
|
||||||
static constexpr uInt32 STT_SECTION = 0x03;
|
|
||||||
|
|
||||||
static constexpr uInt32 R_ARM_ABS32 = 0x02;
|
|
||||||
static constexpr uInt32 R_ARM_THM_CALL = 0x0a;
|
|
||||||
static constexpr uInt32 R_ARM_THM_JUMP24 = 0x1e;
|
|
||||||
static constexpr uInt32 R_ARM_TARGET1 = 0x26;
|
|
||||||
|
|
||||||
static constexpr uInt32 STT_FUNC = 0x02;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ElfParser() = default;
|
|
||||||
|
|
||||||
void parse(const uInt8 *elfData, size_t size);
|
|
||||||
|
|
||||||
const uInt8 *getData() const;
|
|
||||||
size_t getSize() const;
|
|
||||||
|
|
||||||
const Header& getHeader() const;
|
|
||||||
const vector<Section>& getSections() const;
|
|
||||||
const vector<Symbol>& getSymbols() const;
|
|
||||||
const optional<Section> getSection(const std::string &name) const;
|
|
||||||
const optional<vector<Relocation>> getRelocations(size_t section) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uInt8 read8(uInt32 offset) const;
|
uInt8 read8(uInt32 offset) const;
|
||||||
uInt16 read16(uInt32 offset) const;
|
uInt16 read16(uInt32 offset) const;
|
||||||
|
|
|
@ -1665,6 +1665,7 @@
|
||||||
<ClInclude Include="..\..\emucore\ControllerDetector.hxx" />
|
<ClInclude Include="..\..\emucore\ControllerDetector.hxx" />
|
||||||
<ClInclude Include="..\..\emucore\ControlLowLevel.hxx" />
|
<ClInclude Include="..\..\emucore\ControlLowLevel.hxx" />
|
||||||
<ClInclude Include="..\..\emucore\DispatchResult.hxx" />
|
<ClInclude Include="..\..\emucore\DispatchResult.hxx" />
|
||||||
|
<ClInclude Include="..\..\emucore\elf\ElfFile.hxx" />
|
||||||
<ClInclude Include="..\..\emucore\elf\ElfParser.hxx" />
|
<ClInclude Include="..\..\emucore\elf\ElfParser.hxx" />
|
||||||
<ClInclude Include="..\..\emucore\elf\ElfLinker.hxx" />
|
<ClInclude Include="..\..\emucore\elf\ElfLinker.hxx" />
|
||||||
<ClInclude Include="..\..\emucore\elf\ElfUtil.hxx" />
|
<ClInclude Include="..\..\emucore\elf\ElfUtil.hxx" />
|
||||||
|
|
|
@ -2531,6 +2531,9 @@
|
||||||
<ClInclude Include="..\..\debugger\gui\CartJANEWidget.hxx">
|
<ClInclude Include="..\..\debugger\gui\CartJANEWidget.hxx">
|
||||||
<Filter>Header Files\debugger\gui</Filter>
|
<Filter>Header Files\debugger\gui</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\emucore\elf\ElfFile.hxx">
|
||||||
|
<Filter>Header Files\emucore\elf</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\emucore\elf\ElfParser.hxx">
|
<ClInclude Include="..\..\emucore\elf\ElfParser.hxx">
|
||||||
<Filter>Header Files\emucore\elf</Filter>
|
<Filter>Header Files\emucore\elf</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
Loading…
Reference in New Issue