Skip to content

Commit

Permalink
Refactoring.
Browse files Browse the repository at this point in the history
  • Loading branch information
DirtyHairy committed Jul 12, 2024
1 parent dfdcddb commit 9c1231b
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 63 deletions.
117 changes: 54 additions & 63 deletions src/emucore/elf/ElfLinker.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -211,70 +211,11 @@ void ElfLinker::relocateInitArrays()
myInitArray.resize(initArraySize >> 2);
myPreinitArray.resize(preinitArraySize >> 2);

const uInt8* elfData = myParser.getData();

// Copy init arrays
for (const auto [iSection, offset]: relocatedInitArrays) {
const auto& section = sections[iSection];

for (size_t i = 0; i < section.size; i += 4)
myInitArray[(offset + i) >> 2] = read32(elfData + section.offset + i);
}

for (const auto [iSection, offset]: relocatedPreinitArrays) {
const auto& section = sections[iSection];

for (size_t i = 0; i < section.size; i += 4)
myPreinitArray[(offset + i) >> 2] = read32(elfData + section.offset + i);
}

// Apply relocations
const auto& symbols = myParser.getSymbols();
copyInitArrays(myInitArray, relocatedInitArrays);
copyInitArrays(myPreinitArray, relocatedPreinitArrays);

for (size_t iSection = 0; iSection < sections.size(); iSection++) {
const auto& section = sections[iSection];
if (section.type != ElfParser::SHT_INIT_ARRAY && section.type != ElfParser::SHT_PREINIT_ARRAY) continue;

const auto& relocations = myParser.getRelocations(iSection);
if (!relocations) continue;

for (const auto& relocation: *relocations) {
if (relocation.type != ElfParser::R_ARM_ABS32 && relocation.type != ElfParser::R_ARM_TARGET1)
ElfLinkError::raise("unsupported relocation for init table");

const auto& relocatedSymbol = myRelocatedSymbols[relocation.symbol];
if (!relocatedSymbol)
ElfLinkError::raise(
"unable to relocate init section: symbol " + relocation.symbolName + " could not be relocated"
);

if (relocatedSymbol->undefined)
Logger::error("unable to relocate symbol " + relocation.symbolName);

if (relocation.offset + 4 > section.size)
ElfLinkError::raise("unable relocate init section: symbol " + relocation.symbolName + " out of range");

switch (section.type) {
case ElfParser::SHT_INIT_ARRAY:
{
const uInt32 index = (relocatedInitArrays.at(iSection) + relocation.offset) >> 2;
const uInt32 value = relocatedSymbol->value + relocation.addend.value_or(myInitArray[index]);
myInitArray[index] = value | (symbols[relocation.symbol].type == ElfParser::STT_FUNC ? 1 : 0);

break;
}

case ElfParser::SHT_PREINIT_ARRAY:
{
const uInt32 index = (relocatedPreinitArrays.at(iSection) + relocation.offset) >> 2;
const uInt32 value = relocatedSymbol->value + relocation.addend.value_or(myPreinitArray[index]);
myPreinitArray[index] = value | (symbols[relocation.symbol].type == ElfParser::STT_FUNC ? 1 : 0);

break;
}
}
}
}
applyRelocationsToInitArrays(ElfParser::SHT_INIT_ARRAY, myInitArray, relocatedInitArrays);
applyRelocationsToInitArrays(ElfParser::SHT_PREINIT_ARRAY, myPreinitArray, relocatedPreinitArrays);
}

void ElfLinker::relocateSymbols(const vector<ExternalSymbol>& externalSymbols)
Expand Down Expand Up @@ -333,6 +274,20 @@ void ElfLinker::applyRelocationsToSections()
}
}

void ElfLinker::copyInitArrays(vector<uInt32>& initArray, std::unordered_map<uInt32, uInt32> relocatedInitArrays)
{
const uInt8* elfData = myParser.getData();
const auto& sections = myParser.getSections();

// Copy init arrays
for (const auto [iSection, offset]: relocatedInitArrays) {
const auto& section = sections[iSection];

for (size_t i = 0; i < section.size; i += 4)
initArray[(offset + i) >> 2] = read32(elfData + section.offset + i);
}
}

void ElfLinker::applyRelocationToSection(const ElfParser::Relocation& relocation, size_t iSection)
{
const auto& targetSection = myParser.getSections()[iSection];
Expand Down Expand Up @@ -382,6 +337,42 @@ void ElfLinker::applyRelocationToSection(const ElfParser::Relocation& relocation
}
}

void ElfLinker::applyRelocationsToInitArrays(uInt8 initArrayType, vector<uInt32>& initArray,
std::unordered_map<uInt32, uInt32> relocatedInitArrays)
{
const auto& symbols = myParser.getSymbols();
const auto& sections = myParser.getSections();

for (size_t iSection = 0; iSection < sections.size(); iSection++) {
const auto& section = sections[iSection];
if (section.type != initArrayType) continue;

const auto& relocations = myParser.getRelocations(iSection);
if (!relocations) continue;

for (const auto& relocation: *relocations) {
if (relocation.type != ElfParser::R_ARM_ABS32 && relocation.type != ElfParser::R_ARM_TARGET1)
ElfLinkError::raise("unsupported relocation for init table");

const auto& relocatedSymbol = myRelocatedSymbols[relocation.symbol];
if (!relocatedSymbol)
ElfLinkError::raise(
"unable to relocate init section: symbol " + relocation.symbolName + " could not be relocated"
);

if (relocatedSymbol->undefined)
Logger::error("unable to relocate symbol " + relocation.symbolName);

if (relocation.offset + 4 > section.size)
ElfLinkError::raise("unable relocate init section: symbol " + relocation.symbolName + " out of range");

const uInt32 index = (relocatedInitArrays.at(iSection) + relocation.offset) >> 2;
const uInt32 value = relocatedSymbol->value + relocation.addend.value_or(initArray[index]);
initArray[index] = value | (symbols[relocation.symbol].type == ElfParser::STT_FUNC ? 1 : 0);
}
}
}

uInt32 ElfLinker::read32(const uInt8* address)
{
uInt32 value = *(address++);
Expand Down
3 changes: 3 additions & 0 deletions src/emucore/elf/ElfLinker.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,11 @@ class ElfLinker {
void relocateInitArrays();
void relocateSymbols(const vector<ExternalSymbol>& externalSymbols);
void applyRelocationsToSections();
void copyInitArrays(vector<uInt32>& initArray, std::unordered_map<uInt32, uInt32> relocatedInitArrays);

void applyRelocationToSection(const ElfParser::Relocation& relocation, size_t iSection);
void applyRelocationsToInitArrays(uInt8 initArrayType,
vector<uInt32>& initArray, std::unordered_map<uInt32, uInt32> relocatedInitArrays);

uInt32 read32(const uInt8* address);
void write32(uInt8* address, uInt32 value);
Expand Down

0 comments on commit 9c1231b

Please sign in to comment.