This commit is contained in:
Christian Speckner 2024-07-10 08:28:45 +02:00
parent 135349ed6b
commit 5a7a72c745
4 changed files with 85 additions and 32 deletions

View File

@ -82,16 +82,17 @@ namespace {
};
#ifdef DUMP_ELF
void dumpElf(const ElfParser& elfParser) {
void dumpElf(const ElfParser& parser)
{
cout << "ELF sections:" << std::endl << std::endl;
size_t i = 0;
for (auto& section: elfParser.getSections()) {
for (auto& section: parser.getSections()) {
if (section.type != 0x00) cout << i << " " << section << std::endl;
i++;
}
auto symbols = elfParser.getSymbols();
auto symbols = parser.getSymbols();
cout << std::endl << "ELF symbols:" << std::endl << std::endl;
if (symbols.size() > 0) {
i = 0;
@ -100,8 +101,8 @@ namespace {
}
i = 0;
for (auto& section: elfParser.getSections()) {
auto rels = elfParser.getRelocations(i++);
for (auto& section: parser.getSections()) {
auto rels = parser.getRelocations(i++);
if (!rels) continue;
cout
@ -111,6 +112,49 @@ namespace {
for (auto& rel: *rels) cout << rel << std::endl;
}
}
void dumpLinkage(const ElfParser& parser, const ElfLinker& linker)
{
cout << std::endl << "relocated sections:" << std::endl << std::endl;
cout << std::hex << std::setfill('0');
const auto& sections = parser.getSections();
const auto& relocatedSections = linker.getRelocatedSections();
for (size_t i = 0; i < sections.size(); i++) {
if (!relocatedSections[i]) continue;
cout
<< sections[i].name
<< " @ 0x"<< std::setw(8) << (relocatedSections[i]->offset +
(relocatedSections[i]->type == ElfLinker::SectionType::text ? ADDR_TEXT_BASE : ADDR_DATA_BASE)
)
<< " size 0x" << std::setw(8) << sections[i].size << std::endl;
}
cout << std::endl << "relocated symbols:" << std::endl << std::endl;
const auto& symbols = parser.getSymbols();
const auto& relocatedSymbols = linker.getRelocatedSymbols();
for (size_t i = 0; i < symbols.size(); i++) {
if (!relocatedSymbols[i]) continue;
cout
<< symbols[i].name
<< " = 0x" << std::setw(8) << relocatedSymbols[i]->value;
if (relocatedSymbols[i]->section) {
cout << (*relocatedSymbols[i]->section == ElfLinker::SectionType::text ? " (text)" : " (data)");
} else {
cout << " (abs)";
}
cout << std::endl;
}
cout << std::dec;
}
#endif
}
@ -153,6 +197,8 @@ CartridgeELF::CartridgeELF(const ByteBuffer& image, size_t size, string_view md5
}
#ifdef DUMP_ELF
dumpLinkage(elfParser, elfLinker);
cout
<< std::endl
<< "ARM entrypoint: 0x"

View File

@ -78,7 +78,7 @@ void ElfLinker::link(const vector<ExternalSymbol>& externalSymbols)
for (size_t i = 0; i < sections.size(); i++) {
const auto& relocatedSection = myRelocatedSections[i];
if (!relocatedSection.has_value()) continue;
if (!relocatedSection) continue;
const auto& section = sections[i];
if (section.type != ElfParser::SHT_PROGBITS) continue;
@ -192,6 +192,16 @@ ElfLinker::RelocatedSymbol ElfLinker::findRelocatedSymbol(string_view name) cons
ElfSymbolResolutionError::raise("symbol not found");
}
const vector<std::optional<ElfLinker::RelocatedSection>>& ElfLinker::getRelocatedSections() const
{
return myRelocatedSections;
}
const vector<std::optional<ElfLinker::RelocatedSymbol>>& ElfLinker::getRelocatedSymbols() const
{
return myRelocatedSymbols;
}
void ElfLinker::applyRelocation(const ElfParser::Relocation& relocation, size_t iSection)
{
const auto& targetSection = myParser.getSections()[iSection];
@ -204,6 +214,11 @@ void ElfLinker::applyRelocation(const ElfParser::Relocation& relocation, size_t
"unable to relocate " + symbol.name + " in " + targetSection.name + ": symbol could not be relocated"
);
if (relocation.offset + 4 > targetSection.size)
ElfLinkError::raise(
"unable to relocate " + symbol.name + " in " + targetSection.name + ": target out of range"
);
uInt8* target =
(targetSectionRelocated.type == SectionType::text ? myTextData : myDataData).get() +
targetSectionRelocated.offset + relocation.offset;
@ -212,11 +227,6 @@ void ElfLinker::applyRelocation(const ElfParser::Relocation& relocation, size_t
case ElfParser::R_ARM_ABS32:
case ElfParser::R_ARM_TARGET1:
{
if (relocation.offset + 4 > targetSection.size)
ElfLinkError::raise(
"unable to relocate " + symbol.name + " in " + targetSection.name + ": target out of range"
);
const uInt32 value = relocatedSymbol->value + relocation.addend.value_or(read32(target));
write32(target, value | (symbol.type == ElfParser::STT_FUNC ? 0x01 : 0));
@ -226,18 +236,13 @@ void ElfLinker::applyRelocation(const ElfParser::Relocation& relocation, size_t
case ElfParser::R_ARM_THM_CALL:
case ElfParser::R_ARM_THM_JUMP24:
{
if (relocation.offset + 4 > targetSection.size)
ElfLinkError::raise(
"unable to relocate " + symbol.name + " in " + targetSection.name + ": target out of range"
);
const uInt32 op = read32(target);
Int32 offset = relocatedSymbol->value + relocation.addend.value_or(elfUtil::decode_B_BL(op)) -
(targetSectionRelocated.type == SectionType::text ? myTextBase : myDataBase) -
targetSectionRelocated.offset - relocation.offset - 4;
if ((offset >> 25) != -1 && (offset >> 25) != 0)
if ((offset >> 24) != -1 && (offset >> 24) != 0)
ElfLinkError::raise("unable to relocate jump: offset out of bounds");
write32(target, elfUtil::encode_B_BL(offset, relocation.type == ElfParser::R_ARM_THM_CALL));

View File

@ -59,6 +59,11 @@ class ElfLinker {
enum class SectionType: uInt8 { text, data };
struct RelocatedSection {
SectionType type;
uInt32 offset;
};
struct RelocatedSymbol {
optional<SectionType> section;
uInt32 value;
@ -87,11 +92,8 @@ class ElfLinker {
RelocatedSymbol findRelocatedSymbol(string_view name) const;
private:
struct RelocatedSection {
SectionType type;
uInt32 offset;
};
const vector<std::optional<RelocatedSection>>& getRelocatedSections() const;
const vector<std::optional<RelocatedSymbol>>& getRelocatedSymbols() const;
private:
void applyRelocation(const ElfParser::Relocation& relocation, size_t iSection);

View File

@ -329,12 +329,12 @@ ostream& operator<<(ostream& os, const ElfParser::Symbol symbol)
os
<< symbol.nameOffset << " "
<< symbol.name
<< std::hex << std::setw(4) << std::setfill('0')
<< " value=0x" << symbol.value
<< " size=0x" << symbol.size
<< std::hex << std::setfill('0')
<< " value=0x" << std::setw(8) << symbol.value
<< " size=0x" << std::setw(8) << symbol.size
<< std::setw(1)
<< " bind=0x" << (int)symbol.bind
<< " type=0x" << (int)symbol.type;
<< " bind=0x" << std::setw(2) << (int)symbol.bind
<< " type=0x" << std::setw(2) << (int)symbol.type;
os.copyfmt(reset);
@ -351,13 +351,13 @@ ostream& operator<<(ostream& os, const ElfParser::Relocation rel)
os
<< rel.symbolName << " :"
<< std::hex << std::setw(4) << std::setfill('0')
<< " offset=0x" << rel.offset
<< " info=0x" << rel.info
<< " type=0x" << (int)rel.type;
<< std::hex << std::setfill('0')
<< " offset=0x" << std::setw(8) << rel.offset
<< " info=0x" << std::setw(8) << rel.info
<< " type=0x" << std::setw(2) << (int)rel.type;
if (rel.addend.has_value())
os << " addend=0x" << *rel.addend;
os << " addend=0x" << std::setw(8) << *rel.addend;
os.copyfmt(reset);