SELF: More boilerplate code
This commit is contained in:
108
Il2CppInspector.Common/FileFormatReaders/SElfReader.cs
Normal file
108
Il2CppInspector.Common/FileFormatReaders/SElfReader.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
Copyright 2020 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
|
||||
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using NoisyCowStudios.Bin2Object;
|
||||
|
||||
namespace Il2CppInspector
|
||||
{
|
||||
// Sony PlayStation 4 fake signed ELF reader
|
||||
// Not compatible with PlayStation 3, PSP or Vita
|
||||
// References:
|
||||
// http://hitmen.c02.at/files/yapspd/psp_doc/chap26.html
|
||||
// https://www.psdevwiki.com/ps3/SELF_-_SPRX#File_Format
|
||||
// https://www.psdevwiki.com/ps4/SELF_File_Format
|
||||
// https://www.psxhax.com/threads/ps4-self-spkg-file-format-documentation-detailed-for-scene-devs.6636/
|
||||
// https://wiki.henkaku.xyz/vita/images/a/a2/Vita_SDK_specifications.pdf
|
||||
// https://www.psxhax.com/threads/make-fself-gui-for-flat_zs-make_fself-py-script-by-cfwprophet.3494/
|
||||
internal class SElfReader : FileFormatReader<SElfReader>
|
||||
{
|
||||
public SElfReader(Stream stream) : base(stream) { }
|
||||
|
||||
public override string Format => sceData.ProductType == (ulong) SElfExInfoTypes.PTYPE_FAKE? "FSELF" : "SELF";
|
||||
|
||||
public override string Arch => "x64";
|
||||
|
||||
public override int Bits => 64;
|
||||
|
||||
private SElfHeader selfHeader;
|
||||
private SElfEntry[] entries;
|
||||
private SElfSCEData sceData;
|
||||
private elf_header<ulong> elfHeader;
|
||||
private elf_64_phdr[] pht;
|
||||
private elf_64_phdr getProgramHeader(Elf programIndex) => pht.FirstOrDefault(x => x.p_type == (uint) programIndex);
|
||||
|
||||
protected override bool Init() {
|
||||
selfHeader = ReadObject<SElfHeader>();
|
||||
|
||||
// Check for magic bytes
|
||||
if ((SElfConsts) selfHeader.Magic != SElfConsts.Magic)
|
||||
return false;
|
||||
|
||||
if (selfHeader.Endian != 0x1)
|
||||
Endianness = Endianness.Big;
|
||||
|
||||
// Read entries
|
||||
entries = ReadArray<SElfEntry>(selfHeader.NumberOfEntries);
|
||||
|
||||
// We can't deal with encrypted or compressed segments right now
|
||||
if (entries.Any(e => e.HasBlocks && e.IsEncrypted))
|
||||
throw new NotImplementedException("This file contains encrypted segments not currently supported by Il2CppInspector.");
|
||||
|
||||
if (entries.Any(e => e.HasBlocks && e.IsDeflated))
|
||||
throw new NotImplementedException("This file contains compressed segments not currently supported by Il2CppInspector.");
|
||||
|
||||
// Read ELF header
|
||||
// PS4 files as follows:
|
||||
// m_arch = 0x2 (64-bit)
|
||||
// m_endian = 0x1 (little endian)
|
||||
// m_version = 0x1 (ELF version 1)
|
||||
// m_osabi = 0x9 (FreeBSD)
|
||||
// e_type = special type, see psdevwiki documentation; probably 0xFE10 or 0xFE18
|
||||
// e_machine = 0x3E (x86-64)
|
||||
var startOfElf = Position;
|
||||
elfHeader = ReadObject<elf_header<ulong>>();
|
||||
|
||||
// Must be one of these supported binary types
|
||||
if (elfHeader.e_type != (ushort) Elf.ET_EXEC
|
||||
&& elfHeader.e_type != (ushort) SElfETypes.ET_SCE_EXEC
|
||||
&& elfHeader.e_type != (ushort) SElfETypes.ET_SCE_DYNEXEC
|
||||
&& elfHeader.e_type != (ushort) SElfETypes.ET_SCE_DYNAMIC)
|
||||
return false;
|
||||
|
||||
// There are no sections, but read all the program headers
|
||||
// Each segment of type PT_LOAD, PT_SCE_RELRO, PT_SCE_DYNLIBDATA and PT_SCE_COMMENT
|
||||
// generates two SELF entries above - one pointing to the ELF segment and one pointing to a digest.
|
||||
// Only p_vaddr is used for memory mapping; all other fields are ignored.
|
||||
// offset, memsz and filesz are taken from the SELF entries.
|
||||
// The digests are all-zero in FSELF files.
|
||||
// All other ELF segments are ignored completely.
|
||||
pht = ReadArray<elf_64_phdr>(startOfElf + (long) elfHeader.e_phoff, elfHeader.e_phnum);
|
||||
|
||||
// Read extended info
|
||||
sceData = ReadObject<SElfSCEData>(startOfElf + (long) elfHeader.e_phoff + elfHeader.e_phentsize * elfHeader.e_phnum);
|
||||
|
||||
// TODO: Implement the rest of FSELF
|
||||
// TODO: Set GlobalOffset
|
||||
|
||||
throw new NotImplementedException("Il2CppInspector does not have PRX support yet");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Only the DT_INIT function equivalent
|
||||
public override uint[] GetFunctionTable() => new [] { MapVATR(elfHeader.e_entry) };
|
||||
|
||||
public override uint MapVATR(ulong uiAddr) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user