Boot: Unify the ELF and DOL code paths

They're essentially the same. To achieve this, this commit unifies
DolReader and ElfReader into a common interface for boot executable
readers, so the only remaining difference between ELF and DOL is
how which volume is inserted.
This commit is contained in:
Léo Lam
2017-05-28 17:12:38 +02:00
parent 22992ae41e
commit 065261dbad
13 changed files with 195 additions and 233 deletions

View File

@ -66,7 +66,17 @@ static void byteswapSection(Elf32_Shdr& sec)
bswap(sec.sh_type);
}
ElfReader::ElfReader(void* ptr)
ElfReader::ElfReader(const std::vector<u8>& buffer) : BootExecutableReader(buffer)
{
Initialize(m_bytes.data());
}
ElfReader::ElfReader(const std::string& filename) : BootExecutableReader(filename)
{
Initialize(m_bytes.data());
}
void ElfReader::Initialize(u8* ptr)
{
base = (char*)ptr;
base32 = (u32*)ptr;
@ -86,6 +96,8 @@ ElfReader::ElfReader(void* ptr)
byteswapSection(sections[i]);
}
entryPoint = header->e_entry;
bRelocate = (header->e_type != ET_EXEC);
}
const char* ElfReader::GetSectionName(int section) const
@ -103,13 +115,10 @@ const char* ElfReader::GetSectionName(int section) const
}
// This is just a simple elf loader, good enough to load elfs generated by devkitPPC
bool ElfReader::LoadIntoMemory(bool only_in_mem1)
bool ElfReader::LoadIntoMemory(bool only_in_mem1) const
{
INFO_LOG(MASTER_LOG, "String section: %i", header->e_shstrndx);
// Should we relocate?
bRelocate = (header->e_type != ET_EXEC);
if (bRelocate)
{
PanicAlert("Error: Dolphin doesn't know how to load a relocatable elf.");
@ -160,7 +169,7 @@ SectionID ElfReader::GetSectionByName(const char* name, int firstSection) const
return -1;
}
bool ElfReader::LoadSymbols()
bool ElfReader::LoadSymbols() const
{
bool hasSymbols = false;
SectionID sec = GetSectionByName(".symtab");
@ -205,3 +214,31 @@ bool ElfReader::LoadSymbols()
g_symbolDB.Index();
return hasSymbols;
}
bool ElfReader::IsWii() const
{
// Use the same method as the DOL loader uses: search for mfspr from HID4,
// which should only be used in Wii ELFs.
//
// Likely to have some false positives/negatives, patches implementing a
// better heuristic are welcome.
// Swap these once, instead of swapping every word in the file.
u32 HID4_pattern = Common::swap32(0x7c13fba6);
u32 HID4_mask = Common::swap32(0xfc1fffff);
for (int i = 0; i < GetNumSegments(); ++i)
{
if (IsCodeSegment(i))
{
u32* code = (u32*)GetSegmentPtr(i);
for (u32 j = 0; j < GetSegmentSize(i) / sizeof(u32); ++j)
{
if ((code[j] & HID4_mask) == HID4_pattern)
return true;
}
}
}
return false;
}