Implemented classic segment relocations
This commit is contained in:
parent
70045f2b38
commit
a7af13b523
2 changed files with 131 additions and 114 deletions
|
@ -50,141 +50,8 @@ void addrToHiLo(u32 addr, u16 &hi, s16 &lo)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
bool ElfReader::LoadInto(u32 loadAddress)
|
||||
void ElfReader::LoadRelocations(Elf32_Rel *rels, int numRelocs)
|
||||
{
|
||||
DEBUG_LOG(LOADER,"String section: %i", header->e_shstrndx);
|
||||
|
||||
//TODO - Check header->e_ident here
|
||||
//let's dump string section
|
||||
/*
|
||||
char *ptr = (char*)GetSectionDataPtr(header->e_shstrndx);
|
||||
if (*ptr == 0)
|
||||
ptr++;
|
||||
ptr+=513;
|
||||
while (*ptr != 0)
|
||||
{
|
||||
int len = strlen(ptr);
|
||||
LOG(LOADER,"XX %s",ptr);
|
||||
ptr+=len;
|
||||
ptr++;
|
||||
}*/
|
||||
|
||||
sectionOffsets = new u32[GetNumSections()];
|
||||
sectionAddrs = new u32[GetNumSections()];
|
||||
|
||||
// Should we relocate?
|
||||
bRelocate = (header->e_type != ET_EXEC);
|
||||
|
||||
entryPoint = header->e_entry;
|
||||
u32 totalStart = 0xFFFFFFFF;
|
||||
u32 totalEnd = 0;
|
||||
for (int i = 0; i < header->e_phnum; i++) {
|
||||
Elf32_Phdr *p = &segments[i];
|
||||
if (p->p_type == PT_LOAD) {
|
||||
if (p->p_vaddr < totalStart)
|
||||
totalStart = p->p_vaddr;
|
||||
if (p->p_vaddr + p->p_memsz > totalEnd)
|
||||
totalEnd = p->p_vaddr + p->p_memsz;
|
||||
}
|
||||
}
|
||||
u32 totalSize = totalEnd - totalStart;
|
||||
if (loadAddress)
|
||||
vaddr = userMemory.AllocAt(loadAddress, totalSize, "ELF");
|
||||
else
|
||||
vaddr = userMemory.Alloc(totalSize, false, "ELF");
|
||||
|
||||
if (vaddr == -1) {
|
||||
ERROR_LOG(LOADER, "Failed to allocate memory for ELF!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bRelocate) {
|
||||
DEBUG_LOG(LOADER,"Relocatable module");
|
||||
entryPoint += vaddr;
|
||||
} else {
|
||||
DEBUG_LOG(LOADER,"Prerelocated executable");
|
||||
}
|
||||
|
||||
DEBUG_LOG(LOADER,"%i segments:", header->e_phnum);
|
||||
|
||||
// First pass : Get the damn bits into RAM
|
||||
u32 segmentVAddr[32];
|
||||
|
||||
u32 baseAddress = bRelocate?vaddr:0;
|
||||
for (int i=0; i<header->e_phnum; i++)
|
||||
{
|
||||
Elf32_Phdr *p = segments + i;
|
||||
DEBUG_LOG(LOADER, "Type: %i Vaddr: %08x Filesz: %i Memsz: %i ", (int)p->p_type, (u32)p->p_vaddr, (int)p->p_filesz, (int)p->p_memsz);
|
||||
|
||||
if (p->p_type == PT_LOAD)
|
||||
{
|
||||
segmentVAddr[i] = baseAddress + p->p_vaddr;
|
||||
u32 writeAddr = segmentVAddr[i];
|
||||
|
||||
u8 *src = GetSegmentPtr(i);
|
||||
u8 *dst = Memory::GetPointer(writeAddr);
|
||||
u32 srcSize = p->p_filesz;
|
||||
u32 dstSize = p->p_memsz;
|
||||
|
||||
if (srcSize < dstSize)
|
||||
{
|
||||
memset(dst + srcSize, 0, dstSize - srcSize); //zero out bss
|
||||
}
|
||||
|
||||
memcpy(dst, src, srcSize);
|
||||
DEBUG_LOG(LOADER,"Loadable Segment Copied to %08x, size %08x", writeAddr, (u32)p->p_memsz);
|
||||
}
|
||||
}
|
||||
userMemory.ListBlocks();
|
||||
|
||||
DEBUG_LOG(LOADER,"%i sections:", header->e_shnum);
|
||||
|
||||
for (int i = 0; i < GetNumSections(); i++)
|
||||
{
|
||||
Elf32_Shdr *s = §ions[i];
|
||||
const char *name = GetSectionName(i);
|
||||
|
||||
u32 writeAddr = s->sh_addr + baseAddress;
|
||||
sectionOffsets[i] = writeAddr - vaddr;
|
||||
sectionAddrs[i] = writeAddr;
|
||||
|
||||
if (s->sh_flags & SHF_ALLOC)
|
||||
{
|
||||
DEBUG_LOG(LOADER,"Data Section found: %s Sitting at %08x, size %08x", name, writeAddr, (u32)s->sh_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(LOADER,"NonData Section found: %s Ignoring (size=%08x) (flags=%08x)", name, (u32)s->sh_size, (u32)s->sh_flags);
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_LOG(LOADER,"Relocations:");
|
||||
|
||||
// Second pass: Do necessary relocations
|
||||
for (int i=0; i<GetNumSections(); i++)
|
||||
{
|
||||
Elf32_Shdr *s = §ions[i];
|
||||
const char *name = GetSectionName(i);
|
||||
|
||||
if (s->sh_type == SHT_PSPREL)
|
||||
{
|
||||
//We have a relocation table!
|
||||
int symbolSection = s->sh_link;
|
||||
int sectionToModify = s->sh_info;
|
||||
|
||||
if (!(sections[sectionToModify].sh_flags & SHF_ALLOC))
|
||||
{
|
||||
ERROR_LOG(LOADER,"Trying to relocate non-loaded section %s",GetSectionName(sectionToModify));
|
||||
continue;
|
||||
}
|
||||
|
||||
int numRelocs = s->sh_size / sizeof(Elf32_Rel);
|
||||
|
||||
Elf32_Rel *rels = (Elf32_Rel *)GetSectionDataPtr(i);
|
||||
|
||||
DEBUG_LOG(LOADER,"%s: Performing %i relocations on %s",name,numRelocs,GetSectionName(sectionToModify));
|
||||
|
||||
for (int r = 0; r < numRelocs; r++)
|
||||
{
|
||||
u32 info = rels[r].r_info;
|
||||
|
@ -294,6 +161,140 @@ bool ElfReader::LoadInto(u32 loadAddress)
|
|||
}
|
||||
Memory::Write_U32(op, addr);
|
||||
}
|
||||
}
|
||||
|
||||
bool ElfReader::LoadInto(u32 loadAddress)
|
||||
{
|
||||
DEBUG_LOG(LOADER,"String section: %i", header->e_shstrndx);
|
||||
|
||||
//TODO - Check header->e_ident here
|
||||
//let's dump string section
|
||||
/*
|
||||
char *ptr = (char*)GetSectionDataPtr(header->e_shstrndx);
|
||||
if (*ptr == 0)
|
||||
ptr++;
|
||||
ptr+=513;
|
||||
while (*ptr != 0)
|
||||
{
|
||||
int len = strlen(ptr);
|
||||
LOG(LOADER,"XX %s",ptr);
|
||||
ptr+=len;
|
||||
ptr++;
|
||||
}*/
|
||||
|
||||
sectionOffsets = new u32[GetNumSections()];
|
||||
sectionAddrs = new u32[GetNumSections()];
|
||||
|
||||
// Should we relocate?
|
||||
bRelocate = (header->e_type != ET_EXEC);
|
||||
|
||||
entryPoint = header->e_entry;
|
||||
u32 totalStart = 0xFFFFFFFF;
|
||||
u32 totalEnd = 0;
|
||||
for (int i = 0; i < header->e_phnum; i++) {
|
||||
Elf32_Phdr *p = &segments[i];
|
||||
if (p->p_type == PT_LOAD) {
|
||||
if (p->p_vaddr < totalStart)
|
||||
totalStart = p->p_vaddr;
|
||||
if (p->p_vaddr + p->p_memsz > totalEnd)
|
||||
totalEnd = p->p_vaddr + p->p_memsz;
|
||||
}
|
||||
}
|
||||
u32 totalSize = totalEnd - totalStart;
|
||||
if (loadAddress)
|
||||
vaddr = userMemory.AllocAt(loadAddress, totalSize, "ELF");
|
||||
else
|
||||
vaddr = userMemory.Alloc(totalSize, false, "ELF");
|
||||
|
||||
if (vaddr == -1) {
|
||||
ERROR_LOG(LOADER, "Failed to allocate memory for ELF!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bRelocate) {
|
||||
DEBUG_LOG(LOADER,"Relocatable module");
|
||||
entryPoint += vaddr;
|
||||
} else {
|
||||
DEBUG_LOG(LOADER,"Prerelocated executable");
|
||||
}
|
||||
|
||||
DEBUG_LOG(LOADER,"%i segments:", header->e_phnum);
|
||||
|
||||
// First pass : Get the damn bits into RAM
|
||||
u32 baseAddress = bRelocate?vaddr:0;
|
||||
|
||||
for (int i=0; i<header->e_phnum; i++)
|
||||
{
|
||||
Elf32_Phdr *p = segments + i;
|
||||
DEBUG_LOG(LOADER, "Type: %i Vaddr: %08x Filesz: %i Memsz: %i ", (int)p->p_type, (u32)p->p_vaddr, (int)p->p_filesz, (int)p->p_memsz);
|
||||
|
||||
if (p->p_type == PT_LOAD)
|
||||
{
|
||||
segmentVAddr[i] = baseAddress + p->p_vaddr;
|
||||
u32 writeAddr = segmentVAddr[i];
|
||||
|
||||
u8 *src = GetSegmentPtr(i);
|
||||
u8 *dst = Memory::GetPointer(writeAddr);
|
||||
u32 srcSize = p->p_filesz;
|
||||
u32 dstSize = p->p_memsz;
|
||||
|
||||
if (srcSize < dstSize)
|
||||
{
|
||||
memset(dst + srcSize, 0, dstSize - srcSize); //zero out bss
|
||||
}
|
||||
|
||||
memcpy(dst, src, srcSize);
|
||||
DEBUG_LOG(LOADER,"Loadable Segment Copied to %08x, size %08x", writeAddr, (u32)p->p_memsz);
|
||||
}
|
||||
}
|
||||
userMemory.ListBlocks();
|
||||
|
||||
DEBUG_LOG(LOADER,"%i sections:", header->e_shnum);
|
||||
|
||||
for (int i = 0; i < GetNumSections(); i++)
|
||||
{
|
||||
Elf32_Shdr *s = §ions[i];
|
||||
const char *name = GetSectionName(i);
|
||||
|
||||
u32 writeAddr = s->sh_addr + baseAddress;
|
||||
sectionOffsets[i] = writeAddr - vaddr;
|
||||
sectionAddrs[i] = writeAddr;
|
||||
|
||||
if (s->sh_flags & SHF_ALLOC)
|
||||
{
|
||||
DEBUG_LOG(LOADER,"Data Section found: %s Sitting at %08x, size %08x", name, writeAddr, (u32)s->sh_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(LOADER,"NonData Section found: %s Ignoring (size=%08x) (flags=%08x)", name, (u32)s->sh_size, (u32)s->sh_flags);
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_LOG(LOADER,"Relocations:");
|
||||
|
||||
// Second pass: Do necessary relocations
|
||||
for (int i=0; i<GetNumSections(); i++)
|
||||
{
|
||||
Elf32_Shdr *s = §ions[i];
|
||||
const char *name = GetSectionName(i);
|
||||
|
||||
if (s->sh_type == SHT_PSPREL)
|
||||
{
|
||||
//We have a relocation table!
|
||||
int sectionToModify = s->sh_info;
|
||||
|
||||
if (!(sections[sectionToModify].sh_flags & SHF_ALLOC))
|
||||
{
|
||||
ERROR_LOG(LOADER,"Trying to relocate non-loaded section %s",GetSectionName(sectionToModify));
|
||||
continue;
|
||||
}
|
||||
|
||||
int numRelocs = s->sh_size / sizeof(Elf32_Rel);
|
||||
|
||||
Elf32_Rel *rels = (Elf32_Rel *)GetSectionDataPtr(i);
|
||||
|
||||
DEBUG_LOG(LOADER,"%s: Performing %i relocations on %s",name,numRelocs,GetSectionName(sectionToModify));
|
||||
LoadRelocations(rels, numRelocs);
|
||||
}
|
||||
else if (s->sh_type == SHT_REL)
|
||||
{
|
||||
|
@ -305,7 +306,6 @@ bool ElfReader::LoadInto(u32 loadAddress)
|
|||
else
|
||||
{
|
||||
//We have a relocation table!
|
||||
int symbolSection = s->sh_link;
|
||||
int sectionToModify = s->sh_info;
|
||||
if (!(sections[sectionToModify].sh_flags & SHF_ALLOC))
|
||||
{
|
||||
|
@ -317,6 +317,21 @@ bool ElfReader::LoadInto(u32 loadAddress)
|
|||
}
|
||||
}
|
||||
|
||||
// Segment relocations (a few games use them)
|
||||
for (int i=0; i<header->e_phnum; i++)
|
||||
{
|
||||
Elf32_Phdr *p = &segments[i];
|
||||
if (p->p_type == 0x700000A0)
|
||||
{
|
||||
INFO_LOG(LOADER,"Loading segment relocations");
|
||||
|
||||
int numRelocs = p->p_filesz / sizeof(Elf32_Rel);
|
||||
|
||||
Elf32_Rel *rels = (Elf32_Rel *)GetSegmentPtr(i);
|
||||
LoadRelocations(rels, numRelocs);
|
||||
}
|
||||
}
|
||||
|
||||
NOTICE_LOG(LOADER,"ELF loading completed successfully.");
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ class ElfReader
|
|||
bool bRelocate;
|
||||
u32 entryPoint;
|
||||
u32 vaddr;
|
||||
u32 segmentVAddr[32];
|
||||
public:
|
||||
ElfReader(void *ptr)
|
||||
{
|
||||
|
@ -117,4 +118,5 @@ public:
|
|||
// More indepth stuff:)
|
||||
bool LoadInto(u32 vaddr);
|
||||
bool LoadSymbols();
|
||||
void LoadRelocations(Elf32_Rel *rels, int numRelocs);
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue