mirror of
https://github.com/RPCSX/rpcsx.git
synced 2024-10-07 00:33:30 +00:00
[rpcsx-os] implement sys_execve
This commit is contained in:
parent
fd14659dc3
commit
9fe1fb841f
21
orbis-kernel/include/orbis/AppInfo.hpp
Normal file
21
orbis-kernel/include/orbis/AppInfo.hpp
Normal 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
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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,
|
||||
|
@ -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 {};
|
||||
}
|
||||
|
@ -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 {};
|
||||
}
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user