Improved Orbis SELF loader

This commit is contained in:
Alexandro Sánchez Bach 2016-08-27 15:04:49 +02:00
parent 2065e95510
commit 201a78c381
8 changed files with 158 additions and 35 deletions

View file

@ -75,13 +75,13 @@ bool Emulator::load_ps4(const std::string& path) {
return false;
}
self.load();
void* entryBase = self.load();
if (self.getMachine() != sys::EM_X86_64) {
logger.error(LOG_COMMON, "Only PPC64 executables are allowed");
return false;
}
auto entry = self.getEntry();
auto entry = reinterpret_cast<uintptr_t>(entryBase) + self.getEntry();
static_cast<sys::OrbisOS*>(sys.get())->init(entry);
return true;
}

View file

@ -28,11 +28,11 @@ bool isValid(fs::File* file) {
Elf64_Ehdr<LE> eh;
file->seek(0, fs::SeekSet);
file->read(&eh, sizeof(eh));
return eh.elf_class == ELFCLASS64 &&
eh.data == ELFDATA2LSB &&
eh.abi_ver == ELFOSABI_FREEBSD &&
eh.machine == EM_X86_64 &&
eh.type == ET_SCE_EXEC;
return (eh.elf_class == ELFCLASS64) &&
(eh.abi_ver == ELFOSABI_FREEBSD || eh.abi_ver == ELFOSABI_NONE) &&
(eh.type == ET_SCE_EXEC || eh.type == ET_SCE_UNKFE10) &&
(eh.data == ELFDATA2LSB) &&
(eh.machine == EM_X86_64);
}
return false;
}

View file

@ -31,20 +31,20 @@ bool SELFLoader::open(fs::File* file) {
}
}
bool SELFLoader::load() {
void* SELFLoader::load() {
assert_true(!elf.empty(), "No ELF/SELF file has been opened");
const auto& eh = (Ehdr&)elf[0];
//
// Get ELF size
Size low = ~0ULL;
Size high = 0ULL;
for (Size i = 0; i < eh.phnum; i++) {
const auto& ph = (Phdr&)elf[eh.phoff + i*sizeof(Phdr)];
low = std::min(low, Size(ph.vaddr));
high = std::min(high, Size(ph.vaddr + ph.memsz));
high = std::max(high, Size(ph.vaddr + ph.memsz));
}
Size size = high - low;
/*void* elf_addr = _aligned_malloc(size, 0x4000);
void* elf_addr = malloc(size);
// Loading program header table
for (U64 i = 0; i < eh.phnum; i++) {
@ -55,7 +55,7 @@ bool SELFLoader::load() {
if (!ph.memsz) {
break;
}
void* vaddr = reinterpret_cast<void*>(ph.vaddr - reinterpret_cast<uintptr_t>(elf_addr));
void* vaddr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(elf_addr) + ph.vaddr);
memcpy(vaddr, &elf[ph.offset], ph.filesz);
if (ph.flags & PF_X) {
@ -68,6 +68,7 @@ bool SELFLoader::load() {
case PT_TLS:
case PT_SCE_DYNLIBDATA:
case PT_SCE_PROCPARAM:
case PT_SCE_UNK61000010:
case PT_GNU_EH_FRAME:
case PT_SCE_COMMENT:
case PT_SCE_LIBVERSION:
@ -77,8 +78,8 @@ bool SELFLoader::load() {
default:
assert_always("Unexpected segment type");
}
}*/
return true;
}
return elf_addr;
}
U16 SELFLoader::getMachine() {

View file

@ -21,6 +21,7 @@ enum {
ET_SCE_EXEC = 0xFE00, // SCE Executable file
ET_SCE_RELEXEC = 0xFE04, // SCE Relocatable file
ET_SCE_STUBLIB = 0xFE0C, // SCE SDK Stubs
ET_SCE_UNKFE10 = 0xFE10, // Unknown (Probably PS4 Executable file with ASLR)
ET_SCE_DYNAMIC = 0xFE18,
};
@ -30,6 +31,7 @@ enum {
PT_SCE_RELA = 0x60000000,
PT_SCE_DYNLIBDATA = 0x61000000,
PT_SCE_PROCPARAM = 0x61000001,
PT_SCE_UNK61000010 = 0x61000010,
PT_SCE_COMMENT = 0x6FFFFF00,
PT_SCE_LIBVERSION = 0x6FFFFF01,
PT_SCE_PSPRELA = 0x700000A0,
@ -52,7 +54,7 @@ class SELFLoader {
public:
bool open(fs::File* file);
bool load();
void* load();
void close();
U16 getMachine();

View file

@ -7,6 +7,8 @@
#include "syscalls/orbis_dynlib.h"
#define SYSCALL(name) { #name }
namespace sys {
namespace scei {
namespace orbis {
@ -278,7 +280,7 @@ OrbisOS::OrbisOS() {
//syscalls[0x24F] = SYSCALL(sys_dynlib_dlsym);
//syscalls[0x250] = SYSCALL(sys_dynlib_get_list);
//syscalls[0x251] = SYSCALL(sys_dynlib_get_info);
//syscalls[0x252] = SYSCALL(sys_dynlib_load_prx);
syscalls[0x252] = SYSCALL(sys_dynlib_load_prx);
//syscalls[0x253] = SYSCALL(sys_dynlib_unload_prx);
//syscalls[0x254] = SYSCALL(sys_dynlib_do_copy_relocations);
//syscalls[0x255] = SYSCALL(sys_dynlib_prepare_dlclose);
@ -304,13 +306,11 @@ OrbisOS::OrbisOS() {
}
bool OrbisOS::init(U64 entry) {
// TODO: Load /system/common/lib/libkernel.sprx
// TODO: Run libkernel.sprx start function
// TODO: Jump to executable entry point
return true;
// Load libkernel.sprx and run its start function, which will load
// the remaining modules and jump to the executable entry point
dynlib_load_prx_args args = {};
args.path = "/system/common/lib/libkernel.sprx";
return !sys_dynlib_load_prx(nullptr, &args);
}
} // namespace orbis

View file

@ -13,11 +13,117 @@ namespace sys {
namespace scei {
namespace orbis {
// Orbis Return Codes
enum {
SCE_OK = 0x00000000,
SCE_KERNEL_ERROR_UNKNOWN = 0x80020000,
SCE_KERNEL_ERROR_EPERM = 0x80020001,
SCE_KERNEL_ERROR_ENOENT = 0x80020002,
SCE_KERNEL_ERROR_ESRCH = 0x80020003,
SCE_KERNEL_ERROR_EINTR = 0x80020004,
SCE_KERNEL_ERROR_EIO = 0x80020005,
SCE_KERNEL_ERROR_ENXIO = 0x80020006,
SCE_KERNEL_ERROR_E2BIG = 0x80020007,
SCE_KERNEL_ERROR_ENOEXEC = 0x80020008,
SCE_KERNEL_ERROR_EBADF = 0x80020009,
SCE_KERNEL_ERROR_ECHILD = 0x8002000A,
SCE_KERNEL_ERROR_EDEADLK = 0x8002000B,
SCE_KERNEL_ERROR_ENOMEM = 0x8002000C,
SCE_KERNEL_ERROR_EACCES = 0x8002000D,
SCE_KERNEL_ERROR_EFAULT = 0x8002000E,
SCE_KERNEL_ERROR_ENOTBLK = 0x8002000F,
SCE_KERNEL_ERROR_EBUSY = 0x80020010,
SCE_KERNEL_ERROR_EEXIST = 0x80020011,
SCE_KERNEL_ERROR_EXDEV = 0x80020012,
SCE_KERNEL_ERROR_ENODEV = 0x80020013,
SCE_KERNEL_ERROR_ENOTDIR = 0x80020014,
SCE_KERNEL_ERROR_EISDIR = 0x80020015,
SCE_KERNEL_ERROR_EINVAL = 0x80020016,
SCE_KERNEL_ERROR_ENFILE = 0x80020017,
SCE_KERNEL_ERROR_EMFILE = 0x80020018,
SCE_KERNEL_ERROR_ENOTTY = 0x80020019,
SCE_KERNEL_ERROR_ETXTBSY = 0x8002001A,
SCE_KERNEL_ERROR_EFBIG = 0x8002001B,
SCE_KERNEL_ERROR_ENOSPC = 0x8002001C,
SCE_KERNEL_ERROR_ESPIPE = 0x8002001D,
SCE_KERNEL_ERROR_EROFS = 0x8002001E,
SCE_KERNEL_ERROR_EMLINK = 0x8002001F,
SCE_KERNEL_ERROR_EPIPE = 0x80020020,
SCE_KERNEL_ERROR_EDOM = 0x80020021,
SCE_KERNEL_ERROR_ERANGE = 0x80020022,
SCE_KERNEL_ERROR_EWOULDBLOCK = 0x80020023,
SCE_KERNEL_ERROR_EINPROGRESS = 0x80020024,
SCE_KERNEL_ERROR_EALREADY = 0x80020025,
SCE_KERNEL_ERROR_ENOTSOCK = 0x80020026,
SCE_KERNEL_ERROR_EDESTADDRREQ = 0x80020027,
SCE_KERNEL_ERROR_EMSGSIZE = 0x80020028,
SCE_KERNEL_ERROR_EPROTOTYPE = 0x80020029,
SCE_KERNEL_ERROR_ENOPROTOOPT = 0x8002002A,
SCE_KERNEL_ERROR_EPROTONOSUPPORT = 0x8002002B,
SCE_KERNEL_ERROR_ESOCKTNOSUPPORT = 0x8002002C,
SCE_KERNEL_ERROR_EOPNOTSUPP = 0x8002002D,
SCE_KERNEL_ERROR_EPFNOSUPPORT = 0x8002002E,
SCE_KERNEL_ERROR_EAFNOSUPPORT = 0x8002002F,
SCE_KERNEL_ERROR_EADDRINUSE = 0x80020030,
SCE_KERNEL_ERROR_EADDRNOTAVAIL = 0x80020031,
SCE_KERNEL_ERROR_ENETDOWN = 0x80020032,
SCE_KERNEL_ERROR_ENETUNREACH = 0x80020033,
SCE_KERNEL_ERROR_ENETRESET = 0x80020034,
SCE_KERNEL_ERROR_ECONNABORTED = 0x80020035,
SCE_KERNEL_ERROR_ECONNRESET = 0x80020036,
SCE_KERNEL_ERROR_ENOBUFS = 0x80020037,
SCE_KERNEL_ERROR_EISCONN = 0x80020038,
SCE_KERNEL_ERROR_ENOTCONN = 0x80020039,
SCE_KERNEL_ERROR_ESHUTDOWN = 0x8002003A,
SCE_KERNEL_ERROR_ETOOMANYREFS = 0x8002003B,
SCE_KERNEL_ERROR_ETIMEDOUT = 0x8002003C,
SCE_KERNEL_ERROR_ECONNREFUSED = 0x8002003D,
SCE_KERNEL_ERROR_ELOOP = 0x8002003E,
SCE_KERNEL_ERROR_ENAMETOOLONG = 0x8002003F,
SCE_KERNEL_ERROR_EHOSTDOWN = 0x80020040,
SCE_KERNEL_ERROR_EHOSTUNREACH = 0x80020041,
SCE_KERNEL_ERROR_ENOTEMPTY = 0x80020042,
SCE_KERNEL_ERROR_EPROCLIM = 0x80020043,
SCE_KERNEL_ERROR_EUSERS = 0x80020044,
SCE_KERNEL_ERROR_EDQUOT = 0x80020045,
SCE_KERNEL_ERROR_ESTALE = 0x80020046,
SCE_KERNEL_ERROR_EREMOTE = 0x80020047,
SCE_KERNEL_ERROR_EBADRPC = 0x80020048,
SCE_KERNEL_ERROR_ERPCMISMATCH = 0x80020049,
SCE_KERNEL_ERROR_EPROGUNAVAIL = 0x8002004A,
SCE_KERNEL_ERROR_EPROGMISMATCH = 0x8002004B,
SCE_KERNEL_ERROR_EPROCUNAVAIL = 0x8002004C,
SCE_KERNEL_ERROR_ENOLCK = 0x8002004D,
SCE_KERNEL_ERROR_ENOSYS = 0x8002004E,
SCE_KERNEL_ERROR_EFTYPE = 0x8002004F,
SCE_KERNEL_ERROR_EAUTH = 0x80020050,
SCE_KERNEL_ERROR_ENEEDAUTH = 0x80020051,
SCE_KERNEL_ERROR_EIDRM = 0x80020052,
SCE_KERNEL_ERROR_ENOMSG = 0x80020053,
SCE_KERNEL_ERROR_EOVERFLOW = 0x80020054,
SCE_KERNEL_ERROR_ECANCELED = 0x80020055,
SCE_KERNEL_ERROR_EILSEQ = 0x80020056,
SCE_KERNEL_ERROR_ENOATTR = 0x80020057,
SCE_KERNEL_ERROR_EDOOFUS = 0x80020058,
SCE_KERNEL_ERROR_EBADMSG = 0x80020059,
SCE_KERNEL_ERROR_EMULTIHOP = 0x8002005A,
SCE_KERNEL_ERROR_ENOLINK = 0x8002005B,
SCE_KERNEL_ERROR_EPROTO = 0x8002005C,
SCE_KERNEL_ERROR_ENOTCAPABLE = 0x8002005D,
SCE_KERNEL_ERROR_ECAPMODE = 0x8002005E,
SCE_KERNEL_ERROR_ENOBLK = 0x8002005F,
SCE_KERNEL_ERROR_EICV = 0x80020060,
SCE_KERNEL_ERROR_ENOPLAYGOENT = 0x80020061,
};
struct OrbisSyscall {
const char* name;
};
class OrbisOS : public System {
OrbisSyscall syscalls[1024];
public:
// Kernel information
sys_process_t proc; // TODO: Is this really necessary

View file

@ -4,11 +4,16 @@
*/
#include "orbis_dynlib.h"
#include "nucleus/system/scei/orbisos/orbisos.h"
namespace sys {
namespace scei {
namespace orbis {
S64 sys_dynlib_load_prx(void* thread, dynlib_load_prx_args* args) {
return SCE_OK;
}
} // namespace orbis
} // namespace scei
} // namespace sys

View file

@ -14,62 +14,71 @@ namespace orbis {
/**
* OrbisOS Syscall 589 (0x24D)
*/
S64 sys_dynlib_dlopen();
S64 sys_dynlib_dlopen(void* thread, void* args);
/**
* OrbisOS Syscall 590 (0x24E)
*/
S64 sys_dynlib_dlclose();
S64 sys_dynlib_dlclose(void* thread, void* args);
/**
* OrbisOS Syscall 591 (0x24F)
*/
S64 sys_dynlib_dlsym();
S64 sys_dynlib_dlsym(void* thread, void* args);
/**
* OrbisOS Syscall 592 (0x250)
*/
S64 sys_dynlib_get_list();
S64 sys_dynlib_get_list(void* thread, void* args);
/**
* OrbisOS Syscall 593 (0x251)
*/
S64 sys_dynlib_get_info();
S64 sys_dynlib_get_info(void* thread, void* args);
/**
* OrbisOS Syscall 594 (0x252)
*/
S64 sys_dynlib_load_prx();
struct dynlib_load_prx_args {
// TODO: Members below could be wrong
S08* path;
};
S64 sys_dynlib_load_prx(void* thread, dynlib_load_prx_args* args);
/**
* OrbisOS Syscall 595 (0x253)
*/
S64 sys_dynlib_unload_prx();
S64 sys_dynlib_unload_prx(void* thread, void* args);
/**
* OrbisOS Syscall 596 (0x254)
*/
S64 sys_dynlib_do_copy_relocations();
S64 sys_dynlib_do_copy_relocations(void* thread, void* args);
/**
* OrbisOS Syscall 597 (0x255)
*/
S64 sys_dynlib_prepare_dlclose();
struct dynlib_prepare_dlclose_args {
S32 handle;
S32* buffer;
U64* countAddress;
};
S64 sys_dynlib_prepare_dlclose(void* thread, dynlib_prepare_dlclose_args* args);
/**
* OrbisOS Syscall 598 (0x256)
*/
S64 sys_dynlib_get_proc_param();
S64 sys_dynlib_get_proc_param(void* thread, void* args);
/**
* OrbisOS Syscall 599 (0x257)
*/
S64 sys_dynlib_process_needed_and_relocate();
S64 sys_dynlib_process_needed_and_relocate(void* thread, void* args);
/**
* OrbisOS Syscall 608 (0x260)
*/
S64 sys_dynlib_get_info_ex();
S64 sys_dynlib_get_info_ex(void* thread, void* args);
} // namespace orbis
} // namespace scei