mirror of
https://github.com/AlexAltea/nucleus.git
synced 2024-06-12 01:07:35 -04:00
Improved Orbis SELF loader
This commit is contained in:
parent
2065e95510
commit
201a78c381
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue