diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index 74bb8a3112..c6e41fc19f 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -1,6 +1,8 @@ #include "stdafx.h" #include "ELF32.h" +bool isLittleEndian; + ELF32Loader::ELF32Loader(vfsStream& f) : elf32_f(f) , LoaderBase() @@ -36,13 +38,21 @@ bool ELF32Loader::Close() bool ELF32Loader::LoadEhdrInfo() { + u8 endian; + elf32_f.Seek(5); + elf32_f.Read(&endian, 1); + isLittleEndian = (endian == 0x1); + + elf32_f.Reset(); elf32_f.Seek(0); - ehdr.Load(elf32_f); + if (isLittleEndian) ehdr.LoadLE(elf32_f); + else ehdr.Load(elf32_f); if(!ehdr.CheckMagic()) return false; switch(ehdr.e_machine) { + case MACHINE_MIPS: case MACHINE_PPC64: case MACHINE_SPU: machine = (Elf_Machine)ehdr.e_machine; @@ -76,7 +86,8 @@ bool ELF32Loader::LoadPhdrInfo() for(uint i=0; iLoad(elf32_f); + if(isLittleEndian) phdr->LoadLE(elf32_f); + else phdr->Load(elf32_f); phdr_arr.Move(phdr); } @@ -89,13 +100,14 @@ bool ELF32Loader::LoadShdrInfo() for(u32 i=0; iLoad(elf32_f); + if(isLittleEndian) shdr->LoadLE(elf32_f); + else shdr->Load(elf32_f); shdr_arr.Move(shdr); } if(ehdr.e_shstrndx >= shdr_arr.GetCount()) { - ConLog.Error("LoadShdr64 error: shstrndx too big!"); + ConLog.Error("LoadShdr32 error: shstrndx too big!"); return false; } @@ -110,8 +122,7 @@ bool ELF32Loader::LoadShdrInfo() if(c == 0) break; name += c; } - - shdr_name_arr.Add(name); + shdr_name_arr.Add(name); } return true; @@ -162,7 +173,8 @@ bool ELF32Loader::LoadPhdrData(u64 offset) { elf32_f.Seek(phdr_arr[i].p_offset); Elf32_Note note; - note.Load(elf32_f); + if(isLittleEndian) note.LoadLE(elf32_f); + else note.Load(elf32_f); if(note.type != 1) { diff --git a/rpcs3/Loader/ELF32.h b/rpcs3/Loader/ELF32.h index 586d5f4bb9..0a317733d7 100644 --- a/rpcs3/Loader/ELF32.h +++ b/rpcs3/Loader/ELF32.h @@ -71,6 +71,29 @@ struct Elf32_Ehdr 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; } u32 GetEntry() const { return e_entry; } }; @@ -89,6 +112,14 @@ struct Elf32_Desc stack_size = 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 @@ -119,6 +150,23 @@ struct Elf32_Note 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 @@ -148,6 +196,20 @@ struct Elf32_Shdr 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() { #ifdef LOADER_DEBUG @@ -188,6 +250,18 @@ struct Elf32_Phdr 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() { #ifdef LOADER_DEBUG diff --git a/rpcs3/Loader/Loader.cpp b/rpcs3/Loader/Loader.cpp index 929216a9ca..bae0e06a3e 100644 --- a/rpcs3/Loader/Loader.cpp +++ b/rpcs3/Loader/Loader.cpp @@ -39,6 +39,7 @@ const wxString Ehdr_MachineToString(const u16 machine) { switch(machine) { + case MACHINE_MIPS: return "MIPS"; case MACHINE_PPC64: return "PowerPC64"; case MACHINE_SPU: return "SPU"; }; diff --git a/rpcs3/Loader/Loader.h b/rpcs3/Loader/Loader.h index febec7c85c..32c31d3056 100644 --- a/rpcs3/Loader/Loader.h +++ b/rpcs3/Loader/Loader.h @@ -8,6 +8,7 @@ enum Elf_Machine { MACHINE_Unknown, + MACHINE_MIPS = 0x08, MACHINE_PPC64 = 0x15, MACHINE_SPU = 0x17, }; @@ -58,6 +59,21 @@ __forceinline static u64 Read64(vfsStream& 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) { f.Write(&data, 1); @@ -81,6 +97,24 @@ __forceinline static void Write64(wxFile& f, const u64 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_TypeToString(const u16 type);