[rpcsx-os] implement sys_execve

This commit is contained in:
DH 2023-11-01 01:58:03 +03:00
parent fd14659dc3
commit 9fe1fb841f
13 changed files with 342 additions and 141 deletions

View File

@ -0,0 +1,21 @@
#pragma once
#include "orbis-config.hpp"
namespace orbis {
struct AppInfo {
uint32_t appId;
uint32_t unk0;
uint32_t unk1;
uint32_t appType;
char titleId[10];
uint16_t unk2;
uint32_t unk3;
slong unk4;
slong unk5;
slong unk6;
slong unk7;
slong unk8;
};
static_assert(sizeof(AppInfo) == 72);
} // namespace orbis

View File

@ -1,10 +1,8 @@
#pragma once
#include "KernelAllocator.hpp"
#include "thread/Thread.hpp"
#include "utils/SharedCV.hpp"
#include "utils/SharedMutex.hpp"
#include <atomic>
#include <condition_variable>
namespace orbis {
enum {

View File

@ -7,6 +7,7 @@
#include "../thread/Thread.hpp"
#include "../thread/types.hpp"
#include "ProcessState.hpp"
#include "orbis/AppInfo.hpp"
#include "orbis/file.hpp"
#include "orbis/module/Module.hpp"
#include "orbis/utils/IdMap.hpp"
@ -53,10 +54,10 @@ struct Process final {
ptr<void> processParam = nullptr;
uint64_t processParamSize = 0;
const ProcessOps *ops = nullptr;
AppInfo appInfo{};
std::uint64_t nextTlsSlot = 1;
std::uint64_t lastTlsOffset = 0;
bool isSystem = false;
utils::RcIdMap<EventFlag, sint, 4097, 1> evfMap;
utils::RcIdMap<Semaphore, sint, 4097, 1> semMap;

View File

@ -71,6 +71,8 @@ struct ProcessOps {
SysResult (*thr_set_name)(Thread *thread, slong id, ptr<const char> name);
SysResult (*fork)(Thread *thread, slong status);
SysResult (*execve)(Thread *thread, ptr<char> fname, ptr<ptr<char>> argv,
ptr<ptr<char>> envv);
SysResult (*exit)(Thread *thread, sint status);
SysResult (*processNeeded)(Thread *thread);

View File

@ -4,8 +4,10 @@
#include "thread/Process.hpp"
#include "utils/Logs.hpp"
#include "utils/SharedMutex.hpp"
#include <chrono>
#include <list>
#include <span>
#include <thread>
namespace orbis {
struct KEvent {
@ -110,7 +112,6 @@ orbis::SysResult orbis::sys_kevent(Thread *thread, sint fd,
return orbis::ErrorCode::BADF;
}
if (nchanges != 0) {
for (auto change : std::span(changelist, nchanges)) {
ORBIS_LOG_TODO(__FUNCTION__, change.ident, change.filter, change.flags,
@ -148,6 +149,12 @@ orbis::SysResult orbis::sys_kevent(Thread *thread, sint fd,
if (note.event.filter == kEvFiltDisplay || note.event.filter == kEvFiltGraphicsCore) {
result.push_back(note.event);
}
if (note.event.filter == kEvFiltProc) {
// TODO
std::this_thread::sleep_for(std::chrono::milliseconds(500));
note.event.data = 0;
result.push_back(note.event);
}
}
std::memcpy(eventlist, result.data(), result.size() * sizeof(KEvent));

View File

@ -2,6 +2,10 @@
orbis::SysResult orbis::sys_execve(Thread *thread, ptr<char> fname,
ptr<ptr<char>> argv, ptr<ptr<char>> envv) {
if (auto execve = thread->tproc->ops->execve) {
return execve(thread, fname, argv, envv);
}
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_fexecve(Thread *thread, sint fd,

View File

@ -1,9 +1,13 @@
#include "sys/sysproto.hpp"
#include "utils/Logs.hpp"
#include <pipe.hpp>
orbis::SysResult orbis::sys_pipe(Thread *thread) {
auto pipe = createPipe();
thread->retval[0] = thread->tproc->fileDescriptors.insert(pipe);
thread->retval[1] = thread->tproc->fileDescriptors.insert(pipe);
auto fd0 = thread->tproc->fileDescriptors.insert(pipe);
auto fd1 = thread->tproc->fileDescriptors.insert(pipe);
ORBIS_LOG_ERROR(__FUNCTION__, fd0, fd1);
thread->retval[0] = fd0;
thread->retval[1] = fd1;
return {};
}

View File

@ -20,9 +20,10 @@
struct HostFile : orbis::File {
int hostFd = -1;
bool closeOnExit = true;
~HostFile() {
if (hostFd > 0) {
if (hostFd > 0 && closeOnExit) {
::close(hostFd);
}
}
@ -46,86 +47,157 @@ struct HostFsDevice : IoDevice {
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
std::uint32_t flags, std::uint32_t mode,
orbis::Thread *thread) override;
orbis::ErrorCode mkdir(const char *path, int mode, orbis::Thread *thread) override;
orbis::ErrorCode mkdir(const char *path, int mode,
orbis::Thread *thread) override;
orbis::ErrorCode rmdir(const char *path, orbis::Thread *thread) override;
orbis::ErrorCode rename(const char *from, const char *to, orbis::Thread *thread) override;
orbis::ErrorCode rename(const char *from, const char *to,
orbis::Thread *thread) override;
};
static orbis::ErrorCode convertErrc(std::errc errc) {
if (errc == std::errc{}) {
return{};
return {};
}
switch (errc) {
case std::errc::address_family_not_supported: return orbis::ErrorCode::AFNOSUPPORT;
case std::errc::address_in_use: return orbis::ErrorCode::ADDRINUSE;
case std::errc::address_not_available: return orbis::ErrorCode::ADDRNOTAVAIL;
case std::errc::already_connected: return orbis::ErrorCode::ISCONN;
case std::errc::argument_out_of_domain: return orbis::ErrorCode::DOM;
case std::errc::bad_address: return orbis::ErrorCode::FAULT;
case std::errc::bad_file_descriptor: return orbis::ErrorCode::BADF;
case std::errc::bad_message: return orbis::ErrorCode::BADMSG;
case std::errc::broken_pipe: return orbis::ErrorCode::PIPE;
case std::errc::connection_aborted: return orbis::ErrorCode::CONNABORTED;
case std::errc::connection_already_in_progress: return orbis::ErrorCode::ALREADY;
case std::errc::connection_refused: return orbis::ErrorCode::CONNREFUSED;
case std::errc::connection_reset: return orbis::ErrorCode::CONNRESET;
case std::errc::cross_device_link: return orbis::ErrorCode::XDEV;
case std::errc::destination_address_required: return orbis::ErrorCode::DESTADDRREQ;
case std::errc::device_or_resource_busy: return orbis::ErrorCode::BUSY;
case std::errc::directory_not_empty: return orbis::ErrorCode::NOTEMPTY;
case std::errc::executable_format_error: return orbis::ErrorCode::NOEXEC;
case std::errc::file_exists: return orbis::ErrorCode::EXIST;
case std::errc::file_too_large: return orbis::ErrorCode::FBIG;
case std::errc::filename_too_long: return orbis::ErrorCode::NAMETOOLONG;
case std::errc::function_not_supported: return orbis::ErrorCode::NOSYS;
case std::errc::host_unreachable: return orbis::ErrorCode::HOSTUNREACH;
case std::errc::identifier_removed: return orbis::ErrorCode::IDRM;
case std::errc::illegal_byte_sequence: return orbis::ErrorCode::ILSEQ;
case std::errc::inappropriate_io_control_operation: return orbis::ErrorCode::NOTTY;
case std::errc::interrupted: return orbis::ErrorCode::INTR;
case std::errc::invalid_argument: return orbis::ErrorCode::INVAL;
case std::errc::invalid_seek: return orbis::ErrorCode::SPIPE;
case std::errc::io_error: return orbis::ErrorCode::IO;
case std::errc::is_a_directory: return orbis::ErrorCode::ISDIR;
case std::errc::message_size: return orbis::ErrorCode::MSGSIZE;
case std::errc::network_down: return orbis::ErrorCode::NETDOWN;
case std::errc::network_reset: return orbis::ErrorCode::NETRESET;
case std::errc::network_unreachable: return orbis::ErrorCode::NETUNREACH;
case std::errc::no_buffer_space: return orbis::ErrorCode::NOBUFS;
case std::errc::no_child_process: return orbis::ErrorCode::CHILD;
case std::errc::no_link: return orbis::ErrorCode::NOLINK;
case std::errc::no_lock_available: return orbis::ErrorCode::NOLCK;
case std::errc::no_message: return orbis::ErrorCode::NOMSG;
case std::errc::no_protocol_option: return orbis::ErrorCode::NOPROTOOPT;
case std::errc::no_space_on_device: return orbis::ErrorCode::NOSPC;
case std::errc::no_such_device_or_address: return orbis::ErrorCode::NXIO;
case std::errc::no_such_device: return orbis::ErrorCode::NODEV;
case std::errc::no_such_file_or_directory: return orbis::ErrorCode::NOENT;
case std::errc::no_such_process: return orbis::ErrorCode::SRCH;
case std::errc::not_a_directory: return orbis::ErrorCode::NOTDIR;
case std::errc::not_a_socket: return orbis::ErrorCode::NOTSOCK;
case std::errc::not_connected: return orbis::ErrorCode::NOTCONN;
case std::errc::not_enough_memory: return orbis::ErrorCode::NOMEM;
case std::errc::not_supported: return orbis::ErrorCode::NOTSUP;
case std::errc::operation_canceled: return orbis::ErrorCode::CANCELED;
case std::errc::operation_in_progress: return orbis::ErrorCode::INPROGRESS;
case std::errc::operation_not_permitted: return orbis::ErrorCode::PERM;
case std::errc::operation_would_block: return orbis::ErrorCode::WOULDBLOCK;
case std::errc::permission_denied: return orbis::ErrorCode::ACCES;
case std::errc::protocol_error: return orbis::ErrorCode::PROTO;
case std::errc::protocol_not_supported: return orbis::ErrorCode::PROTONOSUPPORT;
case std::errc::read_only_file_system: return orbis::ErrorCode::ROFS;
case std::errc::resource_deadlock_would_occur: return orbis::ErrorCode::DEADLK;
case std::errc::result_out_of_range: return orbis::ErrorCode::RANGE;
case std::errc::text_file_busy: return orbis::ErrorCode::TXTBSY;
case std::errc::timed_out: return orbis::ErrorCode::TIMEDOUT;
case std::errc::too_many_files_open_in_system: return orbis::ErrorCode::NFILE;
case std::errc::too_many_files_open: return orbis::ErrorCode::MFILE;
case std::errc::too_many_links: return orbis::ErrorCode::MLINK;
case std::errc::too_many_symbolic_link_levels: return orbis::ErrorCode::LOOP;
case std::errc::value_too_large: return orbis::ErrorCode::OVERFLOW;
case std::errc::wrong_protocol_type: return orbis::ErrorCode::PROTOTYPE;
case std::errc::address_family_not_supported:
return orbis::ErrorCode::AFNOSUPPORT;
case std::errc::address_in_use:
return orbis::ErrorCode::ADDRINUSE;
case std::errc::address_not_available:
return orbis::ErrorCode::ADDRNOTAVAIL;
case std::errc::already_connected:
return orbis::ErrorCode::ISCONN;
case std::errc::argument_out_of_domain:
return orbis::ErrorCode::DOM;
case std::errc::bad_address:
return orbis::ErrorCode::FAULT;
case std::errc::bad_file_descriptor:
return orbis::ErrorCode::BADF;
case std::errc::bad_message:
return orbis::ErrorCode::BADMSG;
case std::errc::broken_pipe:
return orbis::ErrorCode::PIPE;
case std::errc::connection_aborted:
return orbis::ErrorCode::CONNABORTED;
case std::errc::connection_already_in_progress:
return orbis::ErrorCode::ALREADY;
case std::errc::connection_refused:
return orbis::ErrorCode::CONNREFUSED;
case std::errc::connection_reset:
return orbis::ErrorCode::CONNRESET;
case std::errc::cross_device_link:
return orbis::ErrorCode::XDEV;
case std::errc::destination_address_required:
return orbis::ErrorCode::DESTADDRREQ;
case std::errc::device_or_resource_busy:
return orbis::ErrorCode::BUSY;
case std::errc::directory_not_empty:
return orbis::ErrorCode::NOTEMPTY;
case std::errc::executable_format_error:
return orbis::ErrorCode::NOEXEC;
case std::errc::file_exists:
return orbis::ErrorCode::EXIST;
case std::errc::file_too_large:
return orbis::ErrorCode::FBIG;
case std::errc::filename_too_long:
return orbis::ErrorCode::NAMETOOLONG;
case std::errc::function_not_supported:
return orbis::ErrorCode::NOSYS;
case std::errc::host_unreachable:
return orbis::ErrorCode::HOSTUNREACH;
case std::errc::identifier_removed:
return orbis::ErrorCode::IDRM;
case std::errc::illegal_byte_sequence:
return orbis::ErrorCode::ILSEQ;
case std::errc::inappropriate_io_control_operation:
return orbis::ErrorCode::NOTTY;
case std::errc::interrupted:
return orbis::ErrorCode::INTR;
case std::errc::invalid_argument:
return orbis::ErrorCode::INVAL;
case std::errc::invalid_seek:
return orbis::ErrorCode::SPIPE;
case std::errc::io_error:
return orbis::ErrorCode::IO;
case std::errc::is_a_directory:
return orbis::ErrorCode::ISDIR;
case std::errc::message_size:
return orbis::ErrorCode::MSGSIZE;
case std::errc::network_down:
return orbis::ErrorCode::NETDOWN;
case std::errc::network_reset:
return orbis::ErrorCode::NETRESET;
case std::errc::network_unreachable:
return orbis::ErrorCode::NETUNREACH;
case std::errc::no_buffer_space:
return orbis::ErrorCode::NOBUFS;
case std::errc::no_child_process:
return orbis::ErrorCode::CHILD;
case std::errc::no_link:
return orbis::ErrorCode::NOLINK;
case std::errc::no_lock_available:
return orbis::ErrorCode::NOLCK;
case std::errc::no_message:
return orbis::ErrorCode::NOMSG;
case std::errc::no_protocol_option:
return orbis::ErrorCode::NOPROTOOPT;
case std::errc::no_space_on_device:
return orbis::ErrorCode::NOSPC;
case std::errc::no_such_device_or_address:
return orbis::ErrorCode::NXIO;
case std::errc::no_such_device:
return orbis::ErrorCode::NODEV;
case std::errc::no_such_file_or_directory:
return orbis::ErrorCode::NOENT;
case std::errc::no_such_process:
return orbis::ErrorCode::SRCH;
case std::errc::not_a_directory:
return orbis::ErrorCode::NOTDIR;
case std::errc::not_a_socket:
return orbis::ErrorCode::NOTSOCK;
case std::errc::not_connected:
return orbis::ErrorCode::NOTCONN;
case std::errc::not_enough_memory:
return orbis::ErrorCode::NOMEM;
case std::errc::not_supported:
return orbis::ErrorCode::NOTSUP;
case std::errc::operation_canceled:
return orbis::ErrorCode::CANCELED;
case std::errc::operation_in_progress:
return orbis::ErrorCode::INPROGRESS;
case std::errc::operation_not_permitted:
return orbis::ErrorCode::PERM;
case std::errc::operation_would_block:
return orbis::ErrorCode::WOULDBLOCK;
case std::errc::permission_denied:
return orbis::ErrorCode::ACCES;
case std::errc::protocol_error:
return orbis::ErrorCode::PROTO;
case std::errc::protocol_not_supported:
return orbis::ErrorCode::PROTONOSUPPORT;
case std::errc::read_only_file_system:
return orbis::ErrorCode::ROFS;
case std::errc::resource_deadlock_would_occur:
return orbis::ErrorCode::DEADLK;
case std::errc::result_out_of_range:
return orbis::ErrorCode::RANGE;
case std::errc::text_file_busy:
return orbis::ErrorCode::TXTBSY;
case std::errc::timed_out:
return orbis::ErrorCode::TIMEDOUT;
case std::errc::too_many_files_open_in_system:
return orbis::ErrorCode::NFILE;
case std::errc::too_many_files_open:
return orbis::ErrorCode::MFILE;
case std::errc::too_many_links:
return orbis::ErrorCode::MLINK;
case std::errc::too_many_symbolic_link_levels:
return orbis::ErrorCode::LOOP;
case std::errc::value_too_large:
return orbis::ErrorCode::OVERFLOW;
case std::errc::wrong_protocol_type:
return orbis::ErrorCode::PROTOTYPE;
default:
return orbis::ErrorCode::FAULT;
}
@ -133,7 +205,7 @@ static orbis::ErrorCode convertErrc(std::errc errc) {
static orbis::ErrorCode convertErrorCode(const std::error_code &code) {
if (!code) {
return{};
return {};
}
return convertErrc(static_cast<std::errc>(code.value()));
}
@ -219,20 +291,21 @@ static orbis::ErrorCode host_write(orbis::File *file, orbis::Uio *uio,
vec.push_back({.iov_base = entry.base, .iov_len = entry.len});
}
ssize_t cnt = 0;
if (hostFile->hostFd == 1 || hostFile->hostFd == 2) {
ssize_t cnt = ::pwritev(hostFile->hostFd, vec.data(), vec.size(), uio->offset);
if (cnt < 0) {
for (auto io : vec) {
cnt += ::write(hostFile->hostFd, io.iov_base, io.iov_len);
auto result = ::write(hostFile->hostFd, io.iov_base, io.iov_len);
if (result < 0) {
return convertErrno();
}
cnt += result;
if (cnt != io.iov_len) {
break;
}
}
} else {
cnt = ::pwritev(hostFile->hostFd, vec.data(), vec.size(), uio->offset);
}
if (cnt < 0) {
return convertErrno();
}
uio->resid -= cnt;
@ -461,7 +534,8 @@ orbis::ErrorCode HostFsDevice::open(orbis::Ref<orbis::File> *file,
return {};
}
orbis::ErrorCode HostFsDevice::mkdir(const char *path, int mode, orbis::Thread *thread) {
orbis::ErrorCode HostFsDevice::mkdir(const char *path, int mode,
orbis::Thread *thread) {
std::error_code ec;
std::filesystem::create_directories(hostPath + "/" + path, ec);
return convertErrorCode(ec);
@ -471,7 +545,8 @@ orbis::ErrorCode HostFsDevice::rmdir(const char *path, orbis::Thread *thread) {
std::filesystem::remove(hostPath + "/" + path, ec);
return convertErrorCode(ec);
}
orbis::ErrorCode HostFsDevice::rename(const char *from, const char *to, orbis::Thread *thread) {
orbis::ErrorCode HostFsDevice::rename(const char *from, const char *to,
orbis::Thread *thread) {
std::error_code ec;
std::filesystem::rename(hostPath + "/" + from, hostPath + "/" + to, ec);
return convertErrorCode(ec);
@ -492,6 +567,7 @@ struct FdWrapDevice : public IoDevice {
std::uint32_t flags, std::uint32_t mode,
orbis::Thread *thread) override {
*file = createHostFile(fd, this);
static_cast<HostFile *>(file->get())->closeOnExit = false;
return {};
}
};

View File

@ -251,7 +251,7 @@ static const char *getSyscallName(orbis::Thread *thread, int sysno) {
}
static void onSysEnter(orbis::Thread *thread, int id, uint64_t *args,
int argsCount) {
if (!g_traceSyscalls && thread->tid < 10000) {
if (!g_traceSyscalls) {
return;
}
flockfile(stderr);
@ -277,7 +277,7 @@ static void onSysEnter(orbis::Thread *thread, int id, uint64_t *args,
static void onSysExit(orbis::Thread *thread, int id, uint64_t *args,
int argsCount, orbis::SysResult result) {
if (!result.isError() && !g_traceSyscalls && thread->tid < 10000) {
if (!result.isError() && !g_traceSyscalls) {
return;
}
@ -305,26 +305,13 @@ static void onSysExit(orbis::Thread *thread, int id, uint64_t *args,
funlockfile(stderr);
}
static int ps4Exec(orbis::Thread *mainThread,
orbis::utils::Ref<orbis::Module> executableModule,
std::span<const char *> argv, std::span<const char *> envp) {
const auto stackEndAddress = 0x7'ffff'c000ull;
const auto stackSize = 0x40000 * 16;
auto stackStartAddress = stackEndAddress - stackSize;
mainThread->stackStart =
rx::vm::map(reinterpret_cast<void *>(stackStartAddress), stackSize,
rx::vm::kMapProtCpuWrite | rx::vm::kMapProtCpuRead,
rx::vm::kMapFlagAnonymous | rx::vm::kMapFlagFixed |
rx::vm::kMapFlagPrivate | rx::vm::kMapFlagStack);
mainThread->stackEnd =
reinterpret_cast<std::byte *>(mainThread->stackStart) + stackSize;
static void ps4InitDev() {
auto dmem1 = createDmemCharacterDevice(1);
orbis::g_context.dmemDevice = dmem1;
auto stdoutFd = ::open("stdout.txt", O_CREAT | O_TRUNC | O_WRONLY, 0666);
auto stderrFd = ::open("stderr.txt", O_CREAT | O_TRUNC | O_WRONLY, 0666);
auto stdoutDev = createFdWrapDevice(::open("stdout.txt", O_CREAT | O_TRUNC | O_WRONLY, 0666));
auto stderrDev = createFdWrapDevice(::open("stderr.txt", O_CREAT | O_TRUNC | O_WRONLY, 0666));
auto stdinDev = createFdWrapDevice(STDIN_FILENO);
rx::vfs::addDevice("dmem0", createDmemCharacterDevice(0));
rx::vfs::addDevice("npdrm", createNpdrmCharacterDevice());
@ -334,12 +321,12 @@ static int ps4Exec(orbis::Thread *mainThread,
rx::vfs::addDevice("camera", createCameraCharacterDevice());
rx::vfs::addDevice("dmem1", dmem1);
rx::vfs::addDevice("dmem2", createDmemCharacterDevice(2));
rx::vfs::addDevice("stdout", createFdWrapDevice(stdoutFd));
rx::vfs::addDevice("stderr", createFdWrapDevice(stderrFd));
rx::vfs::addDevice("deci_stdin", createFdWrapDevice(STDIN_FILENO));
rx::vfs::addDevice("deci_stdout", createFdWrapDevice(stdoutFd));
rx::vfs::addDevice("deci_stderr", createFdWrapDevice(stderrFd));
rx::vfs::addDevice("stdin", createFdWrapDevice(STDIN_FILENO));
rx::vfs::addDevice("stdout", stdoutDev);
rx::vfs::addDevice("stderr", stderrDev);
rx::vfs::addDevice("deci_stdin", stdinDev);
rx::vfs::addDevice("deci_stdout", stdoutDev);
rx::vfs::addDevice("deci_stderr", stderrDev);
rx::vfs::addDevice("stdin", stdinDev);
rx::vfs::addDevice("zero", createZeroCharacterDevice());
rx::vfs::addDevice("null", createNullCharacterDevice());
rx::vfs::addDevice("dipsw", createDipswCharacterDevice());
@ -366,6 +353,11 @@ static int ps4Exec(orbis::Thread *mainThread,
rx::vfs::addDevice("notification4", createNotificationCharacterDevice(4));
rx::vfs::addDevice("notification5", createNotificationCharacterDevice(5));
orbis::g_context.shmDevice = createShmDevice();
orbis::g_context.blockpoolDevice = createBlockPoolDevice();
}
static void ps4InitFd(orbis::Thread *mainThread) {
orbis::Ref<orbis::File> stdinFile;
orbis::Ref<orbis::File> stdoutFile;
orbis::Ref<orbis::File> stderrFile;
@ -376,9 +368,22 @@ static int ps4Exec(orbis::Thread *mainThread,
mainThread->tproc->fileDescriptors.insert(stdinFile);
mainThread->tproc->fileDescriptors.insert(stdoutFile);
mainThread->tproc->fileDescriptors.insert(stderrFile);
}
orbis::g_context.shmDevice = createShmDevice();
orbis::g_context.blockpoolDevice = createBlockPoolDevice();
int ps4Exec(orbis::Thread *mainThread,
orbis::utils::Ref<orbis::Module> executableModule,
std::span<std::string> argv, std::span<std::string> envp) {
const auto stackEndAddress = 0x7'ffff'c000ull;
const auto stackSize = 0x40000 * 16;
auto stackStartAddress = stackEndAddress - stackSize;
mainThread->stackStart =
rx::vm::map(reinterpret_cast<void *>(stackStartAddress), stackSize,
rx::vm::kMapProtCpuWrite | rx::vm::kMapProtCpuRead,
rx::vm::kMapFlagAnonymous | rx::vm::kMapFlagFixed |
rx::vm::kMapFlagPrivate | rx::vm::kMapFlagStack);
mainThread->stackEnd =
reinterpret_cast<std::byte *>(mainThread->stackStart) + stackSize;
std::vector<std::uint64_t> argvOffsets;
std::vector<std::uint64_t> envpOffsets;
@ -412,14 +417,14 @@ static int ps4Exec(orbis::Thread *mainThread,
StackWriter stack{reinterpret_cast<std::uint64_t>(mainThread->stackEnd)};
for (auto elem : argv) {
argvOffsets.push_back(stack.pushString(elem));
for (auto &elem : argv) {
argvOffsets.push_back(stack.pushString(elem.data()));
}
argvOffsets.push_back(0);
for (auto elem : envp) {
envpOffsets.push_back(stack.pushString(elem));
for (auto &elem : envp) {
envpOffsets.push_back(stack.pushString(elem.data()));
}
envpOffsets.push_back(0);
@ -647,8 +652,8 @@ int main(int argc, const char *argv[]) {
// rx::vm::printHostStats();
orbis::g_context.allocatePid();
auto initProcess = orbis::g_context.createProcess(asRoot ? 1 : 11);
pthread_setname_np(pthread_self(), "11.MAINTHREAD");
auto initProcess = orbis::g_context.createProcess(asRoot ? 1 : 10);
pthread_setname_np(pthread_self(), "10.MAINTHREAD");
std::thread{[] {
pthread_setname_np(pthread_self(), "Bridge");
@ -718,7 +723,9 @@ int main(int argc, const char *argv[]) {
initProcess->onSysEnter = onSysEnter;
initProcess->onSysExit = onSysExit;
initProcess->ops = &rx::procOpsTable;
initProcess->isSystem = isSystem;
initProcess->appInfo = {
.unk4 = (isSystem ? orbis::slong(0x80000000'00000000) : 0),
};
auto [baseId, mainThread] = initProcess->threadsMap.emplace();
mainThread->tproc = initProcess;
@ -740,9 +747,11 @@ int main(int argc, const char *argv[]) {
if (executableModule->type == rx::linker::kElfTypeSceDynExec ||
executableModule->type == rx::linker::kElfTypeSceExec ||
executableModule->type == rx::linker::kElfTypeExec) {
status = ps4Exec(mainThread, std::move(executableModule),
std::span(argv + argIndex, argc - argIndex),
std::span<const char *>());
ps4InitDev();
ps4InitFd(mainThread);
std::vector<std::string> ps4Argv(argv + argIndex,
argv + argIndex + argc - argIndex);
status = ps4Exec(mainThread, std::move(executableModule), ps4Argv, {});
} else {
std::fprintf(stderr, "Unexpected executable type\n");
status = 1;

View File

@ -5,7 +5,9 @@
#include "iodev/blockpool.hpp"
#include "iodev/dmem.hpp"
#include "linker.hpp"
#include "orbis-config.hpp"
#include "orbis/KernelContext.hpp"
#include "orbis/file.hpp"
#include "orbis/module/ModuleHandle.hpp"
#include "orbis/thread/Process.hpp"
#include "orbis/thread/Thread.hpp"
@ -34,6 +36,9 @@ using namespace orbis;
extern "C" void __register_frame(const void *);
void setupSigHandlers();
int ps4Exec(orbis::Thread *mainThread,
orbis::utils::Ref<orbis::Module> executableModule,
std::span<std::string> argv, std::span<std::string> envp);
namespace {
static std::pair<SysResult, Ref<Module>>
@ -629,19 +634,20 @@ SysResult fork(Thread *thread, slong flags) {
auto childPid = g_context.allocatePid() * 10000 + 1;
auto mtx = knew<shared_mutex>();
auto cv = knew<shared_cv>();
mtx->lock();
int hostPid = ::fork();
if (hostPid) {
mtx->lock();
cv->wait(*mtx);
mtx->unlock();
kdelete(cv);
kdelete(mtx);
thread->retval[0] = childPid;
thread->retval[1] = 0;
return{};
return {};
}
auto process = g_context.createProcess(childPid);
@ -649,7 +655,6 @@ SysResult fork(Thread *thread, slong flags) {
process->onSysEnter = thread->tproc->onSysEnter;
process->onSysExit = thread->tproc->onSysExit;
process->ops = thread->tproc->ops;
process->isSystem = thread->tproc->isSystem;
process->parentProcess = thread->tproc;
for (auto [id, mod] : thread->tproc->modulesMap) {
if (!process->modulesMap.insert(id, mod)) {
@ -669,7 +674,7 @@ SysResult fork(Thread *thread, slong flags) {
rx::vm::fork(thread->tproc->pid);
rx::vfs::fork();
cv->notify_one(*mtx);
cv->notify_all(*mtx);
auto [baseId, newThread] = process->threadsMap.emplace();
newThread->tproc = process;
@ -693,8 +698,11 @@ SysResult fork(Thread *thread, slong flags) {
std::exit(-1);
}
auto ttyFd =
::open(("tty-" + std::to_string(thread->tproc->pid) + ".txt").c_str(),
auto stdoutFd =
::open(("stdout-" + std::to_string(thread->tproc->pid) + ".txt").c_str(),
O_CREAT | O_TRUNC | O_WRONLY, 0666);
auto stderrFd =
::open(("stderr-" + std::to_string(thread->tproc->pid) + ".txt").c_str(),
O_CREAT | O_TRUNC | O_WRONLY, 0666);
auto logFd =
::open(("log-" + std::to_string(thread->tproc->pid) + ".txt").c_str(),
@ -703,13 +711,65 @@ SysResult fork(Thread *thread, slong flags) {
dup2(logFd, 1);
dup2(logFd, 2);
auto tty = createFdWrapDevice(ttyFd);
auto stdoutDev = createFdWrapDevice(stdoutFd);
auto stderrDev = createFdWrapDevice(stderrFd);
rx::vfs::addDevice("stdout", tty);
rx::vfs::addDevice("stderr", tty);
rx::vfs::addDevice("deci_stdout", tty);
rx::vfs::addDevice("deci_stderr", tty);
return{};
rx::vfs::addDevice("stdout", stdoutDev);
rx::vfs::addDevice("stderr", stderrDev);
rx::vfs::addDevice("deci_stdout", stdoutDev);
rx::vfs::addDevice("deci_stderr", stderrDev);
return {};
}
SysResult execve(Thread *thread, ptr<char> fname, ptr<ptr<char>> argv,
ptr<ptr<char>> envv) {
ORBIS_LOG_ERROR(__FUNCTION__, fname);
std::vector<std::string> _argv;
std::vector<std::string> _envv;
if (auto ptr = argv) {
char *p;
while (uread(p, ptr) == ErrorCode{} && p != nullptr) {
ORBIS_LOG_ERROR(" argv ", p);
_argv.push_back(p);
++ptr;
}
}
if (auto ptr = envv) {
char *p;
while (uread(p, ptr) == ErrorCode{} && p != nullptr) {
ORBIS_LOG_ERROR(" envv ", p);
_envv.push_back(p);
++ptr;
}
}
{
orbis::Ref<File> file;
auto result = rx::vfs::open(fname, kOpenFlagReadOnly, 0, &file, thread);
if (result.isError()) {
return result;
}
}
std::string path = fname;
rx::vm::reset();
thread->tproc->nextTlsSlot = 1;
for (auto [id, mod] : thread->tproc->modulesMap) {
thread->tproc->modulesMap.close(id);
}
auto executableModule = rx::linker::loadModuleFile(path, thread);
executableModule->id = thread->tproc->modulesMap.insert(executableModule);
thread->tproc->processParam = executableModule->processParam;
thread->tproc->processParamSize = executableModule->processParamSize;
ps4Exec(thread, executableModule, _argv, _envv);
std::abort();
}
SysResult registerEhFrames(Thread *thread) {
@ -766,6 +826,7 @@ ProcessOps rx::procOpsTable = {
.thr_wake = thr_wake,
.thr_set_name = thr_set_name,
.fork = fork,
.execve = execve,
.exit = exit,
.processNeeded = processNeeded,
.registerEhFrames = registerEhFrames,

View File

@ -49,8 +49,8 @@ void rx::vfs::fork() {
}
gDevFs = orbis::knew<DevFs>();
gMountsMap.emplace("/dev/", gDevFs);
gMountsMap.emplace("/proc/", orbis::knew<ProcFs>());
gMountsMap["/dev/"] = gDevFs;
gMountsMap["/proc/"] = orbis::knew<ProcFs>();
for (auto &fs : parentDevFs->devices) {
gDevFs->devices[fs.first] = fs.second;

View File

@ -673,6 +673,23 @@ void rx::vm::fork(std::uint64_t pid) {
}
}
void rx::vm::reset() {
std::memset(gBlocks, 0, sizeof(gBlocks));
utils::unmap(reinterpret_cast<void *>(kMinAddress),
kMaxAddress - kMinAddress);
if (::ftruncate64(gMemoryShm, 0) < 0) {
std::abort();
}
if (::ftruncate64(gMemoryShm, kMemorySize) < 0) {
std::abort();
}
reserve(0, kMinAddress);
utils::reserve(reinterpret_cast<void *>(kMinAddress),
kMaxAddress - kMinAddress);
}
void rx::vm::initialize() {
std::printf("Memory: initialization\n");

View File

@ -68,6 +68,7 @@ std::string mapProtToString(std::int32_t prot);
void printHostStats();
void fork(std::uint64_t pid);
void reset();
void initialize();
void deinitialize();
void *map(void *addr, std::uint64_t len, std::int32_t prot, std::int32_t flags,