1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 10:42:36 +01:00

Added ELF32 little endian support for PSP ELF files.

This commit is contained in:
Hykem 2013-10-28 21:58:03 +00:00
parent f1b420eb3b
commit 198d0a2fc0
4 changed files with 128 additions and 7 deletions

View File

@ -1,6 +1,8 @@
#include "stdafx.h" #include "stdafx.h"
#include "ELF32.h" #include "ELF32.h"
bool isLittleEndian;
ELF32Loader::ELF32Loader(vfsStream& f) ELF32Loader::ELF32Loader(vfsStream& f)
: elf32_f(f) : elf32_f(f)
, LoaderBase() , LoaderBase()
@ -36,13 +38,21 @@ bool ELF32Loader::Close()
bool ELF32Loader::LoadEhdrInfo() bool ELF32Loader::LoadEhdrInfo()
{ {
u8 endian;
elf32_f.Seek(5);
elf32_f.Read(&endian, 1);
isLittleEndian = (endian == 0x1);
elf32_f.Reset();
elf32_f.Seek(0); elf32_f.Seek(0);
ehdr.Load(elf32_f); if (isLittleEndian) ehdr.LoadLE(elf32_f);
else ehdr.Load(elf32_f);
if(!ehdr.CheckMagic()) return false; if(!ehdr.CheckMagic()) return false;
switch(ehdr.e_machine) switch(ehdr.e_machine)
{ {
case MACHINE_MIPS:
case MACHINE_PPC64: case MACHINE_PPC64:
case MACHINE_SPU: case MACHINE_SPU:
machine = (Elf_Machine)ehdr.e_machine; machine = (Elf_Machine)ehdr.e_machine;
@ -76,7 +86,8 @@ bool ELF32Loader::LoadPhdrInfo()
for(uint i=0; i<ehdr.e_phnum; ++i) for(uint i=0; i<ehdr.e_phnum; ++i)
{ {
Elf32_Phdr* phdr = new Elf32_Phdr(); Elf32_Phdr* phdr = new Elf32_Phdr();
phdr->Load(elf32_f); if(isLittleEndian) phdr->LoadLE(elf32_f);
else phdr->Load(elf32_f);
phdr_arr.Move(phdr); phdr_arr.Move(phdr);
} }
@ -89,13 +100,14 @@ bool ELF32Loader::LoadShdrInfo()
for(u32 i=0; i<ehdr.e_shnum; ++i) for(u32 i=0; i<ehdr.e_shnum; ++i)
{ {
Elf32_Shdr* shdr = new Elf32_Shdr(); Elf32_Shdr* shdr = new Elf32_Shdr();
shdr->Load(elf32_f); if(isLittleEndian) shdr->LoadLE(elf32_f);
else shdr->Load(elf32_f);
shdr_arr.Move(shdr); shdr_arr.Move(shdr);
} }
if(ehdr.e_shstrndx >= shdr_arr.GetCount()) if(ehdr.e_shstrndx >= shdr_arr.GetCount())
{ {
ConLog.Error("LoadShdr64 error: shstrndx too big!"); ConLog.Error("LoadShdr32 error: shstrndx too big!");
return false; return false;
} }
@ -110,8 +122,7 @@ bool ELF32Loader::LoadShdrInfo()
if(c == 0) break; if(c == 0) break;
name += c; name += c;
} }
shdr_name_arr.Add(name);
shdr_name_arr.Add(name);
} }
return true; return true;
@ -162,7 +173,8 @@ bool ELF32Loader::LoadPhdrData(u64 offset)
{ {
elf32_f.Seek(phdr_arr[i].p_offset); elf32_f.Seek(phdr_arr[i].p_offset);
Elf32_Note note; Elf32_Note note;
note.Load(elf32_f); if(isLittleEndian) note.LoadLE(elf32_f);
else note.Load(elf32_f);
if(note.type != 1) if(note.type != 1)
{ {

View File

@ -71,6 +71,29 @@ struct Elf32_Ehdr
e_shstrndx = Read16(f); e_shstrndx = Read16(f);
} }
void LoadLE(vfsStream& f)
{
e_magic = Read32(f);
e_class = Read8(f);
e_data = Read8(f);
e_curver = Read8(f);
e_os_abi = Read8(f);
e_abi_ver = Read64LE(f);
e_type = Read16LE(f);
e_machine = Read16LE(f);
e_version = Read32LE(f);
e_entry = Read32LE(f);
e_phoff = Read32LE(f);
e_shoff = Read32LE(f);
e_flags = Read32LE(f);
e_ehsize = Read16LE(f);
e_phentsize = Read16LE(f);
e_phnum = Read16LE(f);
e_shentsize = Read16LE(f);
e_shnum = Read16LE(f);
e_shstrndx = Read16LE(f);
}
bool CheckMagic() const { return e_magic == 0x7F454C46; } bool CheckMagic() const { return e_magic == 0x7F454C46; }
u32 GetEntry() const { return e_entry; } u32 GetEntry() const { return e_entry; }
}; };
@ -89,6 +112,14 @@ struct Elf32_Desc
stack_size = Read32(f); stack_size = Read32(f);
flags = Read32(f); flags = Read32(f);
} }
void LoadLE(vfsStream& f)
{
revision = Read32LE(f);
ls_size = Read32LE(f);
stack_size = Read32LE(f);
flags = Read32LE(f);
}
}; };
struct Elf32_Note struct Elf32_Note
@ -119,6 +150,23 @@ struct Elf32_Note
desc.Load(f); desc.Load(f);
} }
} }
void LoadLE(vfsStream& f)
{
namesz = Read32LE(f);
descsz = Read32LE(f);
type = Read32LE(f);
f.Read(name, 8);
if(descsz == 32)
{
f.Read(desc_text, descsz);
}
else
{
desc.Load(f);
}
}
}; };
struct Elf32_Shdr struct Elf32_Shdr
@ -148,6 +196,20 @@ struct Elf32_Shdr
sh_entsize = Read32(f); sh_entsize = Read32(f);
} }
void LoadLE(vfsStream& f)
{
sh_name = Read32LE(f);
sh_type = Read32LE(f);
sh_flags = Read32LE(f);
sh_addr = Read32LE(f);
sh_offset = Read32LE(f);
sh_size = Read32LE(f);
sh_link = Read32LE(f);
sh_info = Read32LE(f);
sh_addralign = Read32LE(f);
sh_entsize = Read32LE(f);
}
void Show() void Show()
{ {
#ifdef LOADER_DEBUG #ifdef LOADER_DEBUG
@ -188,6 +250,18 @@ struct Elf32_Phdr
p_align = Read32(f); p_align = Read32(f);
} }
void LoadLE(vfsStream& f)
{
p_type = Read32LE(f);
p_offset = Read32LE(f);
p_vaddr = Read32LE(f);
p_paddr = Read32LE(f);
p_filesz = Read32LE(f);
p_memsz = Read32LE(f);
p_flags = Read32LE(f);
p_align = Read32LE(f);
}
void Show() void Show()
{ {
#ifdef LOADER_DEBUG #ifdef LOADER_DEBUG

View File

@ -39,6 +39,7 @@ const wxString Ehdr_MachineToString(const u16 machine)
{ {
switch(machine) switch(machine)
{ {
case MACHINE_MIPS: return "MIPS";
case MACHINE_PPC64: return "PowerPC64"; case MACHINE_PPC64: return "PowerPC64";
case MACHINE_SPU: return "SPU"; case MACHINE_SPU: return "SPU";
}; };

View File

@ -8,6 +8,7 @@
enum Elf_Machine enum Elf_Machine
{ {
MACHINE_Unknown, MACHINE_Unknown,
MACHINE_MIPS = 0x08,
MACHINE_PPC64 = 0x15, MACHINE_PPC64 = 0x15,
MACHINE_SPU = 0x17, MACHINE_SPU = 0x17,
}; };
@ -58,6 +59,21 @@ __forceinline static u64 Read64(vfsStream& f)
return ((u64)Read32(f) << 32) | (u64)Read32(f); return ((u64)Read32(f) << 32) | (u64)Read32(f);
} }
__forceinline static u16 Read16LE(vfsStream& f)
{
return ((u16)Read8(f) | ((u16)Read8(f) << 8));
}
__forceinline static u32 Read32LE(vfsStream& f)
{
return Read16LE(f) | (Read16LE(f) << 16);
}
__forceinline static u64 Read64LE(vfsStream& f)
{
return ((u64)Read32LE(f) | (u64)Read32LE(f) << 32);
}
__forceinline static void Write8(wxFile& f, const u8 data) __forceinline static void Write8(wxFile& f, const u8 data)
{ {
f.Write(&data, 1); f.Write(&data, 1);
@ -81,6 +97,24 @@ __forceinline static void Write64(wxFile& f, const u64 data)
Write32(f, data); Write32(f, data);
} }
__forceinline static void Write16LE(wxFile& f, const u16 data)
{
Write8(f, data);
Write8(f, data >> 8);
}
__forceinline static void Write32LE(wxFile& f, const u32 data)
{
Write16(f, data);
Write16(f, data >> 16);
}
__forceinline static void Write64LE(wxFile& f, const u64 data)
{
Write32(f, data);
Write32(f, data >> 32);
}
const wxString Ehdr_DataToString(const u8 data); const wxString Ehdr_DataToString(const u8 data);
const wxString Ehdr_TypeToString(const u16 type); const wxString Ehdr_TypeToString(const u16 type);