Implemented classic segment relocations
This commit is contained in:
parent
70045f2b38
commit
a7af13b523
2 changed files with 131 additions and 114 deletions
|
@ -50,6 +50,118 @@ void addrToHiLo(u32 addr, u16 &hi, s16 &lo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ElfReader::LoadRelocations(Elf32_Rel *rels, int numRelocs)
|
||||||
|
{
|
||||||
|
for (int r = 0; r < numRelocs; r++)
|
||||||
|
{
|
||||||
|
u32 info = rels[r].r_info;
|
||||||
|
u32 addr = rels[r].r_offset;
|
||||||
|
|
||||||
|
int type = info & 0xf;
|
||||||
|
|
||||||
|
int readwrite = (info>>8) & 0xff;
|
||||||
|
int relative = (info>>16) & 0xff;
|
||||||
|
|
||||||
|
//0 = code
|
||||||
|
//1 = data
|
||||||
|
|
||||||
|
addr += segmentVAddr[readwrite];
|
||||||
|
|
||||||
|
u32 op = Memory::ReadUnchecked_U32(addr);
|
||||||
|
|
||||||
|
const bool log = false;
|
||||||
|
//log=true;
|
||||||
|
if (log)
|
||||||
|
{
|
||||||
|
DEBUG_LOG(LOADER,"rel at: %08x type: %08x",addr,info);
|
||||||
|
}
|
||||||
|
u32 relocateTo = segmentVAddr[relative];
|
||||||
|
|
||||||
|
#define R_MIPS32 2
|
||||||
|
#define R_MIPS26 4
|
||||||
|
#define R_MIPS16_HI 5
|
||||||
|
#define R_MIPS16_LO 6
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case R_MIPS32:
|
||||||
|
if (log)
|
||||||
|
DEBUG_LOG(LOADER,"Full address reloc %08x", addr);
|
||||||
|
//full address, no problemo
|
||||||
|
op += relocateTo;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case R_MIPS26: //j, jal
|
||||||
|
//add on to put in correct address space
|
||||||
|
if (log)
|
||||||
|
DEBUG_LOG(LOADER,"j/jal reloc %08x", addr);
|
||||||
|
op = (op & 0xFC000000) | (((op&0x03FFFFFF)+(relocateTo>>2))&0x03FFFFFFF);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case R_MIPS16_HI: //lui part of lui-addiu pairs
|
||||||
|
{
|
||||||
|
if (log)
|
||||||
|
DEBUG_LOG(LOADER,"HI reloc %08x", addr);
|
||||||
|
|
||||||
|
u32 cur = (op & 0xFFFF) << 16;
|
||||||
|
u16 hi = 0;
|
||||||
|
bool found = false;
|
||||||
|
for (int t = r + 1; t<numRelocs; t++)
|
||||||
|
{
|
||||||
|
if ((rels[t].r_info & 0xF) == R_MIPS16_LO)
|
||||||
|
{
|
||||||
|
u32 corrLoAddr = rels[t].r_offset + segmentVAddr[readwrite];
|
||||||
|
if (log)
|
||||||
|
{
|
||||||
|
DEBUG_LOG(LOADER,"Corresponding lo found at %08x", corrLoAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
s16 lo = (s32)(s16)(u16)(Memory::ReadUnchecked_U32(corrLoAddr) & 0xFFFF); //signed??
|
||||||
|
cur += lo;
|
||||||
|
cur += relocateTo;
|
||||||
|
addrToHiLo(cur, hi, lo);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
ERROR_LOG(LOADER, "R_MIPS16: not found");
|
||||||
|
|
||||||
|
op = (op & 0xFFFF0000) | (hi);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case R_MIPS16_LO: //addiu part of lui-addiu pairs
|
||||||
|
{
|
||||||
|
if (log)
|
||||||
|
DEBUG_LOG(LOADER,"LO reloc %08x", addr);
|
||||||
|
u32 cur = op & 0xFFFF;
|
||||||
|
cur += relocateTo;
|
||||||
|
cur &= 0xFFFF;
|
||||||
|
op = (op & 0xFFFF0000) | cur;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7: //gp
|
||||||
|
if (log)
|
||||||
|
ERROR_LOG(LOADER,"ARGH IT'S A GP!!!!!!!! %08x", addr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0: // another GP reloc!
|
||||||
|
{
|
||||||
|
char temp[256];
|
||||||
|
MIPSDisAsm(op, 0, temp);
|
||||||
|
ERROR_LOG(LOADER,"WARNING: GP reloc? @ %08x : 0 : %s", addr, temp );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ERROR_LOG(LOADER,"ARGH IT'S A UNKNOWN RELOCATION!!!!!!!! %08x", addr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Memory::Write_U32(op, addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool ElfReader::LoadInto(u32 loadAddress)
|
bool ElfReader::LoadInto(u32 loadAddress)
|
||||||
{
|
{
|
||||||
|
@ -109,9 +221,8 @@ bool ElfReader::LoadInto(u32 loadAddress)
|
||||||
DEBUG_LOG(LOADER,"%i segments:", header->e_phnum);
|
DEBUG_LOG(LOADER,"%i segments:", header->e_phnum);
|
||||||
|
|
||||||
// First pass : Get the damn bits into RAM
|
// First pass : Get the damn bits into RAM
|
||||||
u32 segmentVAddr[32];
|
|
||||||
|
|
||||||
u32 baseAddress = bRelocate?vaddr:0;
|
u32 baseAddress = bRelocate?vaddr:0;
|
||||||
|
|
||||||
for (int i=0; i<header->e_phnum; i++)
|
for (int i=0; i<header->e_phnum; i++)
|
||||||
{
|
{
|
||||||
Elf32_Phdr *p = segments + i;
|
Elf32_Phdr *p = segments + i;
|
||||||
|
@ -170,7 +281,6 @@ bool ElfReader::LoadInto(u32 loadAddress)
|
||||||
if (s->sh_type == SHT_PSPREL)
|
if (s->sh_type == SHT_PSPREL)
|
||||||
{
|
{
|
||||||
//We have a relocation table!
|
//We have a relocation table!
|
||||||
int symbolSection = s->sh_link;
|
|
||||||
int sectionToModify = s->sh_info;
|
int sectionToModify = s->sh_info;
|
||||||
|
|
||||||
if (!(sections[sectionToModify].sh_flags & SHF_ALLOC))
|
if (!(sections[sectionToModify].sh_flags & SHF_ALLOC))
|
||||||
|
@ -184,116 +294,7 @@ bool ElfReader::LoadInto(u32 loadAddress)
|
||||||
Elf32_Rel *rels = (Elf32_Rel *)GetSectionDataPtr(i);
|
Elf32_Rel *rels = (Elf32_Rel *)GetSectionDataPtr(i);
|
||||||
|
|
||||||
DEBUG_LOG(LOADER,"%s: Performing %i relocations on %s",name,numRelocs,GetSectionName(sectionToModify));
|
DEBUG_LOG(LOADER,"%s: Performing %i relocations on %s",name,numRelocs,GetSectionName(sectionToModify));
|
||||||
|
LoadRelocations(rels, numRelocs);
|
||||||
for (int r = 0; r < numRelocs; r++)
|
|
||||||
{
|
|
||||||
u32 info = rels[r].r_info;
|
|
||||||
u32 addr = rels[r].r_offset;
|
|
||||||
|
|
||||||
int type = info & 0xf;
|
|
||||||
|
|
||||||
int readwrite = (info>>8) & 0xff;
|
|
||||||
int relative = (info>>16) & 0xff;
|
|
||||||
|
|
||||||
//0 = code
|
|
||||||
//1 = data
|
|
||||||
|
|
||||||
addr += segmentVAddr[readwrite];
|
|
||||||
|
|
||||||
u32 op = Memory::ReadUnchecked_U32(addr);
|
|
||||||
|
|
||||||
const bool log = false;
|
|
||||||
//log=true;
|
|
||||||
if (log)
|
|
||||||
{
|
|
||||||
DEBUG_LOG(LOADER,"rel at: %08x type: %08x",addr,info);
|
|
||||||
}
|
|
||||||
u32 relocateTo = segmentVAddr[relative];
|
|
||||||
|
|
||||||
#define R_MIPS32 2
|
|
||||||
#define R_MIPS26 4
|
|
||||||
#define R_MIPS16_HI 5
|
|
||||||
#define R_MIPS16_LO 6
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case R_MIPS32:
|
|
||||||
if (log)
|
|
||||||
DEBUG_LOG(LOADER,"Full address reloc %08x", addr);
|
|
||||||
//full address, no problemo
|
|
||||||
op += relocateTo;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_MIPS26: //j, jal
|
|
||||||
//add on to put in correct address space
|
|
||||||
if (log)
|
|
||||||
DEBUG_LOG(LOADER,"j/jal reloc %08x", addr);
|
|
||||||
op = (op & 0xFC000000) | (((op&0x03FFFFFF)+(relocateTo>>2))&0x03FFFFFFF);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_MIPS16_HI: //lui part of lui-addiu pairs
|
|
||||||
{
|
|
||||||
if (log)
|
|
||||||
DEBUG_LOG(LOADER,"HI reloc %08x", addr);
|
|
||||||
|
|
||||||
u32 cur = (op & 0xFFFF) << 16;
|
|
||||||
u16 hi = 0;
|
|
||||||
bool found = false;
|
|
||||||
for (int t = r + 1; t<numRelocs; t++)
|
|
||||||
{
|
|
||||||
if ((rels[t].r_info & 0xF) == R_MIPS16_LO)
|
|
||||||
{
|
|
||||||
u32 corrLoAddr = rels[t].r_offset + segmentVAddr[readwrite];
|
|
||||||
if (log)
|
|
||||||
{
|
|
||||||
DEBUG_LOG(LOADER,"Corresponding lo found at %08x", corrLoAddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
s16 lo = (s32)(s16)(u16)(Memory::ReadUnchecked_U32(corrLoAddr) & 0xFFFF); //signed??
|
|
||||||
cur += lo;
|
|
||||||
cur += relocateTo;
|
|
||||||
addrToHiLo(cur, hi, lo);
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found)
|
|
||||||
ERROR_LOG(LOADER, "R_MIPS16: not found");
|
|
||||||
|
|
||||||
op = (op & 0xFFFF0000) | (hi);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_MIPS16_LO: //addiu part of lui-addiu pairs
|
|
||||||
{
|
|
||||||
if (log)
|
|
||||||
DEBUG_LOG(LOADER,"LO reloc %08x", addr);
|
|
||||||
u32 cur = op & 0xFFFF;
|
|
||||||
cur += relocateTo;
|
|
||||||
cur &= 0xFFFF;
|
|
||||||
op = (op & 0xFFFF0000) | cur;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 7: //gp
|
|
||||||
if (log)
|
|
||||||
ERROR_LOG(LOADER,"ARGH IT'S A GP!!!!!!!! %08x", addr);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0: // another GP reloc!
|
|
||||||
{
|
|
||||||
char temp[256];
|
|
||||||
MIPSDisAsm(op, 0, temp);
|
|
||||||
ERROR_LOG(LOADER,"WARNING: GP reloc? @ %08x : 0 : %s", addr, temp );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
ERROR_LOG(LOADER,"ARGH IT'S A UNKNOWN RELOCATION!!!!!!!! %08x", addr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Memory::Write_U32(op, addr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (s->sh_type == SHT_REL)
|
else if (s->sh_type == SHT_REL)
|
||||||
{
|
{
|
||||||
|
@ -305,7 +306,6 @@ bool ElfReader::LoadInto(u32 loadAddress)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//We have a relocation table!
|
//We have a relocation table!
|
||||||
int symbolSection = s->sh_link;
|
|
||||||
int sectionToModify = s->sh_info;
|
int sectionToModify = s->sh_info;
|
||||||
if (!(sections[sectionToModify].sh_flags & SHF_ALLOC))
|
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.");
|
NOTICE_LOG(LOADER,"ELF loading completed successfully.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ class ElfReader
|
||||||
bool bRelocate;
|
bool bRelocate;
|
||||||
u32 entryPoint;
|
u32 entryPoint;
|
||||||
u32 vaddr;
|
u32 vaddr;
|
||||||
|
u32 segmentVAddr[32];
|
||||||
public:
|
public:
|
||||||
ElfReader(void *ptr)
|
ElfReader(void *ptr)
|
||||||
{
|
{
|
||||||
|
@ -117,4 +118,5 @@ public:
|
||||||
// More indepth stuff:)
|
// More indepth stuff:)
|
||||||
bool LoadInto(u32 vaddr);
|
bool LoadInto(u32 vaddr);
|
||||||
bool LoadSymbols();
|
bool LoadSymbols();
|
||||||
|
void LoadRelocations(Elf32_Rel *rels, int numRelocs);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue