mirror of https://github.com/stella-emu/stella.git
Introduce a separate segment for rodata.
This commit is contained in:
parent
e8cbfabb79
commit
21c80981cd
|
@ -70,9 +70,11 @@ namespace {
|
||||||
|
|
||||||
cout
|
cout
|
||||||
<< std::endl
|
<< std::endl
|
||||||
<< "text segment size: 0x" << std::setw(8) << linker.getTextSize()
|
<< "text segment size: 0x" << std::setw(8) << linker.getSegmentSize(ElfLinker::SegmentType::text)
|
||||||
<< std::endl
|
<< std::endl
|
||||||
<< "data segment size: 0x" << std::setw(8) << linker.getDataSize()
|
<< "data segment size: 0x" << std::setw(8) << linker.getSegmentSize(ElfLinker::SegmentType::data)
|
||||||
|
<< std::endl
|
||||||
|
<< "rodata segment size: 0x" << std::setw(8) << linker.getSegmentSize(ElfLinker::SegmentType::rodata)
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
cout << std::endl << "relocated sections:" << std::endl << std::endl;
|
cout << std::endl << "relocated sections:" << std::endl << std::endl;
|
||||||
|
@ -85,9 +87,8 @@ namespace {
|
||||||
|
|
||||||
cout
|
cout
|
||||||
<< sections[i].name
|
<< sections[i].name
|
||||||
<< " @ 0x"<< std::setw(8) << (relocatedSections[i]->offset +
|
<< " @ 0x"<< std::setw(8)
|
||||||
(relocatedSections[i]->segment == ElfLinker::SegmentType::text ? ADDR_TEXT_BASE : ADDR_DATA_BASE)
|
<< (relocatedSections[i]->offset + linker.getSegmentBase(relocatedSections[i]->segment))
|
||||||
)
|
|
||||||
<< " size 0x" << std::setw(8) << sections[i].size << std::endl;
|
<< " size 0x" << std::setw(8) << sections[i].size << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +105,19 @@ namespace {
|
||||||
<< " = 0x" << std::setw(8) << relocatedSymbols[i]->value;
|
<< " = 0x" << std::setw(8) << relocatedSymbols[i]->value;
|
||||||
|
|
||||||
if (relocatedSymbols[i]->segment) {
|
if (relocatedSymbols[i]->segment) {
|
||||||
cout << (*relocatedSymbols[i]->segment == ElfLinker::SegmentType::text ? " (text)" : " (data)");
|
switch (*relocatedSymbols[i]->segment) {
|
||||||
|
case ElfLinker::SegmentType::text:
|
||||||
|
cout << " (text)";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ElfLinker::SegmentType::data:
|
||||||
|
cout << " (data)";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ElfLinker::SegmentType::rodata:
|
||||||
|
cout << " (rodata)";
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
cout << " (abs)";
|
cout << " (abs)";
|
||||||
}
|
}
|
||||||
|
@ -159,7 +172,7 @@ CartridgeELF::CartridgeELF(const ByteBuffer& image, size_t size, string_view md5
|
||||||
dumpElf(elfParser);
|
dumpElf(elfParser);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ElfLinker elfLinker(ADDR_TEXT_BASE, ADDR_DATA_BASE, elfParser);
|
ElfLinker elfLinker(ADDR_TEXT_BASE, ADDR_DATA_BASE, ADDR_RODATA_BASE, elfParser);
|
||||||
try {
|
try {
|
||||||
elfLinker.link(externalSymbols(Palette::ntsc));
|
elfLinker.link(externalSymbols(Palette::ntsc));
|
||||||
} catch (const ElfLinker::ElfLinkError& e) {
|
} catch (const ElfLinker::ElfLinkError& e) {
|
||||||
|
@ -299,6 +312,7 @@ void CartridgeELF::vcsCopyOverblankToRiotRam()
|
||||||
vcsWrite5(0x80 + i, OVERBLANK_PROGRAM[i]);
|
vcsWrite5(0x80 + i, OVERBLANK_PROGRAM[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void CartridgeELF::vcsStartOverblank()
|
void CartridgeELF::vcsStartOverblank()
|
||||||
{
|
{
|
||||||
myTransactionQueue.injectROM(0x4c);
|
myTransactionQueue.injectROM(0x4c);
|
||||||
|
@ -307,12 +321,14 @@ void CartridgeELF::vcsStartOverblank()
|
||||||
myTransactionQueue.yield(0x0080);
|
myTransactionQueue.yield(0x0080);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
CartridgeELF::BusTransaction CartridgeELF::BusTransaction::transactionYield(uInt16 address)
|
CartridgeELF::BusTransaction CartridgeELF::BusTransaction::transactionYield(uInt16 address)
|
||||||
{
|
{
|
||||||
address &= 0x1fff;
|
address &= 0x1fff;
|
||||||
return {.address = address, .value = 0, .yield = true};
|
return {.address = address, .value = 0, .yield = true};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
CartridgeELF::BusTransaction CartridgeELF::BusTransaction::transactionDrive(uInt16 address, uInt8 value)
|
CartridgeELF::BusTransaction CartridgeELF::BusTransaction::transactionDrive(uInt16 address, uInt8 value)
|
||||||
{
|
{
|
||||||
address &= 0x1fff;
|
address &= 0x1fff;
|
||||||
|
|
|
@ -24,7 +24,8 @@
|
||||||
namespace elfEnvironment {
|
namespace elfEnvironment {
|
||||||
constexpr uInt32 ADDR_TEXT_BASE = 0x00100000;
|
constexpr uInt32 ADDR_TEXT_BASE = 0x00100000;
|
||||||
constexpr uInt32 ADDR_DATA_BASE = 0x00200000;
|
constexpr uInt32 ADDR_DATA_BASE = 0x00200000;
|
||||||
constexpr uInt32 ADDR_TABLES_BASE = 0x00300000;
|
constexpr uInt32 ADDR_RODATA_BASE = 0x00300000;
|
||||||
|
constexpr uInt32 ADDR_TABLES_BASE = 0x00400000;
|
||||||
|
|
||||||
constexpr uInt32 ADDR_ADDR_IDR = 0xf0000000;
|
constexpr uInt32 ADDR_ADDR_IDR = 0xf0000000;
|
||||||
constexpr uInt32 ADDR_DATA_IDR = 0xf0000004;
|
constexpr uInt32 ADDR_DATA_IDR = 0xf0000004;
|
||||||
|
|
|
@ -22,9 +22,35 @@
|
||||||
|
|
||||||
#include "ElfLinker.hxx"
|
#include "ElfLinker.hxx"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
std::optional<ElfLinker::SegmentType> determineSegmentType(const ElfParser::Section& section)
|
||||||
|
{
|
||||||
|
switch (section.type) {
|
||||||
|
case ElfParser::SHT_PROGBITS:
|
||||||
|
if (section.name.starts_with(".text")) return ElfLinker::SegmentType::text;
|
||||||
|
|
||||||
|
if (section.name.starts_with(".rodata")) return ElfLinker::SegmentType::rodata;
|
||||||
|
|
||||||
|
return ElfLinker::SegmentType::data;
|
||||||
|
|
||||||
|
case ElfParser::SHT_NOBITS:
|
||||||
|
return ElfLinker::SegmentType::data;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool checkSegmentOverlap(uInt32 segmentBase1, uInt32 segmentSize1, uInt32 segmentBase2, uInt32 segmentSize2) {
|
||||||
|
return !(segmentBase1 + segmentSize1 <= segmentBase2 || segmentBase2 + segmentSize2 <= segmentBase1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
ElfLinker::ElfLinker(uInt32 textBase, uInt32 dataBase, const ElfParser& parser)
|
ElfLinker::ElfLinker(uInt32 textBase, uInt32 dataBase, uInt32 rodataBase, const ElfParser& parser)
|
||||||
: myTextBase(textBase), myDataBase(dataBase), myParser(parser)
|
: myTextBase(textBase), myDataBase(dataBase), myRodataBase(rodataBase), myParser(parser)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -38,9 +64,10 @@ ElfLinker& ElfLinker::setUndefinedSymbolDefault(uInt32 defaultValue)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void ElfLinker::link(const vector<ExternalSymbol>& externalSymbols)
|
void ElfLinker::link(const vector<ExternalSymbol>& externalSymbols)
|
||||||
{
|
{
|
||||||
myTextSize = myDataSize = 0;
|
myTextSize = myDataSize = myRodataSize = 0;
|
||||||
myTextData.reset();
|
myTextData.reset();
|
||||||
myDataData.reset();
|
myDataData.reset();
|
||||||
|
myRodataData.reset();
|
||||||
myRelocatedSections.resize(0);
|
myRelocatedSections.resize(0);
|
||||||
myRelocatedSymbols.resize(0);
|
myRelocatedSymbols.resize(0);
|
||||||
myInitArray.resize(0);
|
myInitArray.resize(0);
|
||||||
|
@ -53,39 +80,57 @@ void ElfLinker::link(const vector<ExternalSymbol>& externalSymbols)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
uInt32 ElfLinker::getTextBase() const
|
uInt32 ElfLinker::getSegmentSize(SegmentType type) const
|
||||||
{
|
{
|
||||||
return myTextBase;
|
switch (type) {
|
||||||
|
case SegmentType::text:
|
||||||
|
return myTextSize;
|
||||||
|
|
||||||
|
case SegmentType::data:
|
||||||
|
return myDataSize;
|
||||||
|
|
||||||
|
case SegmentType::rodata:
|
||||||
|
return myRodataSize;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw runtime_error("unreachable");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
uInt32 ElfLinker::getTextSize() const
|
const uInt8* ElfLinker::getSegmentData(SegmentType type) const
|
||||||
{
|
{
|
||||||
return myTextSize;
|
switch (type) {
|
||||||
|
case SegmentType::text:
|
||||||
|
return myTextData.get();
|
||||||
|
|
||||||
|
case SegmentType::data:
|
||||||
|
return myDataData.get();
|
||||||
|
|
||||||
|
case SegmentType::rodata:
|
||||||
|
return myRodataData.get();
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw runtime_error("unreachable");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
const uInt8* ElfLinker::getTextData() const
|
uInt32 ElfLinker::getSegmentBase(SegmentType type) const
|
||||||
{
|
{
|
||||||
return myTextData ? myTextData.get() : nullptr;
|
switch (type) {
|
||||||
}
|
case SegmentType::text:
|
||||||
|
return myTextBase;
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
case SegmentType::data:
|
||||||
uInt32 ElfLinker::getDataBase() const
|
return myDataBase;
|
||||||
{
|
|
||||||
return myDataBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
case SegmentType::rodata:
|
||||||
uInt32 ElfLinker::getDataSize() const
|
return myRodataBase;
|
||||||
{
|
|
||||||
return myDataSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
default:
|
||||||
const uInt8* ElfLinker::getDataData() const
|
throw runtime_error("unreachable");
|
||||||
{
|
}
|
||||||
return myDataData ? myDataData.get() : nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -128,26 +173,62 @@ const vector<std::optional<ElfLinker::RelocatedSymbol>>& ElfLinker::getRelocated
|
||||||
return myRelocatedSymbols;
|
return myRelocatedSymbols;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
uInt32& ElfLinker::getSegmentSizeRef(SegmentType type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case SegmentType::text:
|
||||||
|
return myTextSize;
|
||||||
|
|
||||||
|
case SegmentType::data:
|
||||||
|
return myDataSize;
|
||||||
|
|
||||||
|
case SegmentType::rodata:
|
||||||
|
return myRodataSize;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw runtime_error("unreachable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
unique_ptr<uInt8[]>& ElfLinker::getSegmentDataRef(SegmentType type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case SegmentType::text:
|
||||||
|
return myTextData;
|
||||||
|
|
||||||
|
case SegmentType::data:
|
||||||
|
return myDataData;
|
||||||
|
|
||||||
|
case SegmentType::rodata:
|
||||||
|
return myRodataData;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw runtime_error("unreachable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void ElfLinker::relocateSections()
|
void ElfLinker::relocateSections()
|
||||||
{
|
{
|
||||||
auto& sections = myParser.getSections();
|
auto& sections = myParser.getSections();
|
||||||
myRelocatedSections.resize(sections.size(), std::nullopt);
|
myRelocatedSections.resize(sections.size(), std::nullopt);
|
||||||
|
|
||||||
// relocate all .text and .data sections
|
// relocate everything that is not .bss
|
||||||
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_PROGBITS) {
|
const auto segmentType = determineSegmentType(section);
|
||||||
const bool isText = section.name.starts_with(".text");
|
if (!segmentType || section.type == ElfParser::SHT_NOBITS) continue;
|
||||||
uInt32& segmentSize = isText ? myTextSize : myDataSize;
|
|
||||||
|
|
||||||
if (segmentSize % section.align)
|
uInt32& segmentSize = getSegmentSizeRef(*segmentType);
|
||||||
segmentSize = (segmentSize / section.align + 1) * section.align;
|
|
||||||
|
|
||||||
myRelocatedSections[i] = {isText ? SegmentType::text : SegmentType::data, segmentSize};
|
if (segmentSize % section.align)
|
||||||
segmentSize += section.size;
|
segmentSize = (segmentSize / section.align + 1) * section.align;
|
||||||
}
|
|
||||||
|
myRelocatedSections[i] = {*segmentType, segmentSize};
|
||||||
|
segmentSize += section.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// relocate all .bss sections
|
// relocate all .bss sections
|
||||||
|
@ -164,27 +245,37 @@ void ElfLinker::relocateSections()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure that the segments don't overlap
|
// ensure that the segments don't overlap
|
||||||
if (!(myTextBase + myTextSize <= myDataBase || myDataBase + myDataSize <= myTextBase))
|
if (
|
||||||
|
checkSegmentOverlap(myTextBase, myTextSize, myDataBase, myDataSize) ||
|
||||||
|
checkSegmentOverlap(myTextBase, myTextSize, myRodataBase, myRodataSize) ||
|
||||||
|
checkSegmentOverlap(myDataBase, myDataSize, myRodataBase, myRodataSize)
|
||||||
|
)
|
||||||
ElfLinkError::raise("segments overlap");
|
ElfLinkError::raise("segments overlap");
|
||||||
|
|
||||||
// allocate and copy section data
|
// allocate segment data
|
||||||
myTextData = make_unique<uInt8[]>(myTextSize);
|
for (SegmentType segmentType: {SegmentType::text, SegmentType::data, SegmentType::rodata}) {
|
||||||
myDataData = make_unique<uInt8[]>(myDataSize);
|
const uInt32 segmentSize = getSegmentSize(segmentType);
|
||||||
|
if (segmentSize == 0) continue;
|
||||||
|
|
||||||
std::memset(myTextData.get(), 0, myTextSize);
|
auto& segmentData = getSegmentDataRef(segmentType);
|
||||||
std::memset(myDataData.get(), 0, myDataSize);
|
|
||||||
|
|
||||||
|
segmentData = make_unique<uInt8[]>(segmentSize);
|
||||||
|
std::memset(segmentData.get(), 0, segmentSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy segment data
|
||||||
for (size_t i = 0; i < sections.size(); i++) {
|
for (size_t i = 0; i < sections.size(); i++) {
|
||||||
const auto& relocatedSection = myRelocatedSections[i];
|
const auto& relocatedSection = myRelocatedSections[i];
|
||||||
if (!relocatedSection) continue;
|
if (!relocatedSection) continue;
|
||||||
|
|
||||||
const auto& section = sections[i];
|
const auto& section = sections[i];
|
||||||
if (section.type != ElfParser::SHT_PROGBITS) continue;
|
if (section.type == ElfParser::SHT_NOBITS) continue;
|
||||||
|
|
||||||
const bool isText = section.name.starts_with(".text");
|
const auto segmentType = determineSegmentType(section);
|
||||||
|
if (!segmentType) continue;
|
||||||
|
|
||||||
std::memcpy(
|
std::memcpy(
|
||||||
(isText ? myTextData : myDataData).get() + relocatedSection->offset,
|
getSegmentDataRef(*segmentType).get() + relocatedSection->offset,
|
||||||
myParser.getData() + section.offset,
|
myParser.getData() + section.offset,
|
||||||
section.size
|
section.size
|
||||||
);
|
);
|
||||||
|
@ -268,8 +359,7 @@ void ElfLinker::relocateSymbols(const vector<ExternalSymbol>& externalSymbols)
|
||||||
const auto& relocatedSection = myRelocatedSections[symbol.section];
|
const auto& relocatedSection = myRelocatedSections[symbol.section];
|
||||||
if (!relocatedSection) continue;
|
if (!relocatedSection) continue;
|
||||||
|
|
||||||
uInt32 value = relocatedSection->segment == SegmentType::text ? myTextBase : myDataBase;
|
uInt32 value = getSegmentBase(relocatedSection->segment) + relocatedSection->offset;
|
||||||
value += relocatedSection->offset;
|
|
||||||
if (symbol.type != ElfParser::STT_SECTION) value += symbol.value;
|
if (symbol.type != ElfParser::STT_SECTION) value += symbol.value;
|
||||||
|
|
||||||
myRelocatedSymbols[i] = {relocatedSection->segment, value, false};
|
myRelocatedSymbols[i] = {relocatedSection->segment, value, false};
|
||||||
|
@ -327,8 +417,9 @@ void ElfLinker::applyRelocationToSection(const ElfParser::Relocation& relocation
|
||||||
);
|
);
|
||||||
|
|
||||||
uInt8* target =
|
uInt8* target =
|
||||||
(targetSectionRelocated.segment == SegmentType::text ? myTextData : myDataData).get() +
|
getSegmentDataRef(targetSectionRelocated.segment).get() +
|
||||||
targetSectionRelocated.offset + relocation.offset;
|
targetSectionRelocated.offset +
|
||||||
|
relocation.offset;
|
||||||
|
|
||||||
switch (relocation.type) {
|
switch (relocation.type) {
|
||||||
case ElfParser::R_ARM_ABS32:
|
case ElfParser::R_ARM_ABS32:
|
||||||
|
@ -346,8 +437,9 @@ void ElfLinker::applyRelocationToSection(const ElfParser::Relocation& relocation
|
||||||
const uInt32 op = read32(target);
|
const uInt32 op = read32(target);
|
||||||
|
|
||||||
Int32 offset = relocatedSymbol->value + relocation.addend.value_or(elfUtil::decode_B_BL(op)) -
|
Int32 offset = relocatedSymbol->value + relocation.addend.value_or(elfUtil::decode_B_BL(op)) -
|
||||||
(targetSectionRelocated.segment == SegmentType::text ? myTextBase : myDataBase) -
|
getSegmentBase(targetSectionRelocated.segment) -
|
||||||
targetSectionRelocated.offset - relocation.offset - 4;
|
targetSectionRelocated.offset -
|
||||||
|
relocation.offset - 4;
|
||||||
|
|
||||||
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");
|
||||||
|
|
|
@ -57,7 +57,7 @@ class ElfLinker {
|
||||||
const string myReason;
|
const string myReason;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class SegmentType: uInt8 { text, data };
|
enum class SegmentType: uInt8 { text, data, rodata };
|
||||||
|
|
||||||
struct RelocatedSection {
|
struct RelocatedSection {
|
||||||
SegmentType segment;
|
SegmentType segment;
|
||||||
|
@ -76,18 +76,14 @@ class ElfLinker {
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ElfLinker(uInt32 textBase, uInt32 dataBase, const ElfParser& parser);
|
ElfLinker(uInt32 textBase, uInt32 dataBase, uInt32 rodataBase, const ElfParser& parser);
|
||||||
|
|
||||||
ElfLinker& setUndefinedSymbolDefault(uInt32 defaultValue);
|
ElfLinker& setUndefinedSymbolDefault(uInt32 defaultValue);
|
||||||
void link(const vector<ExternalSymbol>& externalSymbols);
|
void link(const vector<ExternalSymbol>& externalSymbols);
|
||||||
|
|
||||||
uInt32 getTextBase() const;
|
uInt32 getSegmentSize(SegmentType type) const;
|
||||||
uInt32 getTextSize() const;
|
const uInt8* getSegmentData(SegmentType type) const;
|
||||||
const uInt8* getTextData() const;
|
uInt32 getSegmentBase(SegmentType type) const;
|
||||||
|
|
||||||
uInt32 getDataBase() const;
|
|
||||||
uInt32 getDataSize() const;
|
|
||||||
const uInt8* getDataData() const;
|
|
||||||
|
|
||||||
const vector<uInt32>& getInitArray() const;
|
const vector<uInt32>& getInitArray() const;
|
||||||
const vector<uInt32>& getPreinitArray() const;
|
const vector<uInt32>& getPreinitArray() const;
|
||||||
|
@ -98,6 +94,9 @@ class ElfLinker {
|
||||||
const vector<std::optional<RelocatedSymbol>>& getRelocatedSymbols() const;
|
const vector<std::optional<RelocatedSymbol>>& getRelocatedSymbols() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
uInt32& getSegmentSizeRef(SegmentType type);
|
||||||
|
unique_ptr<uInt8[]>& getSegmentDataRef(SegmentType type);
|
||||||
|
|
||||||
void relocateSections();
|
void relocateSections();
|
||||||
void relocateInitArrays();
|
void relocateInitArrays();
|
||||||
void relocateSymbols(const vector<ExternalSymbol>& externalSymbols);
|
void relocateSymbols(const vector<ExternalSymbol>& externalSymbols);
|
||||||
|
@ -116,12 +115,15 @@ class ElfLinker {
|
||||||
|
|
||||||
const uInt32 myTextBase{0};
|
const uInt32 myTextBase{0};
|
||||||
const uInt32 myDataBase{0};
|
const uInt32 myDataBase{0};
|
||||||
|
const uInt32 myRodataBase{0};
|
||||||
const ElfParser& myParser;
|
const ElfParser& myParser;
|
||||||
|
|
||||||
uInt32 myTextSize{0};
|
uInt32 myTextSize{0};
|
||||||
uInt32 myDataSize{0};
|
uInt32 myDataSize{0};
|
||||||
|
uInt32 myRodataSize{0};
|
||||||
unique_ptr<uInt8[]> myTextData;
|
unique_ptr<uInt8[]> myTextData;
|
||||||
unique_ptr<uInt8[]> myDataData;
|
unique_ptr<uInt8[]> myDataData;
|
||||||
|
unique_ptr<uInt8[]> myRodataData;
|
||||||
|
|
||||||
vector<optional<RelocatedSection>> myRelocatedSections;
|
vector<optional<RelocatedSection>> myRelocatedSections;
|
||||||
vector<optional<RelocatedSymbol>> myRelocatedSymbols;
|
vector<optional<RelocatedSymbol>> myRelocatedSymbols;
|
||||||
|
|
Loading…
Reference in New Issue