Merge orbis-kernel submodule

This commit is contained in:
Ivan Chikish 2023-07-03 14:10:16 +03:00
parent 91f48cdf77
commit 1ee6b7c970
97 changed files with 8134 additions and 1 deletions

View file

@ -0,0 +1,97 @@
#pragma once
#include "orbis/thread/Process.hpp"
#include "utils/LinkedNode.hpp"
#include "utils/SharedMutex.hpp"
#include <algorithm>
#include <mutex>
#include <utility>
#include <vector>
namespace orbis {
class KernelContext {
public:
struct EventListener {
virtual ~EventListener() = default;
virtual void onProcessCreated(Process *) = 0;
virtual void onProcessDeleted(pid_t pid) = 0;
};
~KernelContext() {
while (m_processes != nullptr) {
deleteProcess(&m_processes->object);
}
}
void addEventListener(EventListener *listener) {
m_event_listeners.push_back(listener);
}
void removeEventListener(EventListener *listener) {
auto it =
std::find(m_event_listeners.begin(), m_event_listeners.end(), listener);
if (it != m_event_listeners.end()) {
m_event_listeners.erase(it);
}
}
Process *createProcess(pid_t pid) {
auto newProcess = new utils::LinkedNode<Process>();
newProcess->object.context = this;
newProcess->object.pid = pid;
newProcess->object.state = ProcessState::NEW;
{
std::lock_guard lock(m_proc_mtx);
if (m_processes != nullptr) {
m_processes->insertPrev(*newProcess);
}
m_processes = newProcess;
}
for (auto listener : m_event_listeners) {
listener->onProcessCreated(&newProcess->object);
}
return &newProcess->object;
}
void deleteProcess(Process *proc) {
auto procNode = reinterpret_cast<utils::LinkedNode<Process> *>(proc);
auto pid = proc->pid;
{
std::lock_guard lock(m_proc_mtx);
auto next = procNode->erase();
if (procNode == m_processes) {
m_processes = next;
}
}
delete procNode;
for (auto listener : m_event_listeners) {
listener->onProcessDeleted(pid);
}
}
Process *findProcessById(pid_t pid) const {
std::lock_guard lock(m_proc_mtx);
for (auto proc = m_processes; proc != nullptr; proc = proc->next) {
if (proc->object.pid == pid) {
return &proc->object;
}
}
return nullptr;
}
private:
mutable shared_mutex m_proc_mtx;
utils::LinkedNode<Process> *m_processes = nullptr;
std::vector<EventListener *> m_event_listeners;
};
} // namespace orbis

View file

@ -0,0 +1,4 @@
#pragma once
#include "error/SysResult.hpp" // IWYU pragma: export
#include "error/ErrorCode.hpp" // IWYU pragma: export

View file

@ -0,0 +1,111 @@
#pragma once
namespace orbis {
enum class ErrorCode : int {
PERM = 1, // Operation not permitted
NOENT = 2, // No such file or directory
SRCH = 3, // No such process
INTR = 4, // Interrupted system call
IO = 5, // Input/output error
NXIO = 6, // Device not configured
TOOBIG = 7, // Argument list too long
NOEXEC = 8, // Exec format error
BADF = 9, // Bad file descriptor
CHILD = 10, // No child processes
DEADLK = 11, // Resource deadlock avoided
NOMEM = 12, // Cannot allocate memory
ACCES = 13, // Permission denied
FAULT = 14, // Bad address
NOTBLK = 15, // Block device required
BUSY = 16, // Device busy
EXIST = 17, // File exists
XDEV = 18, // Cross-device link
NODEV = 19, // Operation not supported by device
NOTDIR = 20, // Not a directory
ISDIR = 21, // Is a directory
INVAL = 22, // Invalid argument
NFILE = 23, // Too many open files in system
MFILE = 24, // Too many open files
NOTTY = 25, // Inappropriate ioctl for device
TXTBSY = 26, // Text file busy
FBIG = 27, // File too large
NOSPC = 28, // No space left on device
SPIPE = 29, // Illegal seek
ROFS = 30, // Read-only filesystem
MLINK = 31, // Too many links
PIPE = 32, // Broken pipe
DOM = 33, // Numerical argument out of domain
RANGE = 34, // Result too large
AGAIN = 35, // Resource temporarily unavailable
WOULDBLOCK = AGAIN, // Operation would block
INPROGRESS = 36, // Operation now in progress
ALREADY = 37, // Operation already in progress
NOTSOCK = 38, // Socket operation on non-socket
DESTADDRREQ = 39, // Destination address required
MSGSIZE = 40, // Message too long
PROTOTYPE = 41, // Protocol wrong type for socket
NOPROTOOPT = 42, // Protocol not available
PROTONOSUPPORT = 43, // Protocol not supported
SOCKTNOSUPPORT = 44, // Socket type not supported
OPNOTSUPP = 45, // Operation not supported
NOTSUP = OPNOTSUPP, // Operation not supported
PFNOSUPPORT = 46, // Protocol family not supported
AFNOSUPPORT = 47, // Address family not supported by protocol family
ADDRINUSE = 48, // Address already in use
ADDRNOTAVAIL = 49, // Can't assign requested address
NETDOWN = 50, // Network is down
NETUNREACH = 51, // Network is unreachable
NETRESET = 52, // Network dropped connection on reset
CONNABORTED = 53, // Software caused connection abort
CONNRESET = 54, // Connection reset by peer
NOBUFS = 55, // No buffer space available
ISCONN = 56, // Socket is already connected
NOTCONN = 57, // Socket is not connected
SHUTDOWN = 58, // Can't send after socket shutdown
TOOMANYREFS = 59, // Too many references: can't splice
TIMEDOUT = 60, // Operation timed out
CONNREFUSED = 61, // Connection refused
LOOP = 62, // Too many levels of symbolic links
NAMETOOLONG = 63, // File name too long
HOSTDOWN = 64, // Host is down
HOSTUNREACH = 65, // No route to host
NOTEMPTY = 66, // Directory not empty
PROCLIM = 67, // Too many processes
USERS = 68, // Too many users
DQUOT = 69, // Disc quota exceeded
STALE = 70, // Stale NFS file handle
REMOTE = 71, // Too many levels of remote in path
BADRPC = 72, // RPC struct is bad
RPCMISMATCH = 73, // RPC version wrong
PROGUNAVAIL = 74, // RPC prog. not avail
PROGMISMATCH = 75, // Program version wrong
PROCUNAVAIL = 76, // Bad procedure for program
NOLCK = 77, // No locks available
NOSYS = 78, // Function not implemented
FTYPE = 79, // Inappropriate file type or format
AUTH = 80, // Authentication error
NEEDAUTH = 81, // Need authenticator
IDRM = 82, // Identifier removed
NOMSG = 83, // No message of desired type
OVERFLOW = 84, // Value too large to be stored in data type
CANCELED = 85, // Operation canceled
ILSEQ = 86, // Illegal byte sequence
NOATTR = 87, // Attribute not found
DOOFUS = 88, // Programming error
BADMSG = 89, // Bad message
MULTIHOP = 90, // Multihop attempted
NOLINK = 91, // Link has been severed
PROTO = 92, // Protocol error
NOTCAPABLE = 93, // Capabilities insufficient
CAPMODE = 94, // Not permitted in capability mode
};
} // namespace orbis

View file

@ -0,0 +1,22 @@
#pragma once
namespace orbis {
enum class ErrorCode : int;
class SysResult {
int mValue = 0;
public:
SysResult() = default;
SysResult(ErrorCode ec) : mValue(-static_cast<int>(ec)){}
[[nodiscard]] static SysResult notAnError(ErrorCode ec) {
SysResult result;
result.mValue = static_cast<int>(ec);
return result;
}
[[nodiscard]] int value() const { return mValue < 0 ? -mValue : mValue; }
[[nodiscard]] bool isError() const { return mValue < 0; }
};
} // namespace orbis

View file

@ -0,0 +1,7 @@
#pragma once
#include "module/Module.hpp" // IWYU pragma: export
#include "module/ModuleHandle.hpp" // IWYU pragma: export
#include "module/ModuleInfo.hpp" // IWYU pragma: export
#include "module/ModuleInfoEx.hpp" // IWYU pragma: export
#include "module/ModuleSegment.hpp" // IWYU pragma: export

View file

@ -0,0 +1,141 @@
#pragma once
#include "ModuleHandle.hpp"
#include "ModuleSegment.hpp"
#include "../utils/Rc.hpp"
#include "orbis-config.hpp"
#include <cstddef>
#include <vector>
#include <string>
namespace orbis {
struct Thread;
struct Process;
struct ModuleNeeded {
std::string name;
std::uint16_t version;
std::uint16_t attr;
bool isExport;
};
enum class SymbolBind : std::uint8_t {
Local,
Global,
Weak,
Unique = 10
};
enum class SymbolVisibility : std::uint8_t {
Default,
Internal,
Hidden,
Protected
};
enum class SymbolType : std::uint8_t {
NoType,
Object,
Function,
Section,
File,
Common,
Tls,
IFunc = 10,
};
struct Symbol {
std::int32_t moduleIndex;
std::uint32_t libraryIndex;
std::uint64_t id;
std::uint64_t address;
std::uint64_t size;
SymbolVisibility visibility;
SymbolBind bind;
SymbolType type;
};
struct Relocation {
std::uint64_t offset;
std::uint32_t relType;
std::uint32_t symbolIndex;
std::int64_t addend;
};
struct Module {
Process *proc{};
std::string vfsPath;
char moduleName[256]{};
char soName[256]{};
ModuleHandle id{};
uint32_t tlsIndex{};
ptr<void> tlsInit{};
uint32_t tlsInitSize{};
uint32_t tlsSize{};
uint32_t tlsOffset{};
uint32_t tlsAlign{};
ptr<void> initProc{};
ptr<void> finiProc{};
ptr<void> ehFrameHdr{};
ptr<void> ehFrame{};
uint32_t ehFrameHdrSize{};
uint32_t ehFrameSize{};
ModuleSegment segments[4]{};
uint32_t segmentCount{};
std::uint8_t fingerprint[20]{};
ptr<void> base{};
uint64_t size{};
ptr<void> stackStart{};
ptr<void> stackEnd{};
ptr<void> processParam{};
uint64_t processParamSize{};
ptr<void> moduleParam{};
uint64_t moduleParamSize{};
ptr<uint64_t> pltGot{};
uint16_t version{};
uint16_t attributes{};
uint16_t type{};
uint16_t flags{};
uint64_t entryPoint{};
uint32_t phNum{};
uint64_t phdrAddress{};
bool isTlsDone = false;
std::vector<Symbol> symbols;
std::vector<Relocation> pltRelocations;
std::vector<Relocation> nonPltRelocations;
std::vector<ModuleNeeded> neededModules;
std::vector<ModuleNeeded> neededLibraries;
std::vector<utils::Ref<Module>> importedModules;
std::vector<utils::Ref<Module>> namespaceModules;
std::vector<std::string> needed;
std::atomic<unsigned> references{0};
void incRef() {
if (references.fetch_add(1, std::memory_order::relaxed) > 512) {
assert(!"too many references");
}
}
void decRef() {
if (references.fetch_sub(1, std::memory_order::relaxed) == 1 && proc != nullptr) {
destroy();
}
}
orbis::SysResult relocate(Process *process);
private:
void destroy();
};
utils::Ref<Module> createModule(Thread *p, std::string vfsPath, const char *name);
} // namespace orbis

View file

@ -0,0 +1,7 @@
#pragma once
#include <cstdint>
namespace orbis {
enum class ModuleHandle : std::uint32_t {};
} // namespace orbis

View file

@ -0,0 +1,15 @@
#pragma once
#include "ModuleSegment.hpp"
#include "orbis-config.hpp"
namespace orbis {
struct ModuleInfo {
uint64_t size;
char name[256];
ModuleSegment segments[4];
uint32_t segmentCount;
uint8_t fingerprint[20];
};
} // namespace orbis

View file

@ -0,0 +1,30 @@
#pragma once
#include "ModuleSegment.hpp"
#include "orbis-config.hpp"
namespace orbis {
struct ModuleInfoEx {
uint64_t size;
char name[256];
uint32_t id;
uint32_t tlsIndex;
ptr<void> tlsInit;
uint32_t tlsInitSize;
uint32_t tlsSize;
uint32_t tlsOffset;
uint32_t tlsAlign;
ptr<void> initProc;
ptr<void> finiProc;
uint64_t reserved1;
uint64_t reserved2;
ptr<void> ehFrameHdr;
ptr<void> ehFrame;
uint32_t ehFrameHdrSize;
uint32_t ehFrameSize;
ModuleSegment segments[4];
uint32_t segmentCount;
uint32_t refCount;
};
} // namespace orbis

View file

@ -0,0 +1,11 @@
#pragma once
#include "orbis-config.hpp"
namespace orbis {
struct ModuleSegment {
ptr<void> addr;
uint32_t size;
uint32_t prot;
};
} // namespace orbis

View file

@ -0,0 +1,599 @@
#pragma once
namespace orbis {
enum Syscall {
kSYS_syscall = 0,
kSYS_exit = 1,
kSYS_fork = 2,
kSYS_read = 3,
kSYS_write = 4,
kSYS_open = 5,
kSYS_close = 6,
kSYS_wait4 = 7,
kSYS_link = 9,
kSYS_unlink = 10,
kSYS_chdir = 12,
kSYS_fchdir = 13,
kSYS_mknod = 14,
kSYS_chmod = 15,
kSYS_chown = 16,
kSYS_break = 17,
kSYS_freebsd4_getfsstat = 18,
kSYS_getpid = 20,
kSYS_mount = 21,
kSYS_unmount = 22,
kSYS_setuid = 23,
kSYS_getuid = 24,
kSYS_geteuid = 25,
kSYS_ptrace = 26,
kSYS_recvmsg = 27,
kSYS_sendmsg = 28,
kSYS_recvfrom = 29,
kSYS_accept = 30,
kSYS_getpeername = 31,
kSYS_getsockname = 32,
kSYS_access = 33,
kSYS_chflags = 34,
kSYS_fchflags = 35,
kSYS_sync = 36,
kSYS_kill = 37,
kSYS_getppid = 39,
kSYS_dup = 41,
kSYS_pipe = 42,
kSYS_getegid = 43,
kSYS_profil = 44,
kSYS_ktrace = 45,
kSYS_getgid = 47,
kSYS_getlogin = 49,
kSYS_setlogin = 50,
kSYS_acct = 51,
kSYS_sigaltstack = 53,
kSYS_ioctl = 54,
kSYS_reboot = 55,
kSYS_revoke = 56,
kSYS_symlink = 57,
kSYS_readlink = 58,
kSYS_execve = 59,
kSYS_umask = 60,
kSYS_chroot = 61,
kSYS_msync = 65,
kSYS_vfork = 66,
kSYS_sbrk = 69,
kSYS_sstk = 70,
kSYS_vadvise = 72,
kSYS_munmap = 73,
kSYS_mprotect = 74,
kSYS_madvise = 75,
kSYS_mincore = 78,
kSYS_getgroups = 79,
kSYS_setgroups = 80,
kSYS_getpgrp = 81,
kSYS_setpgid = 82,
kSYS_setitimer = 83,
kSYS_swapon = 85,
kSYS_getitimer = 86,
kSYS_getdtablesize = 89,
kSYS_dup2 = 90,
kSYS_fcntl = 92,
kSYS_select = 93,
kSYS_fsync = 95,
kSYS_setpriority = 96,
kSYS_socket = 97,
kSYS_connect = 98,
kSYS_getpriority = 100,
kSYS_bind = 104,
kSYS_setsockopt = 105,
kSYS_listen = 106,
kSYS_gettimeofday = 116,
kSYS_getrusage = 117,
kSYS_getsockopt = 118,
kSYS_readv = 120,
kSYS_writev = 121,
kSYS_settimeofday = 122,
kSYS_fchown = 123,
kSYS_fchmod = 124,
kSYS_setreuid = 126,
kSYS_setregid = 127,
kSYS_rename = 128,
kSYS_flock = 131,
kSYS_mkfifo = 132,
kSYS_sendto = 133,
kSYS_shutdown = 134,
kSYS_socketpair = 135,
kSYS_mkdir = 136,
kSYS_rmdir = 137,
kSYS_utimes = 138,
kSYS_adjtime = 140,
kSYS_setsid = 147,
kSYS_quotactl = 148,
kSYS_nlm_syscall = 154,
kSYS_nfssvc = 155,
kSYS_freebsd4_statfs = 157,
kSYS_freebsd4_fstatfs = 158,
kSYS_lgetfh = 160,
kSYS_getfh = 161,
kSYS_freebsd4_getdomainname = 162,
kSYS_freebsd4_setdomainname = 163,
kSYS_freebsd4_uname = 164,
kSYS_sysarch = 165,
kSYS_rtprio = 166,
kSYS_semsys = 169,
kSYS_msgsys = 170,
kSYS_shmsys = 171,
kSYS_freebsd6_pread = 173,
kSYS_freebsd6_pwrite = 174,
kSYS_setfib = 175,
kSYS_ntp_adjtime = 176,
kSYS_setgid = 181,
kSYS_setegid = 182,
kSYS_seteuid = 183,
kSYS_stat = 188,
kSYS_fstat = 189,
kSYS_lstat = 190,
kSYS_pathconf = 191,
kSYS_fpathconf = 192,
kSYS_getrlimit = 194,
kSYS_setrlimit = 195,
kSYS_getdirentries = 196,
kSYS_freebsd6_mmap = 197,
kSYS___syscall = 198,
kSYS_freebsd6_lseek = 199,
kSYS_freebsd6_truncate = 200,
kSYS_freebsd6_ftruncate = 201,
kSYS___sysctl = 202,
kSYS_mlock = 203,
kSYS_munlock = 204,
kSYS_undelete = 205,
kSYS_futimes = 206,
kSYS_getpgid = 207,
kSYS_poll = 209,
kSYS_freebsd7___semctl = 220,
kSYS_semget = 221,
kSYS_semop = 222,
kSYS_freebsd7_msgctl = 224,
kSYS_msgget = 225,
kSYS_msgsnd = 226,
kSYS_msgrcv = 227,
kSYS_shmat = 228,
kSYS_freebsd7_shmctl = 229,
kSYS_shmdt = 230,
kSYS_shmget = 231,
kSYS_clock_gettime = 232,
kSYS_clock_settime = 233,
kSYS_clock_getres = 234,
kSYS_ktimer_create = 235,
kSYS_ktimer_delete = 236,
kSYS_ktimer_settime = 237,
kSYS_ktimer_gettime = 238,
kSYS_ktimer_getoverrun = 239,
kSYS_nanosleep = 240,
kSYS_ffclock_getcounter = 241,
kSYS_ffclock_setestimate = 242,
kSYS_ffclock_getestimate = 243,
kSYS_clock_getcpuclockid2 = 247,
kSYS_ntp_gettime = 248,
kSYS_minherit = 250,
kSYS_rfork = 251,
kSYS_openbsd_poll = 252,
kSYS_issetugid = 253,
kSYS_lchown = 254,
kSYS_aio_read = 255,
kSYS_aio_write = 256,
kSYS_lio_listio = 257,
kSYS_getdents = 272,
kSYS_lchmod = 274,
kSYS_netbsd_lchown = 275,
kSYS_lutimes = 276,
kSYS_netbsd_msync = 277,
kSYS_nstat = 278,
kSYS_nfstat = 279,
kSYS_nlstat = 280,
kSYS_preadv = 289,
kSYS_pwritev = 290,
kSYS_freebsd4_fhstatfs = 297,
kSYS_fhopen = 298,
kSYS_fhstat = 299,
kSYS_modnext = 300,
kSYS_modstat = 301,
kSYS_modfnext = 302,
kSYS_modfind = 303,
kSYS_kldload = 304,
kSYS_kldunload = 305,
kSYS_kldfind = 306,
kSYS_kldnext = 307,
kSYS_kldstat = 308,
kSYS_kldfirstmod = 309,
kSYS_getsid = 310,
kSYS_setresuid = 311,
kSYS_setresgid = 312,
kSYS_aio_return = 314,
kSYS_aio_suspend = 315,
kSYS_aio_cancel = 316,
kSYS_aio_error = 317,
kSYS_oaio_read = 318,
kSYS_oaio_write = 319,
kSYS_olio_listio = 320,
kSYS_yield = 321,
kSYS_mlockall = 324,
kSYS_munlockall = 325,
kSYS___getcwd = 326,
kSYS_sched_setparam = 327,
kSYS_sched_getparam = 328,
kSYS_sched_setscheduler = 329,
kSYS_sched_getscheduler = 330,
kSYS_sched_yield = 331,
kSYS_sched_get_priority_max = 332,
kSYS_sched_get_priority_min = 333,
kSYS_sched_rr_get_interval = 334,
kSYS_utrace = 335,
kSYS_freebsd4_sendfile = 336,
kSYS_kldsym = 337,
kSYS_jail = 338,
kSYS_nnpfs_syscall = 339,
kSYS_sigprocmask = 340,
kSYS_sigsuspend = 341,
kSYS_freebsd4_sigaction = 342,
kSYS_sigpending = 343,
kSYS_freebsd4_sigreturn = 344,
kSYS_sigtimedwait = 345,
kSYS_sigwaitinfo = 346,
kSYS___acl_get_file = 347,
kSYS___acl_set_file = 348,
kSYS___acl_get_fd = 349,
kSYS___acl_set_fd = 350,
kSYS___acl_delete_file = 351,
kSYS___acl_delete_fd = 352,
kSYS___acl_aclcheck_file = 353,
kSYS___acl_aclcheck_fd = 354,
kSYS_extattrctl = 355,
kSYS_extattr_set_file = 356,
kSYS_extattr_get_file = 357,
kSYS_extattr_delete_file = 358,
kSYS_aio_waitcomplete = 359,
kSYS_getresuid = 360,
kSYS_getresgid = 361,
kSYS_kqueue = 362,
kSYS_kevent = 363,
kSYS_extattr_set_fd = 371,
kSYS_extattr_get_fd = 372,
kSYS_extattr_delete_fd = 373,
kSYS___setugid = 374,
kSYS_eaccess = 376,
kSYS_afs3_syscall = 377,
kSYS_nmount = 378,
kSYS___mac_get_proc = 384,
kSYS___mac_set_proc = 385,
kSYS___mac_get_fd = 386,
kSYS___mac_get_file = 387,
kSYS___mac_set_fd = 388,
kSYS___mac_set_file = 389,
kSYS_kenv = 390,
kSYS_lchflags = 391,
kSYS_uuidgen = 392,
kSYS_sendfile = 393,
kSYS_mac_syscall = 394,
kSYS_getfsstat = 395,
kSYS_statfs = 396,
kSYS_fstatfs = 397,
kSYS_fhstatfs = 398,
kSYS_ksem_close = 400,
kSYS_ksem_post = 401,
kSYS_ksem_wait = 402,
kSYS_ksem_trywait = 403,
kSYS_ksem_init = 404,
kSYS_ksem_open = 405,
kSYS_ksem_unlink = 406,
kSYS_ksem_getvalue = 407,
kSYS_ksem_destroy = 408,
kSYS___mac_get_pid = 409,
kSYS___mac_get_link = 410,
kSYS___mac_set_link = 411,
kSYS_extattr_set_link = 412,
kSYS_extattr_get_link = 413,
kSYS_extattr_delete_link = 414,
kSYS___mac_execve = 415,
kSYS_sigaction = 416,
kSYS_sigreturn = 417,
kSYS_getcontext = 421,
kSYS_setcontext = 422,
kSYS_swapcontext = 423,
kSYS_swapoff = 424,
kSYS___acl_get_link = 425,
kSYS___acl_set_link = 426,
kSYS___acl_delete_link = 427,
kSYS___acl_aclcheck_link = 428,
kSYS_sigwait = 429,
kSYS_thr_create = 430,
kSYS_thr_exit = 431,
kSYS_thr_self = 432,
kSYS_thr_kill = 433,
kSYS__umtx_lock = 434,
kSYS__umtx_unlock = 435,
kSYS_jail_attach = 436,
kSYS_extattr_list_fd = 437,
kSYS_extattr_list_file = 438,
kSYS_extattr_list_link = 439,
kSYS_ksem_timedwait = 441,
kSYS_thr_suspend = 442,
kSYS_thr_wake = 443,
kSYS_kldunloadf = 444,
kSYS_audit = 445,
kSYS_auditon = 446,
kSYS_getauid = 447,
kSYS_setauid = 448,
kSYS_getaudit = 449,
kSYS_setaudit = 450,
kSYS_getaudit_addr = 451,
kSYS_setaudit_addr = 452,
kSYS_auditctl = 453,
kSYS__umtx_op = 454,
kSYS_thr_new = 455,
kSYS_sigqueue = 456,
kSYS_kmq_open = 457,
kSYS_kmq_setattr = 458,
kSYS_kmq_timedreceive = 459,
kSYS_kmq_timedsend = 460,
kSYS_kmq_notify = 461,
kSYS_kmq_unlink = 462,
kSYS_abort2 = 463,
kSYS_thr_set_name = 464,
kSYS_aio_fsync = 465,
kSYS_rtprio_thread = 466,
kSYS_sctp_peeloff = 471,
kSYS_sctp_generic_sendmsg = 472,
kSYS_sctp_generic_sendmsg_iov = 473,
kSYS_sctp_generic_recvmsg = 474,
kSYS_pread = 475,
kSYS_pwrite = 476,
kSYS_mmap = 477,
kSYS_lseek = 478,
kSYS_truncate = 479,
kSYS_ftruncate = 480,
kSYS_thr_kill2 = 481,
kSYS_shm_open = 482,
kSYS_shm_unlink = 483,
kSYS_cpuset = 484,
kSYS_cpuset_setid = 485,
kSYS_cpuset_getid = 486,
kSYS_cpuset_getaffinity = 487,
kSYS_cpuset_setaffinity = 488,
kSYS_faccessat = 489,
kSYS_fchmodat = 490,
kSYS_fchownat = 491,
kSYS_fexecve = 492,
kSYS_fstatat = 493,
kSYS_futimesat = 494,
kSYS_linkat = 495,
kSYS_mkdirat = 496,
kSYS_mkfifoat = 497,
kSYS_mknodat = 498,
kSYS_openat = 499,
kSYS_readlinkat = 500,
kSYS_renameat = 501,
kSYS_symlinkat = 502,
kSYS_unlinkat = 503,
kSYS_posix_openpt = 504,
kSYS_gssd_syscall = 505,
kSYS_jail_get = 506,
kSYS_jail_set = 507,
kSYS_jail_remove = 508,
kSYS_closefrom = 509,
kSYS___semctl = 510,
kSYS_msgctl = 511,
kSYS_shmctl = 512,
kSYS_lpathconf = 513,
kSYS_cap_new = 514,
kSYS_cap_getrights = 515,
kSYS_cap_enter = 516,
kSYS_cap_getmode = 517,
kSYS_pdfork = 518,
kSYS_pdkill = 519,
kSYS_pdgetpid = 520,
kSYS_pselect = 522,
kSYS_getloginclass = 523,
kSYS_setloginclass = 524,
kSYS_rctl_get_racct = 525,
kSYS_rctl_get_rules = 526,
kSYS_rctl_get_limits = 527,
kSYS_rctl_add_rule = 528,
kSYS_rctl_remove_rule = 529,
kSYS_posix_fallocate = 530,
kSYS_posix_fadvise = 531,
kSYS_netcontrol = 99,
kSYS_netabort = 101,
kSYS_netgetsockinfo = 102,
kSYS_socketex = 113,
kSYS_socketclose = 114,
kSYS_netgetiflist = 125,
kSYS_kqueueex = 141,
kSYS_mtypeprotect = 379,
kSYS_regmgr_call = 532,
kSYS_jitshm_create = 533,
kSYS_jitshm_alias = 534,
kSYS_dl_get_list = 535,
kSYS_dl_get_info = 536,
kSYS_dl_notify_event = 537,
kSYS_evf_create = 538,
kSYS_evf_delete = 539,
kSYS_evf_open = 540,
kSYS_evf_close = 541,
kSYS_evf_wait = 542,
kSYS_evf_trywait = 543,
kSYS_evf_set = 544,
kSYS_evf_clear = 545,
kSYS_evf_cancel = 546,
kSYS_query_memory_protection = 547,
kSYS_batch_map = 548,
kSYS_osem_create = 549,
kSYS_osem_delete = 550,
kSYS_osem_open = 551,
kSYS_osem_close = 552,
kSYS_osem_wait = 553,
kSYS_osem_trywait = 554,
kSYS_osem_post = 555,
kSYS_osem_cancel = 556,
kSYS_namedobj_create = 557,
kSYS_namedobj_delete = 558,
kSYS_set_vm_container = 559,
kSYS_debug_init = 560,
kSYS_suspend_process = 561,
kSYS_resume_process = 562,
kSYS_opmc_enable = 563,
kSYS_opmc_disable = 564,
kSYS_opmc_set_ctl = 565,
kSYS_opmc_set_ctr = 566,
kSYS_opmc_get_ctr = 567,
kSYS_budget_create = 568,
kSYS_budget_delete = 569,
kSYS_budget_get = 570,
kSYS_budget_set = 571,
kSYS_virtual_query = 572,
kSYS_mdbg_call = 573,
kSYS_obs_sblock_create = 574,
kSYS_obs_sblock_delete = 575,
kSYS_obs_sblock_enter = 576,
kSYS_obs_sblock_exit = 577,
kSYS_obs_sblock_xenter = 578,
kSYS_obs_sblock_xexit = 579,
kSYS_obs_eport_create = 580,
kSYS_obs_eport_delete = 581,
kSYS_obs_eport_trigger = 582,
kSYS_obs_eport_open = 583,
kSYS_obs_eport_close = 584,
kSYS_is_in_sandbox = 585,
kSYS_dmem_container = 586,
kSYS_get_authinfo = 587,
kSYS_mname = 588,
kSYS_dynlib_dlopen = 589,
kSYS_dynlib_dlclose = 590,
kSYS_dynlib_dlsym = 591,
kSYS_dynlib_get_list = 592,
kSYS_dynlib_get_info = 593,
kSYS_dynlib_load_prx = 594,
kSYS_dynlib_unload_prx = 595,
kSYS_dynlib_do_copy_relocations = 596,
kSYS_dynlib_prepare_dlclose = 597,
kSYS_dynlib_get_proc_param = 598,
kSYS_dynlib_process_needed_and_relocate = 599,
kSYS_sandbox_path = 600,
kSYS_mdbg_service = 601,
kSYS_randomized_path = 602,
kSYS_rdup = 603,
kSYS_dl_get_metadata = 604,
kSYS_workaround8849 = 605,
kSYS_is_development_mode = 606,
kSYS_get_self_auth_info = 607,
kSYS_dynlib_get_info_ex = 608,
kSYS_budget_getid = 609,
kSYS_budget_get_ptype = 610,
kSYS_get_paging_stats_of_all_threads = 611,
kSYS_get_proc_type_info = 612,
kSYS_get_resident_count = 613,
kSYS_prepare_to_suspend_process = 614,
kSYS_get_resident_fmem_count = 615,
kSYS_thr_get_name = 616,
kSYS_set_gpo = 617,
kSYS_get_paging_stats_of_all_objects = 618,
kSYS_test_debug_rwmem = 619,
kSYS_free_stack = 620,
kSYS_suspend_system = 621,
kSYS_ipmimgr_call = 622,
kSYS_get_gpo = 623,
kSYS_get_vm_map_timestamp = 624,
kSYS_opmc_set_hw = 625,
kSYS_opmc_get_hw = 626,
kSYS_get_cpu_usage_all = 627,
kSYS_mmap_dmem = 628,
kSYS_physhm_open = 629,
kSYS_physhm_unlink = 630,
kSYS_resume_internal_hdd = 631,
kSYS_thr_suspend_ucontext = 632,
kSYS_thr_resume_ucontext = 633,
kSYS_thr_get_ucontext = 634,
kSYS_thr_set_ucontext = 635,
kSYS_set_timezone_info = 636,
kSYS_set_phys_fmem_limit = 637,
kSYS_utc_to_localtime = 638,
kSYS_localtime_to_utc = 639,
kSYS_set_uevt = 640,
kSYS_get_cpu_usage_proc = 641,
kSYS_get_map_statistics = 642,
kSYS_set_chicken_switches = 643,
kSYS_extend_page_table_pool = 644,
kSYS_extend_page_table_pool2 = 645,
kSYS_get_kernel_mem_statistics = 646,
kSYS_get_sdk_compiled_version = 647,
kSYS_app_state_change = 648,
kSYS_dynlib_get_obj_member = 649,
kSYS_budget_get_ptype_of_budget = 650,
kSYS_prepare_to_resume_process = 651,
kSYS_process_terminate = 652,
kSYS_blockpool_open = 653,
kSYS_blockpool_map = 654,
kSYS_blockpool_unmap = 655,
kSYS_dynlib_get_info_for_libdbg = 656,
kSYS_blockpool_batch = 657,
kSYS_fdatasync = 658,
kSYS_dynlib_get_list2 = 659,
kSYS_dynlib_get_info2 = 660,
kSYS_aio_submit = 661,
kSYS_aio_multi_delete = 662,
kSYS_aio_multi_wait = 663,
kSYS_aio_multi_poll = 664,
kSYS_aio_get_data = 665,
kSYS_aio_multi_cancel = 666,
kSYS_get_bio_usage_all = 667,
kSYS_aio_create = 668,
kSYS_aio_submit_cmd = 669,
kSYS_aio_init = 670,
kSYS_get_page_table_stats = 671,
kSYS_dynlib_get_list_for_libdbg = 672,
kSYS_blockpool_move = 673,
kSYS_virtual_query_all = 674,
kSYS_reserve_2mb_page = 675,
kSYS_cpumode_yield = 676,
kSYS_wait6 = 677,
kSYS_cap_rights_limit = 678,
kSYS_cap_ioctls_limit = 679,
kSYS_cap_ioctls_get = 680,
kSYS_cap_fcntls_limit = 681,
kSYS_cap_fcntls_get = 682,
kSYS_bindat = 683,
kSYS_connectat = 684,
kSYS_chflagsat = 685,
kSYS_accept4 = 686,
kSYS_pipe2 = 687,
kSYS_aio_mlock = 688,
kSYS_procctl = 689,
kSYS_ppoll = 690,
kSYS_futimens = 691,
kSYS_utimensat = 692,
kSYS_numa_getaffinity = 693,
kSYS_numa_setaffinity = 694,
kSYS_apr_submit = 700,
kSYS_apr_resolve = 701,
kSYS_apr_stat = 702,
kSYS_apr_wait = 703,
kSYS_apr_ctrl = 704,
kSYS_get_phys_page_size = 705,
kSYS_begin_app_mount = 706,
kSYS_end_app_mount = 707,
kSYS_fsc2h_ctrl = 708,
kSYS_streamwrite = 709,
kSYS_app_save = 710,
kSYS_app_restore = 711,
kSYS_saved_app_delete = 712,
kSYS_get_ppr_sdk_compiled_version = 713,
kSYS_notify_app_event = 714,
kSYS_ioreq = 715,
kSYS_openintr = 716,
kSYS_dl_get_info_2 = 717,
kSYS_acinfo_add = 718,
kSYS_acinfo_delete = 719,
kSYS_acinfo_get_all_for_coredump = 720,
kSYS_ampr_ctrl_debug = 721,
kSYS_workspace_ctrl = 722,
};
} // namespace orbis

View file

@ -0,0 +1,15 @@
#pragma once
#include "orbis-config.hpp"
#include "orbis/thread/sysent.hpp"
namespace orbis {
extern sysentvec freebsd9_sysvec;
extern sysentvec freebsd11_sysvec;
extern sysentvec ps4_sysvec;
extern sysentvec ps5_sysvec;
struct Thread;
void syscall_entry(Thread *thread);
const char *getSysentName(SysResult (*sysent)(Thread *, uint64_t *));
} // namespace orbis

View file

@ -0,0 +1,593 @@
#include <orbis/error.hpp>
#include <orbis/thread.hpp>
#include <array>
namespace orbis {
using acl_type_t = sint;
using key_t = sint;
using semid_t = uint64_t;
using cpusetid_t = sint;
using cpuwhich_t = sint;
using cpulevel_t = sint;
using SceKernelModule = ModuleHandle;
struct ModuleInfo;
struct ModuleInfoEx;
struct stack_t;
SysResult nosys(Thread *thread);
SysResult sys_exit(Thread *thread, sint status);
SysResult sys_fork(Thread *thread);
SysResult sys_read(Thread *thread, sint fd, ptr<void> buf, size_t nbyte);
SysResult sys_write(Thread *thread, sint fd, ptr<const void> buf, size_t nbyte);
SysResult sys_open(Thread *thread, ptr<char> path, sint flags, sint mode);
SysResult sys_close(Thread *thread, sint fd);
SysResult sys_wait4(Thread *thread, sint pid, ptr<sint> status, sint options, ptr<struct rusage> rusage);
SysResult sys_link(Thread *thread, ptr<char> path, ptr<char> link);
SysResult sys_unlink(Thread *thread, ptr<char> path);
SysResult sys_chdir(Thread *thread, ptr<char> path);
SysResult sys_fchdir(Thread *thread, sint fd);
SysResult sys_mknod(Thread *thread, ptr<char> path, sint mode, sint dev);
SysResult sys_chmod(Thread *thread, ptr<char> path, sint mode);
SysResult sys_chown(Thread *thread, ptr<char> path, sint uid, sint gid);
SysResult sys_obreak(Thread *thread, ptr<char> nsize);
SysResult sys_getpid(Thread *thread);
SysResult sys_mount(Thread *thread, ptr<char> type, ptr<char> path, sint flags, caddr_t data);
SysResult sys_unmount(Thread *thread, ptr<char> path, sint flags);
SysResult sys_setuid(Thread *thread, uid_t uid);
SysResult sys_getuid(Thread *thread);
SysResult sys_geteuid(Thread *thread);
SysResult sys_ptrace(Thread *thread, sint req, pid_t pid, caddr_t addr, sint data);
SysResult sys_recvmsg(Thread *thread, sint s, ptr<struct msghdr> msg, sint flags);
SysResult sys_sendmsg(Thread *thread, sint s, ptr<struct msghdr> msg, sint flags);
SysResult sys_recvfrom(Thread *thread, sint s, caddr_t buf, size_t len, sint flags, ptr<struct sockaddr> from, ptr<uint32_t> fromlenaddr);
SysResult sys_accept(Thread *thread, sint s, ptr<struct sockaddr> from, ptr<uint32_t> fromlenaddr);
SysResult sys_getpeername(Thread *thread, sint fdes, ptr<struct sockaddr> asa, ptr<uint32_t> alen);
SysResult sys_getsockname(Thread *thread, sint fdes, ptr<struct sockaddr> asa, ptr<uint32_t> alen);
SysResult sys_access(Thread *thread, ptr<char> path, sint flags);
SysResult sys_chflags(Thread *thread, ptr<char> path, sint flags);
SysResult sys_fchflags(Thread *thread, sint fd, sint flags);
SysResult sys_sync(Thread *thread);
SysResult sys_kill(Thread *thread, sint pid, sint signum);
SysResult sys_getppid(Thread *thread);
SysResult sys_dup(Thread *thread, uint fd);
SysResult sys_pipe(Thread *thread);
SysResult sys_getegid(Thread *thread);
SysResult sys_profil(Thread *thread, caddr_t samples, size_t size, size_t offset, uint scale);
SysResult sys_ktrace(Thread *thread, ptr<const char> fname, sint ops, sint facs, sint pit);
SysResult sys_getgid(Thread *thread);
SysResult sys_getlogin(Thread *thread, ptr<char> namebuf, uint namelen);
SysResult sys_setlogin(Thread *thread, ptr<char> namebuf);
SysResult sys_acct(Thread *thread, ptr<char> path);
SysResult sys_sigaltstack(Thread *thread, ptr<stack_t> ss, ptr<stack_t> oss);
SysResult sys_ioctl(Thread *thread, sint fd, ulong com, caddr_t data);
SysResult sys_reboot(Thread *thread, sint opt);
SysResult sys_revoke(Thread *thread, ptr<char> path);
SysResult sys_symlink(Thread *thread, ptr<char> path, ptr<char> link);
SysResult sys_readlink(Thread *thread, ptr<char> path, ptr<char> buf, size_t count);
SysResult sys_execve(Thread *thread, ptr<char> fname, ptr<ptr<char>> argv, ptr<ptr<char>> envv);
SysResult sys_umask(Thread *thread, sint newmask);
SysResult sys_chroot(Thread *thread, ptr<char> path);
SysResult sys_msync(Thread *thread, ptr<void> addr, size_t len, sint flags);
SysResult sys_vfork(Thread *thread);
SysResult sys_sbrk(Thread *thread, sint incr);
SysResult sys_sstk(Thread *thread, sint incr);
SysResult sys_ovadvise(Thread *thread, sint anom);
SysResult sys_munmap(Thread *thread, ptr<void> addr, size_t len);
SysResult sys_mprotect(Thread *thread, ptr<const void> addr, size_t len, sint prot);
SysResult sys_madvise(Thread *thread, ptr<void> addr, size_t len, sint behav);
SysResult sys_mincore(Thread *thread, ptr<const void> addr, size_t len, ptr<char> vec);
SysResult sys_getgroups(Thread *thread, uint gidsetsize, ptr<gid_t> gidset);
SysResult sys_setgroups(Thread *thread, uint gidsetsize, ptr<gid_t> gidset);
SysResult sys_getpgrp(Thread *thread);
SysResult sys_setpgid(Thread *thread, sint pid, sint pgid);
SysResult sys_setitimer(Thread *thread, uint which, ptr<struct itimerval> itv, ptr<struct itimerval> oitv);
SysResult sys_swapon(Thread *thread, ptr<char> name);
SysResult sys_getitimer(Thread *thread, uint which, ptr<struct itimerval> itv);
SysResult sys_getdtablesize(Thread *thread);
SysResult sys_dup2(Thread *thread, uint from, uint to);
SysResult sys_fcntl(Thread *thread, sint fd, sint cmd, slong arg);
SysResult sys_select(Thread *thread, sint nd, ptr<struct fd_set_t> in, ptr<struct fd_set_t> out, ptr<struct fd_set_t> ex, ptr<struct timeval> tv);
SysResult sys_fsync(Thread *thread, sint fd);
SysResult sys_setpriority(Thread *thread, sint which, sint who, sint prio);
SysResult sys_socket(Thread *thread, sint domain, sint type, sint protocol);
SysResult sys_connect(Thread *thread, sint s, caddr_t name, sint namelen);
SysResult sys_getpriority(Thread *thread, sint which, sint who);
SysResult sys_bind(Thread *thread, sint s, caddr_t name, sint namelen);
SysResult sys_setsockopt(Thread *thread, sint s, sint level, sint name, caddr_t val, sint valsize);
SysResult sys_listen(Thread *thread, sint s, sint backlog);
SysResult sys_gettimeofday(Thread *thread, ptr<struct timeval> tp, ptr<struct timezone> tzp);
SysResult sys_getrusage(Thread *thread, sint who, ptr<struct rusage> rusage);
SysResult sys_getsockopt(Thread *thread, sint s, sint level, sint name, caddr_t val, ptr<sint> avalsize);
SysResult sys_readv(Thread *thread, sint fd, ptr<struct iovec> iovp, uint iovcnt);
SysResult sys_writev(Thread *thread, sint fd, ptr<struct iovec> iovp, uint iovcnt);
SysResult sys_settimeofday(Thread *thread, ptr<struct timeval> tp, ptr<struct timezone> tzp);
SysResult sys_fchown(Thread *thread, sint fd, sint uid, sint gid);
SysResult sys_fchmod(Thread *thread, sint fd, sint mode);
SysResult sys_setreuid(Thread *thread, sint ruid, sint euid);
SysResult sys_setregid(Thread *thread, sint rgid, sint egid);
SysResult sys_rename(Thread *thread, ptr<char> from, ptr<char> to);
SysResult sys_flock(Thread *thread, sint fd, sint how);
SysResult sys_mkfifo(Thread *thread, ptr<char> path, sint mode);
SysResult sys_sendto(Thread *thread, sint s, caddr_t buf, size_t len, sint flags, caddr_t to, sint tolen);
SysResult sys_shutdown(Thread *thread, sint s, sint how);
SysResult sys_socketpair(Thread *thread, sint domain, sint type, sint protocol, ptr<sint> rsv);
SysResult sys_mkdir(Thread *thread, ptr<char> path, sint mode);
SysResult sys_rmdir(Thread *thread, ptr<char> path);
SysResult sys_utimes(Thread *thread, ptr<char> path, ptr<struct timeval> tptr);
SysResult sys_adjtime(Thread *thread, ptr<struct timeval> delta, ptr<struct timeval> olddelta);
SysResult sys_setsid(Thread *thread);
SysResult sys_quotactl(Thread *thread, ptr<char> path, sint cmd, sint uid, caddr_t arg);
SysResult sys_nlm_syscall(Thread *thread, sint debug_level, sint grace_period, sint addr_count, ptr<ptr<char>> addrs);
SysResult sys_nfssvc(Thread *thread, sint flag, caddr_t argp);
SysResult sys_lgetfh(Thread *thread, ptr<char> fname, ptr<struct fhandle> fhp);
SysResult sys_getfh(Thread *thread, ptr<char> fname, ptr<struct fhandle> fhp);
SysResult sys_sysarch(Thread *thread, sint op, ptr<char> parms);
SysResult sys_rtprio(Thread *thread, sint function, pid_t pid, ptr<struct rtprio> rtp);
SysResult sys_semsys(Thread *thread, sint which, sint a2, sint a3, sint a4, sint a5);
SysResult sys_msgsys(Thread *thread, sint which, sint a2, sint a3, sint a4, sint a5, sint a6);
SysResult sys_shmsys(Thread *thread, sint which, sint a2, sint a3, sint a4);
SysResult sys_freebsd6_pread(Thread *thread, sint fd, ptr<void> buf, size_t nbyte, sint pad, off_t offset);
SysResult sys_freebsd6_pwrite(Thread *thread, sint fd, ptr<const void> buf, size_t nbyte, sint pad, off_t offset);
SysResult sys_setfib(Thread *thread, sint fib);
SysResult sys_ntp_adjtime(Thread *thread, ptr<struct timex> tp);
SysResult sys_setgid(Thread *thread, gid_t gid);
SysResult sys_setegid(Thread *thread, gid_t egid);
SysResult sys_seteuid(Thread *thread, uid_t euid);
SysResult sys_stat(Thread *thread, ptr<char> path, ptr<struct stat> ub);
SysResult sys_fstat(Thread *thread, sint fd, ptr<struct stat> ub);
SysResult sys_lstat(Thread *thread, ptr<char> path, ptr<struct stat> ub);
SysResult sys_pathconf(Thread *thread, ptr<char> path, sint name);
SysResult sys_fpathconf(Thread *thread, sint fd, sint name);
SysResult sys_getrlimit(Thread *thread, uint which, ptr<struct rlimit> rlp);
SysResult sys_setrlimit(Thread *thread, uint which, ptr<struct rlimit> rlp);
SysResult sys_getdirentries(Thread *thread, sint fd, ptr<char> buf, uint count, ptr<slong> basep);
SysResult sys_freebsd6_mmap(Thread *thread, caddr_t addr, size_t len, sint prot, sint flags, sint fd, sint pad, off_t pos);
SysResult sys_freebsd6_lseek(Thread *thread, sint fd, sint pad, off_t offset, sint whence);
SysResult sys_freebsd6_truncate(Thread *thread, ptr<char> path, sint pad, off_t length);
SysResult sys_freebsd6_ftruncate(Thread *thread, sint fd, sint pad, off_t length);
SysResult sys___sysctl(Thread *thread, ptr<sint> name, uint namelen, ptr<void> old, ptr<size_t> oldenp, ptr<void> new_, size_t newlen);
SysResult sys_mlock(Thread *thread, ptr<const void> addr, size_t len);
SysResult sys_munlock(Thread *thread, ptr<const void> addr, size_t len);
SysResult sys_undelete(Thread *thread, ptr<char> path);
SysResult sys_futimes(Thread *thread, sint fd, ptr<struct timeval> tptr);
SysResult sys_getpgid(Thread *thread, pid_t pid);
SysResult sys_poll(Thread *thread, ptr<struct pollfd> fds, uint nfds, sint timeout);
SysResult sys_semget(Thread *thread, key_t key, sint nsems, sint semflg);
SysResult sys_semop(Thread *thread, sint semid, ptr<struct sembuf> sops, size_t nspos);
SysResult sys_msgget(Thread *thread, key_t key, sint msgflg);
SysResult sys_msgsnd(Thread *thread, sint msqid, ptr<const void> msgp, size_t msgsz, sint msgflg);
SysResult sys_msgrcv(Thread *thread, sint msqid, ptr<void> msgp, size_t msgsz, slong msgtyp, sint msgflg);
SysResult sys_shmat(Thread *thread, sint shmid, ptr<const void> shmaddr, sint shmflg);
SysResult sys_shmdt(Thread *thread, ptr<const void> shmaddr);
SysResult sys_shmget(Thread *thread, key_t key, size_t size, sint shmflg);
SysResult sys_clock_gettime(Thread *thread, clockid_t clock_id, ptr<struct timespec> tp);
SysResult sys_clock_settime(Thread *thread, clockid_t clock_id, ptr<const struct timespec> tp);
SysResult sys_clock_getres(Thread *thread, clockid_t clock_id, ptr<struct timespec> tp);
SysResult sys_ktimer_create(Thread *thread, clockid_t clock_id, ptr<struct sigevent> evp, ptr<sint> timerid);
SysResult sys_ktimer_delete(Thread *thread, sint timerid);
SysResult sys_ktimer_settime(Thread *thread, sint timerid, sint flags, ptr<const struct itimerspec> value, ptr<struct itimerspec> ovalue);
SysResult sys_ktimer_gettime(Thread *thread, sint timerid, ptr<struct itimerspec> value);
SysResult sys_ktimer_getoverrun(Thread *thread, sint timerid);
SysResult sys_nanosleep(Thread *thread, ptr<const struct timespec> rqtp, ptr<struct timespec> rmtp);
SysResult sys_ntp_gettime(Thread *thread, ptr<struct ntptimeval> ntvp);
SysResult sys_minherit(Thread *thread, ptr<void> addr, size_t len, sint inherit);
SysResult sys_rfork(Thread *thread, sint flags);
SysResult sys_openbsd_poll(Thread *thread, ptr<struct pollfd> fds, uint nfds, sint timeout);
SysResult sys_issetugid(Thread *thread);
SysResult sys_lchown(Thread *thread, ptr<char> path, sint uid, sint gid);
SysResult sys_aio_read(Thread *thread, ptr<struct aiocb> aiocbp);
SysResult sys_aio_write(Thread *thread, ptr<struct aiocb> aiocbp);
SysResult sys_lio_listio(Thread *thread, sint mode, ptr<cptr<struct aiocb>> aiocbp, sint nent, ptr<struct sigevent> sig);
SysResult sys_getdents(Thread *thread, sint fd, ptr<char> buf, size_t count);
SysResult sys_lchmod(Thread *thread, ptr<char> path, mode_t mode);
SysResult sys_lutimes(Thread *thread, ptr<char> path, ptr<struct timeval> tptr);
SysResult sys_nstat(Thread *thread, ptr<char> path, ptr<struct nstat> ub);
SysResult sys_nfstat(Thread *thread, sint fd, ptr<struct nstat> sb);
SysResult sys_nlstat(Thread *thread, ptr<char> path, ptr<struct nstat> ub);
SysResult sys_preadv(Thread *thread, sint fd, ptr<struct iovec> iovp, uint iovcnt, off_t offset);
SysResult sys_pwritev(Thread *thread, sint fd, ptr<struct iovec> iovp, uint iovcnt, off_t offset);
SysResult sys_fhopen(Thread *thread, ptr<const struct fhandle> u_fhp, sint flags);
SysResult sys_fhstat(Thread *thread, ptr<const struct fhandle> u_fhp, ptr<struct stat> sb);
SysResult sys_modnext(Thread *thread, sint modid);
SysResult sys_modstat(Thread *thread, sint modid, ptr<struct module_stat> stat);
SysResult sys_modfnext(Thread *thread, sint modid);
SysResult sys_modfind(Thread *thread, ptr<const char> name);
SysResult sys_kldload(Thread *thread, ptr<const char> file);
SysResult sys_kldunload(Thread *thread, sint fileid);
SysResult sys_kldfind(Thread *thread, ptr<const char> name);
SysResult sys_kldnext(Thread *thread, sint fileid);
SysResult sys_kldstat(Thread *thread, sint fileid, ptr<struct kld_file_stat> stat);
SysResult sys_kldfirstmod(Thread *thread, sint fileid);
SysResult sys_getsid(Thread *thread, pid_t pid);
SysResult sys_setresuid(Thread *thread, uid_t ruid, uid_t euid, uid_t suid);
SysResult sys_setresgid(Thread *thread, gid_t rgid, gid_t egid, gid_t sgid);
SysResult sys_aio_return(Thread *thread, ptr<struct aiocb> aiocbp);
SysResult sys_aio_suspend(Thread *thread, ptr<struct aiocb> aiocbp, sint nent, ptr<const struct timespec> timeout);
SysResult sys_aio_cancel(Thread *thread, sint fd, ptr<struct aiocb> aiocbp);
SysResult sys_aio_error(Thread *thread, ptr<struct aiocb> aiocbp);
SysResult sys_oaio_read(Thread *thread, ptr<struct aiocb> aiocbp);
SysResult sys_oaio_write(Thread *thread, ptr<struct aiocb> aiocbp);
SysResult sys_olio_listio(Thread *thread, sint mode, ptr<cptr<struct aiocb>> acb_list, sint nent, ptr<struct osigevent> sig);
SysResult sys_yield(Thread *thread);
SysResult sys_mlockall(Thread *thread, sint how);
SysResult sys_munlockall(Thread *thread);
SysResult sys___getcwd(Thread *thread, ptr<char> buf, uint buflen);
SysResult sys_sched_setparam(Thread *thread, pid_t pid, ptr<const struct sched_param> param);
SysResult sys_sched_getparam(Thread *thread, pid_t pid, ptr<struct sched_param> param);
SysResult sys_sched_setscheduler(Thread *thread, pid_t pid, sint policy, ptr<const struct sched_param> param);
SysResult sys_sched_getscheduler(Thread *thread, pid_t pid);
SysResult sys_sched_yield(Thread *thread);
SysResult sys_sched_get_priority_max(Thread *thread, sint policy);
SysResult sys_sched_get_priority_min(Thread *thread, sint policy);
SysResult sys_sched_rr_get_interval(Thread *thread, pid_t pid, ptr<struct timespec> interval);
SysResult sys_utrace(Thread *thread, ptr<const void> addr, size_t len);
SysResult sys_kldsym(Thread *thread, sint fileid, sint cmd, ptr<void> data);
SysResult sys_jail(Thread *thread, ptr<struct jail> jail);
SysResult sys_nnpfs_syscall(Thread *thread, sint operation, ptr<char> a_pathP, sint opcode, ptr<void> a_paramsP, sint a_followSymlinks);
SysResult sys_sigprocmask(Thread *thread, sint how, ptr<uint64_t> set, ptr<uint64_t> oset);
SysResult sys_sigsuspend(Thread *thread, ptr<const struct sigset> set);
SysResult sys_sigpending(Thread *thread, ptr<struct sigset> set);
SysResult sys_sigtimedwait(Thread *thread, ptr<const struct sigset> set, ptr<struct siginfo> info, ptr<const struct timespec> timeout);
SysResult sys_sigwaitinfo(Thread *thread, ptr<const struct sigset> set, ptr<struct siginfo> info);
SysResult sys___acl_get_file(Thread *thread, ptr<char> path, acl_type_t type, ptr<struct acl> aclp);
SysResult sys___acl_set_file(Thread *thread, ptr<char> path, acl_type_t type, ptr<struct acl> aclp);
SysResult sys___acl_get_fd(Thread *thread, sint filedes, acl_type_t type, ptr<struct acl> aclp);
SysResult sys___acl_set_fd(Thread *thread, sint filedes, acl_type_t type, ptr<struct acl> aclp);
SysResult sys___acl_delete_file(Thread *thread, ptr<char> path, acl_type_t type);
SysResult sys___acl_delete_fd(Thread *thread, sint filedes, acl_type_t type);
SysResult sys___acl_aclcheck_file(Thread *thread, ptr<char> path, acl_type_t type, ptr<struct acl> aclp);
SysResult sys___acl_aclcheck_fd(Thread *thread, sint filedes, acl_type_t type, ptr<struct acl> aclp);
SysResult sys_extattrctl(Thread *thread, ptr<char> path, char cmd, ptr<const char> filename, sint attrnamespace, ptr<const char> attrname);
SysResult sys_extattr_set_file(Thread *thread, ptr<char> path, sint attrnamespace, ptr<const char> filename, ptr<void> data, size_t nbytes);
SysResult sys_extattr_get_file(Thread *thread, ptr<char> path, sint attrnamespace, ptr<const char> filename, ptr<void> data, size_t nbytes);
SysResult sys_extattr_delete_file(Thread *thread, ptr<char> path, sint attrnamespace, ptr<const char> attrname);
SysResult sys_aio_waitcomplete(Thread *thread, ptr<ptr<struct aiocb>> aiocbp, ptr<struct timespec> timeout);
SysResult sys_getresuid(Thread *thread, ptr<uid_t> ruid, ptr<uid_t> euid, ptr<uid_t> suid);
SysResult sys_getresgid(Thread *thread, ptr<gid_t> rgid, ptr<gid_t> egid, ptr<gid_t> sgid);
SysResult sys_kqueue(Thread *thread);
SysResult sys_kevent(Thread *thread, sint fd, ptr<struct kevent> changelist, sint nchanges, ptr<struct kevent> eventlist, sint nevents, ptr<const struct timespec> timeout);
SysResult sys_extattr_set_fd(Thread *thread, sint fd, sint attrnamespace, ptr<const char> attrname, ptr<void> data, size_t nbytes);
SysResult sys_extattr_get_fd(Thread *thread, sint fd, sint attrnamespace, ptr<const char> attrname, ptr<void> data, size_t nbytes);
SysResult sys_extattr_delete_fd(Thread *thread, sint fd, sint attrnamespace, ptr<const char> attrname);
SysResult sys___setugid(Thread *thread, sint flags);
SysResult sys_eaccess(Thread *thread, ptr<char> path, sint flags);
SysResult sys_afs3_syscall(Thread *thread, slong syscall, slong param1, slong param2, slong param3, slong param4, slong param5, slong param6);
SysResult sys_nmount(Thread *thread, ptr<struct iovec> iovp, uint iovcnt, sint flags);
SysResult sys___mac_get_proc(Thread *thread, ptr<struct mac> mac_p);
SysResult sys___mac_set_proc(Thread *thread, ptr<struct mac> mac_p);
SysResult sys___mac_get_fd(Thread *thread, sint fd, ptr<struct mac> mac_p);
SysResult sys___mac_get_file(Thread *thread, ptr<const char> path, ptr<struct mac> mac_p);
SysResult sys___mac_set_fd(Thread *thread, sint fd, ptr<struct mac> mac_p);
SysResult sys___mac_set_file(Thread *thread, ptr<const char> path, ptr<struct mac> mac_p);
SysResult sys_kenv(Thread *thread, sint what, ptr<const char> name, ptr<char> value, sint len);
SysResult sys_lchflags(Thread *thread, ptr<const char> path, sint flags);
SysResult sys_uuidgen(Thread *thread, ptr<struct uuid> store, sint count);
SysResult sys_sendfile(Thread *thread, sint fd, sint s, off_t offset, size_t nbytes, ptr<struct sf_hdtr> hdtr, ptr<off_t> sbytes, sint flags);
SysResult sys_mac_syscall(Thread *thread, ptr<const char> policy, sint call, ptr<void> arg);
SysResult sys_getfsstat(Thread *thread, ptr<struct statfs> buf, slong bufsize, sint flags);
SysResult sys_statfs(Thread *thread, ptr<char> path, ptr<struct statfs> buf);
SysResult sys_fstatfs(Thread *thread, sint fd, ptr<struct statfs> buf);
SysResult sys_fhstatfs(Thread *thread, ptr<const struct fhandle> u_fhp, ptr<struct statfs> buf);
SysResult sys_ksem_close(Thread *thread, semid_t id);
SysResult sys_ksem_post(Thread *thread, semid_t id);
SysResult sys_ksem_wait(Thread *thread, semid_t id);
SysResult sys_ksem_trywait(Thread *thread, semid_t id);
SysResult sys_ksem_init(Thread *thread, ptr<semid_t> idp, uint value);
SysResult sys_ksem_open(Thread *thread, ptr<semid_t> idp, ptr<const char> name, sint oflag, mode_t mode, uint value);
SysResult sys_ksem_unlink(Thread *thread, ptr<const char> name);
SysResult sys_ksem_getvalue(Thread *thread, semid_t id, ptr<sint> value);
SysResult sys_ksem_destroy(Thread *thread, semid_t id);
SysResult sys___mac_get_pid(Thread *thread, pid_t pid, ptr<struct mac> mac_p);
SysResult sys___mac_get_link(Thread *thread, ptr<const char> path_p, ptr<struct mac> mac_p);
SysResult sys___mac_set_link(Thread *thread, ptr<const char> path_p, ptr<struct mac> mac_p);
SysResult sys_extattr_set_link(Thread *thread, ptr<const char> path, sint attrnamespace, ptr<const char> attrname, ptr<void> data, size_t nbytes);
SysResult sys_extattr_get_link(Thread *thread, ptr<const char> path, sint attrnamespace, ptr<const char> attrname, ptr<void> data, size_t nbytes);
SysResult sys_extattr_delete_link(Thread *thread, ptr<const char> path, sint attrnamespace, ptr<const char> attrname);
SysResult sys___mac_execve(Thread *thread, ptr<char> fname, ptr<ptr<char>> argv, ptr<ptr<char>> envv, ptr<struct mac> mac_p);
SysResult sys_sigaction(Thread *thread, sint sig, ptr<struct sigaction> act, ptr<struct sigaction> oact);
SysResult sys_sigreturn(Thread *thread, ptr<struct ucontext> sigcntxp);
SysResult sys_getcontext(Thread *thread, ptr<struct ucontext> ucp);
SysResult sys_setcontext(Thread *thread, ptr<struct ucontext> ucp);
SysResult sys_swapcontext(Thread *thread, ptr<struct ucontext> oucp, ptr<struct ucontext> ucp);
SysResult sys_swapoff(Thread *thread, ptr<const char> name);
SysResult sys___acl_get_link(Thread *thread, ptr<const char> path, acl_type_t type, ptr<struct acl> aclp);
SysResult sys___acl_set_link(Thread *thread, ptr<const char> path, acl_type_t type, ptr<struct acl> aclp);
SysResult sys___acl_delete_link(Thread *thread, ptr<const char> path, acl_type_t type);
SysResult sys___acl_aclcheck_link(Thread *thread, ptr<const char> path, acl_type_t type, ptr<struct acl> aclp);
SysResult sys_sigwait(Thread *thread, ptr<const struct sigset> set, ptr<sint> sig);
SysResult sys_thr_create(Thread *thread, ptr<struct ucontext> ctxt, ptr<slong> arg, sint flags);
SysResult sys_thr_exit(Thread *thread, ptr<slong> state);
SysResult sys_thr_self(Thread *thread, ptr<slong> id);
SysResult sys_thr_kill(Thread *thread, slong id, sint sig);
SysResult sys__umtx_lock(Thread *thread, ptr<struct umtx> umtx);
SysResult sys__umtx_unlock(Thread *thread, ptr<struct umtx> umtx);
SysResult sys_jail_attach(Thread *thread, sint jid);
SysResult sys_extattr_list_fd(Thread *thread, sint fd, sint attrnamespace, ptr<void> data, size_t nbytes);
SysResult sys_extattr_list_file(Thread *thread, ptr<const char> path, sint attrnamespace, ptr<void> data, size_t nbytes);
SysResult sys_extattr_list_link(Thread *thread, ptr<const char> path, sint attrnamespace, ptr<void> data, size_t nbytes);
SysResult sys_ksem_timedwait(Thread *thread, semid_t id, ptr<const struct timespec> abstime);
SysResult sys_thr_suspend(Thread *thread, ptr<const struct timespec> timeout);
SysResult sys_thr_wake(Thread *thread, slong id);
SysResult sys_kldunloadf(Thread *thread, slong fileid, sint flags);
SysResult sys_audit(Thread *thread, ptr<const void> record, uint length);
SysResult sys_auditon(Thread *thread, sint cmd, ptr<void> data, uint length);
SysResult sys_getauid(Thread *thread, ptr<uid_t> auid);
SysResult sys_setauid(Thread *thread, ptr<uid_t> auid);
SysResult sys_getaudit(Thread *thread, ptr<struct auditinfo> auditinfo);
SysResult sys_setaudit(Thread *thread, ptr<struct auditinfo> auditinfo);
SysResult sys_getaudit_addr(Thread *thread, ptr<struct auditinfo_addr> auditinfo_addr, uint length);
SysResult sys_setaudit_addr(Thread *thread, ptr<struct auditinfo_addr> auditinfo_addr, uint length);
SysResult sys_auditctl(Thread *thread, ptr<char> path);
SysResult sys__umtx_op(Thread *thread, ptr<void> obj, sint op, ulong val, ptr<void> uaddr1, ptr<void> uaddr2);
SysResult sys_thr_new(Thread *thread, ptr<struct thr_param> param, sint param_size);
SysResult sys_sigqueue(Thread *thread, pid_t pid, sint signum, ptr<void> value);
SysResult sys_kmq_open(Thread *thread, ptr<const char> path, sint flags, mode_t mode, ptr<const struct mq_attr> attr);
SysResult sys_kmq_setattr(Thread *thread, sint mqd, ptr<const struct mq_attr> attr, ptr<struct mq_attr> oattr);
SysResult sys_kmq_timedreceive(Thread *thread, sint mqd, ptr<const char> msg_ptr, size_t msg_len, ptr<uint> msg_prio, ptr<const struct timespec> abstimeout);
SysResult sys_kmq_timedsend(Thread *thread, sint mqd, ptr<char> msg_ptr, size_t msg_len, ptr<uint> msg_prio, ptr<const struct timespec> abstimeout);
SysResult sys_kmq_notify(Thread *thread, sint mqd, ptr<const struct sigevent> sigev);
SysResult sys_kmq_unlink(Thread *thread, ptr<const char> path);
SysResult sys_abort2(Thread *thread, ptr<const char> why, sint narg, ptr<ptr<void>> args);
SysResult sys_thr_set_name(Thread *thread, slong id, ptr<const char> name);
SysResult sys_aio_fsync(Thread *thread, sint op, ptr<struct aiocb> aiocbp);
SysResult sys_rtprio_thread(Thread *thread, sint function, lwpid_t lwpid, ptr<struct rtprio> rtp);
SysResult sys_sctp_peeloff(Thread *thread, sint sd, uint32_t name);
SysResult sys_sctp_generic_sendmsg(Thread *thread, sint sd, caddr_t msg, sint mlen, caddr_t to, __socklen_t tolen, ptr<struct sctp_sndrcvinfo> sinfo, sint flags);
SysResult sys_sctp_generic_sendmsg_iov(Thread *thread, sint sd, ptr<struct iovec> iov, sint iovlen, caddr_t to, __socklen_t tolen, ptr<struct sctp_sndrcvinfo> sinfo, sint flags);
SysResult sys_sctp_generic_recvmsg(Thread *thread, sint sd, ptr<struct iovec> iov, sint iovlen, caddr_t from, __socklen_t fromlen, ptr<struct sctp_sndrcvinfo> sinfo, sint flags);
SysResult sys_pread(Thread *thread, sint fd, ptr<void> buf, size_t nbyte, off_t offset);
SysResult sys_pwrite(Thread *thread, sint fd, ptr<const void> buf, size_t nbyte, off_t offset);
SysResult sys_mmap(Thread *thread, caddr_t addr, size_t len, sint prot, sint flags, sint fd, off_t pos);
SysResult sys_lseek(Thread *thread, sint fd, off_t offset, sint whence);
SysResult sys_truncate(Thread *thread, ptr<char> path, off_t length);
SysResult sys_ftruncate(Thread *thread, sint fd, off_t length);
SysResult sys_thr_kill2(Thread *thread, pid_t pid, slong id, sint sig);
SysResult sys_shm_open(Thread *thread, ptr<const char> path, sint flags, mode_t mode);
SysResult sys_shm_unlink(Thread *thread, ptr<const char> path);
SysResult sys_cpuset(Thread *thread, ptr<cpusetid_t> setid);
SysResult sys_cpuset_setid(Thread *thread, cpuwhich_t which, id_t id, cpusetid_t setid);
SysResult sys_cpuset_getid(Thread *thread, cpulevel_t level, cpuwhich_t which, id_t id, ptr<cpusetid_t> setid);
SysResult sys_cpuset_getaffinity(Thread *thread, cpulevel_t level, cpuwhich_t which, id_t id, size_t cpusetsize, ptr<cpuset> mask);
SysResult sys_cpuset_setaffinity(Thread *thread, cpulevel_t level, cpuwhich_t which, id_t id, size_t cpusetsize, ptr<const cpuset> mask);
SysResult sys_faccessat(Thread *thread, sint fd, ptr<char> path, sint mode, sint flag);
SysResult sys_fchmodat(Thread *thread, sint fd, ptr<char> path, mode_t mode, sint flag);
SysResult sys_fchownat(Thread *thread, sint fd, ptr<char> path, uid_t uid, gid_t gid, sint flag);
SysResult sys_fexecve(Thread *thread, sint fd, ptr<ptr<char>> argv, ptr<ptr<char>> envv);
SysResult sys_fstatat(Thread *thread, sint fd, ptr<char> path, ptr<struct stat> buf, sint flag);
SysResult sys_futimesat(Thread *thread, sint fd, ptr<char> path, ptr<struct timeval> times);
SysResult sys_linkat(Thread *thread, sint fd1, ptr<char> path1, sint fd2, ptr<char> path2, sint flag);
SysResult sys_mkdirat(Thread *thread, sint fd, ptr<char> path, mode_t mode);
SysResult sys_mkfifoat(Thread *thread, sint fd, ptr<char> path, mode_t mode);
SysResult sys_mknodat(Thread *thread, sint fd, ptr<char> path, mode_t mode, dev_t dev);
SysResult sys_openat(Thread *thread, sint fd, ptr<char> path, sint flag, mode_t mode);
SysResult sys_readlinkat(Thread *thread, sint fd, ptr<char> path, ptr<char> buf, size_t bufsize);
SysResult sys_renameat(Thread *thread, sint oldfd, ptr<char> old, sint newfd, ptr<char> new_);
SysResult sys_symlinkat(Thread *thread, ptr<char> path1, sint fd, ptr<char> path2);
SysResult sys_unlinkat(Thread *thread, sint fd, ptr<char> path, sint flag);
SysResult sys_posix_openpt(Thread *thread, sint flags);
SysResult sys_gssd_syscall(Thread *thread, ptr<char> path);
SysResult sys_jail_get(Thread *thread, ptr<struct iovec> iovp, uint iovcnt, sint flags);
SysResult sys_jail_set(Thread *thread, ptr<struct iovec> iovp, uint iovcnt, sint flags);
SysResult sys_jail_remove(Thread *thread, sint jid);
SysResult sys_closefrom(Thread *thread, sint lowfd);
SysResult sys___semctl(Thread *thread, sint semid, sint semnum, sint cmd, ptr<union semun> arg);
SysResult sys_msgctl(Thread *thread, sint msqid, sint cmd, ptr<struct msqid_ds> buf);
SysResult sys_shmctl(Thread *thread, sint shmid, sint cmd, ptr<struct shmid_ds> buf);
SysResult sys_lpathconf(Thread *thread, ptr<char> path, sint name);
SysResult sys_cap_new(Thread *thread, sint fd, uint64_t rights);
SysResult sys_cap_getrights(Thread *thread, sint fd, ptr<uint64_t> rights);
SysResult sys_cap_enter(Thread *thread);
SysResult sys_cap_getmode(Thread *thread, ptr<uint> modep);
SysResult sys_pdfork(Thread *thread, ptr<sint> fdp, sint flags);
SysResult sys_pdkill(Thread *thread, sint fd, sint signum);
SysResult sys_pdgetpid(Thread *thread, sint fd, ptr<pid_t> pidp);
SysResult sys_pselect(Thread *thread, sint nd, ptr<fd_set> in, ptr<fd_set> ou, ptr<fd_set> ex, ptr<const struct timespec> ts, ptr<const sigset_t> sm);
SysResult sys_getloginclass(Thread *thread, ptr<char> namebuf, size_t namelen);
SysResult sys_setloginclass(Thread *thread, ptr<char> namebuf);
SysResult sys_rctl_get_racct(Thread *thread, ptr<const void> inbufp, size_t inbuflen, ptr<void> outbuf, size_t outbuflen);
SysResult sys_rctl_get_rules(Thread *thread, ptr<const void> inbufp, size_t inbuflen, ptr<void> outbuf, size_t outbuflen);
SysResult sys_rctl_get_limits(Thread *thread, ptr<const void> inbufp, size_t inbuflen, ptr<void> outbuf, size_t outbuflen);
SysResult sys_rctl_add_rule(Thread *thread, ptr<const void> inbufp, size_t inbuflen, ptr<void> outbuf, size_t outbuflen);
SysResult sys_rctl_remove_rule(Thread *thread, ptr<const void> inbufp, size_t inbuflen, ptr<void> outbuf, size_t outbuflen);
SysResult sys_posix_fallocate(Thread *thread, sint fd, off_t offset, off_t len);
SysResult sys_posix_fadvise(Thread *thread, sint fd, off_t offset, off_t len, sint advice);
SysResult sys_netcontrol(Thread *thread, sint fd, uint op, ptr<void> buf, uint nbuf);
SysResult sys_netabort(Thread *thread /* TODO */);
SysResult sys_netgetsockinfo(Thread *thread /* TODO */);
SysResult sys_socketex(Thread *thread, ptr<const char> name, sint domain, sint type, sint protocol);
SysResult sys_socketclose(Thread *thread /* TODO */);
SysResult sys_netgetiflist(Thread *thread /* TODO */);
SysResult sys_kqueueex(Thread *thread /* TODO */);
SysResult sys_mtypeprotect(Thread *thread /* TODO */);
SysResult sys_regmgr_call(Thread *thread, uint32_t op, uint32_t id, ptr<void> result, ptr<void> value, uint64_t type);
SysResult sys_jitshm_create(Thread *thread /* TODO */);
SysResult sys_jitshm_alias(Thread *thread /* TODO */);
SysResult sys_dl_get_list(Thread *thread /* TODO */);
SysResult sys_dl_get_info(Thread *thread /* TODO */);
SysResult sys_dl_notify_event(Thread *thread /* TODO */);
SysResult sys_evf_create(Thread *thread, ptr<char> name, sint flag, ptr<struct evFlag> evf);
SysResult sys_evf_delete(Thread *thread, sint fd);
SysResult sys_evf_open(Thread *thread, ptr<char> name);
SysResult sys_evf_close(Thread *thread, sint fd);
SysResult sys_evf_wait(Thread *thread /* TODO */);
SysResult sys_evf_trywait(Thread *thread /* TODO */);
SysResult sys_evf_set(Thread *thread, sint fd);
SysResult sys_evf_clear(Thread *thread, sint fd);
SysResult sys_evf_cancel(Thread *thread, sint fd);
SysResult sys_query_memory_protection(Thread *thread /* TODO */);
SysResult sys_batch_map(Thread *thread /* TODO */);
SysResult sys_osem_create(Thread *thread /* TODO */);
SysResult sys_osem_delete(Thread *thread /* TODO */);
SysResult sys_osem_open(Thread *thread /* TODO */);
SysResult sys_osem_close(Thread *thread /* TODO */);
SysResult sys_osem_wait(Thread *thread /* TODO */);
SysResult sys_osem_trywait(Thread *thread /* TODO */);
SysResult sys_osem_post(Thread *thread /* TODO */);
SysResult sys_osem_cancel(Thread *thread /* TODO */);
SysResult sys_namedobj_create(Thread *thread, ptr<const char> name, ptr<void> object, uint64_t type);
SysResult sys_namedobj_delete(Thread *thread /* TODO */);
SysResult sys_set_vm_container(Thread *thread /* TODO */);
SysResult sys_debug_init(Thread *thread /* TODO */);
SysResult sys_suspend_process(Thread *thread, pid_t pid);
SysResult sys_resume_process(Thread *thread, pid_t pid);
SysResult sys_opmc_enable(Thread *thread /* TODO */);
SysResult sys_opmc_disable(Thread *thread /* TODO */);
SysResult sys_opmc_set_ctl(Thread *thread /* TODO */);
SysResult sys_opmc_set_ctr(Thread *thread /* TODO */);
SysResult sys_opmc_get_ctr(Thread *thread /* TODO */);
SysResult sys_budget_create(Thread *thread /* TODO */);
SysResult sys_budget_delete(Thread *thread /* TODO */);
SysResult sys_budget_get(Thread *thread /* TODO */);
SysResult sys_budget_set(Thread *thread /* TODO */);
SysResult sys_virtual_query(Thread *thread, ptr<void> addr, uint64_t unk, ptr<void> info, size_t infosz);
SysResult sys_mdbg_call(Thread *thread /* TODO */);
SysResult sys_obs_sblock_create(Thread *thread /* TODO */);
SysResult sys_obs_sblock_delete(Thread *thread /* TODO */);
SysResult sys_obs_sblock_enter(Thread *thread /* TODO */);
SysResult sys_obs_sblock_exit(Thread *thread /* TODO */);
SysResult sys_obs_sblock_xenter(Thread *thread /* TODO */);
SysResult sys_obs_sblock_xexit(Thread *thread /* TODO */);
SysResult sys_obs_eport_create(Thread *thread /* TODO */);
SysResult sys_obs_eport_delete(Thread *thread /* TODO */);
SysResult sys_obs_eport_trigger(Thread *thread /* TODO */);
SysResult sys_obs_eport_open(Thread *thread /* TODO */);
SysResult sys_obs_eport_close(Thread *thread /* TODO */);
SysResult sys_is_in_sandbox(Thread *thread /* TODO */);
SysResult sys_dmem_container(Thread *thread);
SysResult sys_get_authinfo(Thread *thread, pid_t pid, ptr<void> info);
SysResult sys_mname(Thread *thread, ptr<void> address, uint64_t length, ptr<const char> name);
SysResult sys_dynlib_dlopen(Thread *thread /* TODO */);
SysResult sys_dynlib_dlclose(Thread *thread /* TODO */);
SysResult sys_dynlib_dlsym(Thread *thread, SceKernelModule handle, ptr<const char> symbol, ptr<ptr<void>> addrp);
SysResult sys_dynlib_get_list(Thread *thread, ptr<SceKernelModule> pArray, size_t numArray, ptr<size_t> pActualNum);
SysResult sys_dynlib_get_info(Thread *thread, SceKernelModule handle, ptr<ModuleInfo> pInfo);
SysResult sys_dynlib_load_prx(Thread *thread, ptr<const char> name, uint64_t arg1, ptr<ModuleHandle> pHandle, uint64_t arg3);
SysResult sys_dynlib_unload_prx(Thread *thread, SceKernelModule handle /* TODO*/);
SysResult sys_dynlib_do_copy_relocations(Thread *thread);
SysResult sys_dynlib_prepare_dlclose(Thread *thread /* TODO */);
SysResult sys_dynlib_get_proc_param(Thread *thread, ptr<ptr<void>> procParam, ptr<uint64_t> procParamSize);
SysResult sys_dynlib_process_needed_and_relocate(Thread *thread);
SysResult sys_sandbox_path(Thread *thread /* TODO */);
SysResult sys_mdbg_service(Thread *thread, uint32_t op, ptr<void> arg0, ptr<void> arg1);
SysResult sys_randomized_path(Thread *thread /* TODO */);
SysResult sys_rdup(Thread *thread /* TODO */);
SysResult sys_dl_get_metadata(Thread *thread /* TODO */);
SysResult sys_workaround8849(Thread *thread /* TODO */);
SysResult sys_is_development_mode(Thread *thread /* TODO */);
SysResult sys_get_self_auth_info(Thread *thread /* TODO */);
SysResult sys_dynlib_get_info_ex(Thread *thread, SceKernelModule handle, ptr<struct Unk> unk, ptr<ModuleInfoEx> destModuleInfoEx);
SysResult sys_budget_getid(Thread *thread);
SysResult sys_budget_get_ptype(Thread *thread, sint budgetId);
SysResult sys_get_paging_stats_of_all_threads(Thread *thread /* TODO */);
SysResult sys_get_proc_type_info(Thread *thread, ptr<sint> destProcessInfo);
SysResult sys_get_resident_count(Thread *thread, pid_t pid);
SysResult sys_prepare_to_suspend_process(Thread *thread, pid_t pid);
SysResult sys_get_resident_fmem_count(Thread *thread, pid_t pid);
SysResult sys_thr_get_name(Thread *thread, lwpid_t lwpid);
SysResult sys_set_gpo(Thread *thread /* TODO */);
SysResult sys_get_paging_stats_of_all_objects(Thread *thread /* TODO */);
SysResult sys_test_debug_rwmem(Thread *thread /* TODO */);
SysResult sys_free_stack(Thread *thread /* TODO */);
SysResult sys_suspend_system(Thread *thread /* TODO */);
SysResult sys_ipmimgr_call(Thread *thread, uint64_t id, uint64_t arg2, ptr<uint64_t> result, ptr<uint64_t> params, uint64_t arg5, uint64_t arg6);
SysResult sys_get_gpo(Thread *thread /* TODO */);
SysResult sys_get_vm_map_timestamp(Thread *thread /* TODO */);
SysResult sys_opmc_set_hw(Thread *thread /* TODO */);
SysResult sys_opmc_get_hw(Thread *thread /* TODO */);
SysResult sys_get_cpu_usage_all(Thread *thread /* TODO */);
SysResult sys_mmap_dmem(Thread *thread /* TODO */);
SysResult sys_physhm_open(Thread *thread /* TODO */);
SysResult sys_physhm_unlink(Thread *thread /* TODO */);
SysResult sys_resume_internal_hdd(Thread *thread /* TODO */);
SysResult sys_thr_suspend_ucontext(Thread *thread /* TODO */);
SysResult sys_thr_resume_ucontext(Thread *thread /* TODO */);
SysResult sys_thr_get_ucontext(Thread *thread /* TODO */);
SysResult sys_thr_set_ucontext(Thread *thread /* TODO */);
SysResult sys_set_timezone_info(Thread *thread /* TODO */);
SysResult sys_set_phys_fmem_limit(Thread *thread /* TODO */);
SysResult sys_utc_to_localtime(Thread *thread /* TODO */);
SysResult sys_localtime_to_utc(Thread *thread /* TODO */);
SysResult sys_set_uevt(Thread *thread /* TODO */);
SysResult sys_get_cpu_usage_proc(Thread *thread /* TODO */);
SysResult sys_get_map_statistics(Thread *thread /* TODO */);
SysResult sys_set_chicken_switches(Thread *thread /* TODO */);
SysResult sys_extend_page_table_pool(Thread *thread);
SysResult sys_extend_page_table_pool2(Thread *thread);
SysResult sys_get_kernel_mem_statistics(Thread *thread /* TODO */);
SysResult sys_get_sdk_compiled_version(Thread *thread /* TODO */);
SysResult sys_app_state_change(Thread *thread /* TODO */);
SysResult sys_dynlib_get_obj_member(Thread *thread, SceKernelModule handle, uint64_t index, ptr<ptr<void>> addrp);
SysResult sys_budget_get_ptype_of_budget(Thread *thread /* TODO */);
SysResult sys_prepare_to_resume_process(Thread *thread /* TODO */);
SysResult sys_process_terminate(Thread *thread /* TODO */);
SysResult sys_blockpool_open(Thread *thread /* TODO */);
SysResult sys_blockpool_map(Thread *thread /* TODO */);
SysResult sys_blockpool_unmap(Thread *thread /* TODO */);
SysResult sys_dynlib_get_info_for_libdbg(Thread *thread /* TODO */);
SysResult sys_blockpool_batch(Thread *thread /* TODO */);
SysResult sys_fdatasync(Thread *thread /* TODO */);
SysResult sys_dynlib_get_list2(Thread *thread /* TODO */);
SysResult sys_dynlib_get_info2(Thread *thread /* TODO */);
SysResult sys_aio_submit(Thread *thread /* TODO */);
SysResult sys_aio_multi_delete(Thread *thread /* TODO */);
SysResult sys_aio_multi_wait(Thread *thread /* TODO */);
SysResult sys_aio_multi_poll(Thread *thread /* TODO */);
SysResult sys_aio_get_data(Thread *thread /* TODO */);
SysResult sys_aio_multi_cancel(Thread *thread /* TODO */);
SysResult sys_get_bio_usage_all(Thread *thread /* TODO */);
SysResult sys_aio_create(Thread *thread /* TODO */);
SysResult sys_aio_submit_cmd(Thread *thread /* TODO */);
SysResult sys_aio_init(Thread *thread /* TODO */);
SysResult sys_get_page_table_stats(Thread *thread /* TODO */);
SysResult sys_dynlib_get_list_for_libdbg(Thread *thread /* TODO */);
SysResult sys_blockpool_move(Thread *thread /* TODO */);
SysResult sys_virtual_query_all(Thread *thread /* TODO */);
SysResult sys_reserve_2mb_page(Thread *thread /* TODO */);
SysResult sys_cpumode_yield(Thread *thread /* TODO */);
SysResult sys_wait6(Thread *thread /* TODO */);
SysResult sys_cap_rights_limit(Thread *thread /* TODO */);
SysResult sys_cap_ioctls_limit(Thread *thread /* TODO */);
SysResult sys_cap_ioctls_get(Thread *thread /* TODO */);
SysResult sys_cap_fcntls_limit(Thread *thread /* TODO */);
SysResult sys_cap_fcntls_get(Thread *thread /* TODO */);
SysResult sys_bindat(Thread *thread /* TODO */);
SysResult sys_connectat(Thread *thread /* TODO */);
SysResult sys_chflagsat(Thread *thread /* TODO */);
SysResult sys_accept4(Thread *thread /* TODO */);
SysResult sys_pipe2(Thread *thread /* TODO */);
SysResult sys_aio_mlock(Thread *thread /* TODO */);
SysResult sys_procctl(Thread *thread /* TODO */);
SysResult sys_ppoll(Thread *thread /* TODO */);
SysResult sys_futimens(Thread *thread /* TODO */);
SysResult sys_utimensat(Thread *thread /* TODO */);
SysResult sys_numa_getaffinity(Thread *thread /* TODO */);
SysResult sys_numa_setaffinity(Thread *thread /* TODO */);
SysResult sys_apr_submit(Thread *thread /* TODO */);
SysResult sys_apr_resolve(Thread *thread /* TODO */);
SysResult sys_apr_stat(Thread *thread /* TODO */);
SysResult sys_apr_wait(Thread *thread /* TODO */);
SysResult sys_apr_ctrl(Thread *thread /* TODO */);
SysResult sys_get_phys_page_size(Thread *thread /* TODO */);
SysResult sys_begin_app_mount(Thread *thread /* TODO */);
SysResult sys_end_app_mount(Thread *thread /* TODO */);
SysResult sys_fsc2h_ctrl(Thread *thread /* TODO */);
SysResult sys_streamwrite(Thread *thread /* TODO */);
SysResult sys_app_save(Thread *thread /* TODO */);
SysResult sys_app_restore(Thread *thread /* TODO */);
SysResult sys_saved_app_delete(Thread *thread /* TODO */);
SysResult sys_get_ppr_sdk_compiled_version(Thread *thread /* TODO */);
SysResult sys_notify_app_event(Thread *thread /* TODO */);
SysResult sys_ioreq(Thread *thread /* TODO */);
SysResult sys_openintr(Thread *thread /* TODO */);
SysResult sys_dl_get_info_2(Thread *thread /* TODO */);
SysResult sys_acinfo_add(Thread *thread /* TODO */);
SysResult sys_acinfo_delete(Thread *thread /* TODO */);
SysResult sys_acinfo_get_all_for_coredump(Thread *thread /* TODO */);
SysResult sys_ampr_ctrl_debug(Thread *thread /* TODO */);
SysResult sys_workspace_ctrl(Thread *thread /* TODO */);
} // namespace orbis

View file

@ -0,0 +1,10 @@
#pragma once
#include "thread/cpuset.hpp" // IWYU pragma: export
#include "thread/Process.hpp" // IWYU pragma: export
#include "thread/ProcessOps.hpp" // IWYU pragma: export
#include "thread/ProcessState.hpp" // IWYU pragma: export
#include "thread/sysent.hpp" // IWYU pragma: export
#include "thread/Thread.hpp" // IWYU pragma: export
#include "thread/ThreadState.hpp" // IWYU pragma: export
#include "thread/types.hpp" // IWYU pragma: export

View file

@ -0,0 +1,38 @@
#pragma once
#include "ProcessState.hpp"
#include "orbis-config.hpp"
#include "orbis/module/Module.hpp"
#include "orbis/utils/IdMap.hpp"
#include "orbis/utils/SharedMutex.hpp"
#include "../thread/types.hpp"
#include "../thread/Thread.hpp"
#include <mutex>
namespace orbis {
class KernelContext;
struct Thread;
struct ProcessOps;
struct sysentvec;
struct Process {
KernelContext *context = nullptr;
pid_t pid = -1;
sysentvec *sysent = nullptr;
ProcessState state = ProcessState::NEW;
Process *parentProcess = nullptr;
shared_mutex mtx;
void (*onSysEnter)(Thread *thread, int id, uint64_t *args, int argsCount) = nullptr;
void (*onSysExit)(Thread *thread, int id, uint64_t *args, int argsCount, SysResult result) = nullptr;
ptr<void> processParam = nullptr;
uint64_t processParamSize = 0;
const ProcessOps *ops = nullptr;
std::uint64_t nextTlsSlot = 1;
std::uint64_t lastTlsOffset = 0;
utils::RcIdMap<Module, ModuleHandle> modulesMap;
utils::OwningIdMap<Thread, lwpid_t> threadsMap;
utils::RcIdMap<utils::RcBase, sint> fileDescriptors;
};
} // namespace orbis

View file

@ -0,0 +1,56 @@
#pragma once
#include "../error/SysResult.hpp"
#include "../module/ModuleHandle.hpp"
#include "orbis-config.hpp"
#include "../thread/types.hpp"
namespace orbis {
struct Thread;
struct Module;
struct ProcessOps {
SysResult (*mmap)(Thread *thread, caddr_t addr, size_t len, sint prot, sint flags, sint fd, off_t pos);
SysResult (*munmap)(Thread *thread, ptr<void> addr, size_t len);
SysResult (*msync)(Thread *thread, ptr<void> addr, size_t len, sint flags);
SysResult (*mprotect)(Thread *thread, ptr<const void> addr, size_t len, sint prot);
SysResult (*minherit)(Thread *thread, ptr<void> addr, size_t len, sint inherit);
SysResult (*madvise)(Thread *thread, ptr<void> addr, size_t len, sint behav);
SysResult (*mincore)(Thread *thread, ptr<const void> addr, size_t len, ptr<char> vec);
SysResult (*mlock)(Thread *thread, ptr<const void> addr, size_t len);
SysResult (*mlockall)(Thread *thread, sint how);
SysResult (*munlockall)(Thread *thread);
SysResult (*munlock)(Thread *thread, ptr<const void> addr, size_t len);
SysResult (*virtual_query)(Thread *thread, ptr<const void> addr, sint flags, ptr<void> info, ulong infoSize);
SysResult (*open)(Thread *thread, ptr<const char> path, sint flags, sint mode);
SysResult (*close)(Thread *thread, sint fd);
SysResult (*ioctl)(Thread *thread, sint fd, ulong com, caddr_t argp);
SysResult (*write)(Thread *thread, sint fd, ptr<const void> data, ulong size);
SysResult (*read)(Thread *thread, sint fd, ptr<void> data, ulong size);
SysResult (*pread)(Thread *thread, sint fd, ptr<void> data, ulong size, ulong offset);
SysResult (*pwrite)(Thread *thread, sint fd, ptr<const void> data, ulong size, ulong offset);
SysResult (*lseek)(Thread *thread, sint fd, ulong offset, sint whence);
SysResult (*ftruncate)(Thread *thread, sint fd, off_t length);
SysResult (*truncate)(Thread *thread, ptr<const char> path, off_t length);
SysResult (*dynlib_get_obj_member)(Thread *thread, ModuleHandle handle, uint64_t index, ptr<ptr<void>> addrp);
SysResult (*dynlib_dlsym)(Thread *thread, ModuleHandle handle, ptr<const char> symbol, ptr<ptr<void>> addrp);
SysResult (*dynlib_do_copy_relocations)(Thread *thread);
SysResult (*dynlib_load_prx)(Thread *thread, ptr<const char> name, uint64_t arg1, ptr<ModuleHandle> pHandle, uint64_t arg3);
SysResult (*dynlib_unload_prx)(Thread *thread, ModuleHandle handle);
SysResult (*thr_create)(Thread *thread, ptr<struct ucontext> ctxt, ptr<slong> arg, sint flags);
SysResult (*thr_new)(Thread *thread, ptr<struct thr_param> param, sint param_size);
SysResult (*thr_exit)(Thread *thread, ptr<slong> state);
SysResult (*thr_kill)(Thread *thread, slong id, sint sig);
SysResult (*thr_kill2)(Thread *thread, pid_t pid, slong id, sint sig);
SysResult (*thr_suspend)(Thread *thread, ptr<const struct timespec> timeout);
SysResult (*thr_wake)(Thread *thread, slong id);
SysResult (*thr_set_name)(Thread *thread, slong id, ptr<const char> name);
SysResult (*exit)(Thread *thread, sint status);
SysResult (*processNeeded)(Thread *thread);
SysResult (*registerEhFrames)(Thread *thread);
};
} // namespace orbis

View file

@ -0,0 +1,11 @@
#pragma once
#include <cstdint>
namespace orbis {
enum class ProcessState : std::uint32_t {
NEW, // In creation
NORMAL, // threads can be run
ZOMBIE
};
} // namespace orbis

View file

@ -0,0 +1,23 @@
#pragma once
namespace orbis {
enum class RegisterId {
r15,
r14,
r13,
r12,
r11,
r10,
r9,
r8,
rdi,
rsi,
rbp,
rbx,
rdx,
rcx,
rax,
rsp,
rflags,
};
} // namespace orbis

View file

@ -0,0 +1,30 @@
#pragma once
#include "orbis-config.hpp"
#include "types.hpp"
#include "ThreadState.hpp"
#include <mutex>
namespace orbis {
struct Process;
struct Thread {
std::mutex lock;
Process *tproc = nullptr;
uint64_t retval[2]{};
void *context{};
ptr<void> stackStart;
ptr<void> stackEnd;
uint64_t fsBase{};
uint64_t gsBase{};
char name[32];
uint64_t sigMask[4] = {
0x7fff'ffff,
0
};
lwpid_t tid = -1;
ThreadState state = ThreadState::INACTIVE;
};
} // namespace orbis

View file

@ -0,0 +1,7 @@
#pragma once
#include <cstdint>
namespace orbis {
enum class ThreadState : std::uint32_t { INACTIVE, INHIBITED, CAN_RUN, RUNQ, RUNNING };
} // namespace orbis

View file

@ -0,0 +1,12 @@
#pragma once
#include "orbis-config.hpp"
namespace orbis {
static constexpr auto NCPUBITS = sizeof(slong) * 8;
static constexpr auto NCPUWORDS = 128 / NCPUBITS;
struct cpuset {
slong bits[NCPUWORDS];
};
} // namespace orbis

View file

@ -0,0 +1,18 @@
#pragma once
#include "orbis-config.hpp"
namespace orbis {
struct Thread;
using sy_call_t = SysResult(Thread *, uint64_t *);
struct sysent {
sint narg;
sy_call_t *call;
};
struct sysentvec {
sint size;
const sysent *table;
};
} // namespace orbis

View file

@ -0,0 +1,9 @@
#pragma once
#include "orbis-config.hpp"
namespace orbis {
using lwpid_t = int32_t;
using pid_t = int64_t;
using uid_t = uint32_t;
using gid_t = uint32_t;
} // namespace orbis

View file

@ -0,0 +1,74 @@
#pragma once
#include <atomic>
#include <utility>
#include <functional>
namespace orbis {
inline namespace utils {
// Atomic operation; returns old value, or pair of old value and return value
// (cancel op if evaluates to false)
template <typename T, typename F, typename RT = std::invoke_result_t<F, T &>>
inline std::conditional_t<std::is_void_v<RT>, T, std::pair<T, RT>>
atomic_fetch_op(std::atomic<T> &v, F func) {
T _new, old = v.load();
while (true) {
_new = old;
if constexpr (std::is_void_v<RT>) {
std::invoke(func, _new);
if (v.compare_exchange_strong(old, _new)) [[likely]] {
return old;
}
} else {
RT ret = std::invoke(func, _new);
if (!ret || v.compare_exchange_strong(old, _new)) [[likely]] {
return {old, std::move(ret)};
}
}
}
}
// Atomic operation; returns function result value, function is the lambda
template <typename T, typename F, typename RT = std::invoke_result_t<F, T &>>
inline RT atomic_op(std::atomic<T> &v, F func) {
T _new, old = v.load();
while (true) {
_new = old;
if constexpr (std::is_void_v<RT>) {
std::invoke(func, _new);
if (v.compare_exchange_strong(old, _new)) [[likely]] {
return;
}
} else {
RT result = std::invoke(func, _new);
if (v.compare_exchange_strong(old, _new)) [[likely]] {
return result;
}
}
}
}
#if defined(__ATOMIC_HLE_ACQUIRE) && defined(__ATOMIC_HLE_RELEASE)
static constexpr int s_hle_ack = __ATOMIC_SEQ_CST | __ATOMIC_HLE_ACQUIRE;
static constexpr int s_hle_rel = __ATOMIC_SEQ_CST | __ATOMIC_HLE_RELEASE;
#else
static constexpr int s_hle_ack = __ATOMIC_SEQ_CST;
static constexpr int s_hle_rel = __ATOMIC_SEQ_CST;
#endif
template <typename T>
inline bool compare_exchange_hle_acq(std::atomic<T> &dest, T &comp, T exch) {
static_assert(sizeof(T) == 4 || sizeof(T) == 8);
static_assert(std::atomic<T>::is_always_lock_free);
return __atomic_compare_exchange(reinterpret_cast<T *>(&dest), &comp, &exch,
false, s_hle_ack, s_hle_ack);
}
template <typename T>
inline T fetch_add_hle_rel(std::atomic<T> &dest, T value) {
static_assert(sizeof(T) == 4 || sizeof(T) == 8);
static_assert(std::atomic<T>::is_always_lock_free);
return __atomic_fetch_add(reinterpret_cast<T *>(&dest), value, s_hle_rel);
}
} // namespace utils
} // namespace orbis

View file

@ -0,0 +1,104 @@
#pragma once
#include <bit>
#include <cstddef>
#include <cstdint>
namespace orbis {
inline namespace utils {
template <std::size_t Count> struct BitSet {
using chunk_type = std::uint64_t;
static constexpr auto BitsPerChunk = sizeof(chunk_type) * 8;
static constexpr auto ChunkCount = (Count + BitsPerChunk - 1) / BitsPerChunk;
chunk_type _bits[ChunkCount]{};
constexpr std::size_t countr_one() const {
std::size_t result = 0;
for (auto bits : _bits) {
auto count = std::countr_one(bits);
result += count;
if (count != BitsPerChunk) {
break;
}
}
return result;
}
constexpr std::size_t countr_zero(std::size_t offset = 0) const {
std::size_t result = 0;
if (auto chunkOffset = offset % BitsPerChunk) {
auto count =
std::countr_zero(_bits[offset / BitsPerChunk] >> chunkOffset);
if (count != BitsPerChunk) {
return count + offset;
}
offset = (offset + BitsPerChunk - 1) & ~(BitsPerChunk - 1);
}
for (auto i = offset / BitsPerChunk; i < ChunkCount; ++i) {
auto count = std::countr_zero(_bits[i]);
result += count;
if (count != BitsPerChunk) {
break;
}
}
/*
for (auto bits : _bits) {
auto count = std::countr_zero(bits);
result += count;
if (count != BitsPerChunk) {
break;
}
}
*/
return result + offset;
}
bool empty() const {
for (auto bits : _bits) {
if (bits != 0) {
return false;
}
}
return true;
}
bool full() const {
if constexpr (Count < BitsPerChunk) {
return _bits[0] == (static_cast<std::uint64_t>(1) << Count) - 1;
}
for (auto bits : _bits) {
if (bits != ~static_cast<chunk_type>(0)) {
return false;
}
}
return true;
}
constexpr void clear(std::size_t index) {
_bits[index / BitsPerChunk] &=
~(static_cast<chunk_type>(1) << (index % BitsPerChunk));
}
constexpr void set(std::size_t index) {
_bits[index / BitsPerChunk] |= static_cast<chunk_type>(1)
<< (index % BitsPerChunk);
}
constexpr bool test(std::size_t index) const {
return (_bits[index / BitsPerChunk] &
(static_cast<chunk_type>(1) << (index % BitsPerChunk))) != 0;
}
};
} // namespace utils
} // namespace orbis

View file

@ -0,0 +1,306 @@
#pragma once
#include "BitSet.hpp"
#include "Rc.hpp"
#include <algorithm>
#include <bit>
#include <cstddef>
#include <cstdint>
#include <type_traits>
namespace orbis {
inline namespace utils {
template <WithRc T, typename IdT = int, std::size_t MaxId = 4096,
std::size_t MinId = 0>
requires(MaxId > MinId)
class RcIdMap {
static constexpr auto ChunkSize = std::min<std::size_t>(MaxId - MinId, 64);
static constexpr auto ChunkCount =
(MaxId - MinId + ChunkSize - 1) / ChunkSize;
struct IdMapChunk {
BitSet<ChunkSize> mask = {};
T *objects[ChunkSize]{};
~IdMapChunk() {
std::size_t index = mask.countr_zero();
while (index < ChunkSize) {
objects[index]->decRef();
index = mask.countr_zero(index + 1);
}
}
std::size_t insert(T *object) {
std::size_t index = mask.countr_one();
mask.set(index);
objects[index] = object;
return index;
}
T *get(std::size_t index) { return objects[index]; }
void remove(std::size_t index) {
objects[index]->decRef();
objects[index] = nullptr;
mask.clear(index);
}
};
IdMapChunk m_chunks[ChunkCount]{};
BitSet<ChunkCount> m_fullChunks;
public:
static constexpr auto npos = static_cast<IdT>(~static_cast<std::size_t>(0));
struct end_iterator {};
class iterator {
const IdMapChunk *chunks = nullptr;
std::size_t chunk = 0;
std::size_t index = 0;
public:
iterator(const IdMapChunk *chunks) : chunks(chunks) { findNext(); }
iterator &operator++() {
++index;
findNext();
return *this;
}
std::pair<IdT, T *> operator*() const {
return {static_cast<IdT>(chunk * ChunkSize + index + MinId),
chunks[chunk].objects[index]};
}
bool operator!=(const end_iterator &) const { return chunk < ChunkCount; }
bool operator==(const end_iterator &) const { return chunk >= ChunkCount; }
private:
void findNext() {
while (chunk < ChunkCount) {
index = chunks[chunk].mask.countr_zero(index);
if (index < ChunkSize) {
break;
}
index = 0;
chunk++;
}
}
};
void walk(auto cb) {
for (std::size_t chunk = 0; chunk < ChunkCount; ++chunk) {
std::size_t index = m_chunks[chunk].mask.countr_zero();
while (index < ChunkSize) {
cb(static_cast<IdT>(index + chunk * ChunkSize + MinId),
m_chunks[chunk].objects[index]);
index = m_chunks[chunk].mask.countr_zero(index + 1);
}
}
}
iterator begin() const { return iterator{m_chunks}; }
end_iterator end() const { return {}; }
private:
IdT insert_impl(T *object) {
auto page = m_fullChunks.countr_one();
if (page == ChunkCount) {
return npos;
}
auto index = m_chunks[page].insert(object);
if (m_chunks[page].mask.full()) {
m_fullChunks.set(page);
}
return {static_cast<IdT>(page * ChunkSize + index + MinId)};
}
public:
IdT insert(T *object) {
auto result = insert_impl(object);
if (result != npos) {
object->incRef();
}
return result;
}
IdT insert(const Ref<T> &ref) { return insert(ref.get()); }
IdT insert(Ref<T> &&ref) {
auto object = ref.release();
auto result = insert_impl(object);
if (result == npos) {
object->decRef();
}
return result;
}
T *get(IdT id) {
const auto rawId = static_cast<std::size_t>(id) - MinId;
if (rawId >= MaxId - MinId) {
return nullptr;
}
const auto chunk = rawId / ChunkSize;
const auto index = rawId % ChunkSize;
if (!m_chunks[chunk].mask.test(index)) {
return nullptr;
}
return m_chunks[chunk].get(index);
}
bool remove(IdT id) {
const auto rawId = static_cast<std::size_t>(id) - MinId;
if (rawId >= MaxId - MinId) {
return false;
}
const auto chunk = rawId / ChunkSize;
const auto index = rawId % ChunkSize;
if (!m_chunks[chunk].mask.test(index)) {
return false;
}
m_chunks[chunk].remove(index);
m_fullChunks.clear(chunk);
return true;
}
};
template <typename T, typename IdT = int, std::size_t MaxId = 4096,
std::size_t MinId = 0>
requires(MaxId > MinId)
struct OwningIdMap {
static constexpr auto ChunkSize = std::min<std::size_t>(MaxId - MinId, 64);
static constexpr auto ChunkCount =
(MaxId - MinId + ChunkSize - 1) / ChunkSize;
struct IdMapChunk {
BitSet<ChunkSize> mask = {};
alignas(T) std::byte objects[sizeof(T) * ChunkSize];
~IdMapChunk() {
std::size_t pageOffset = 0;
for (auto page : mask._bits) {
auto tmp = page;
while (true) {
const auto index = std::countr_zero(tmp);
if (index >= 64) {
break;
}
tmp &= ~(static_cast<std::uint64_t>(1) << index);
destroy(pageOffset + index);
}
pageOffset += 64;
}
}
template <typename... ArgsT>
std::pair<std::size_t, T *> emplace_new(ArgsT &&...args) {
std::size_t index = mask.countr_one();
if (index >= ChunkSize) {
return {};
}
mask.set(index);
return {index,
std::construct_at(get(index), std::forward<ArgsT>(args)...)};
}
T *get(std::size_t index) {
return reinterpret_cast<T *>(objects + sizeof(T) * index);
}
void destroy(std::size_t index) {
std::destroy_at(get(index));
mask.clear(index);
}
};
IdMapChunk chunks[ChunkCount]{};
BitSet<ChunkCount> fullChunks;
template <typename... ArgsT>
requires(std::is_constructible_v<T, ArgsT...>)
std::pair<IdT, T *> emplace(ArgsT &&...args) {
auto page = fullChunks.countr_one();
if (page == ChunkCount) {
return {};
}
auto newElem = chunks[page].emplace_new(std::forward<ArgsT>(args)...);
if (chunks[page].mask.full()) {
fullChunks.set(page);
}
return {static_cast<IdT>(page * ChunkSize + newElem.first + MinId),
newElem.second};
}
T *get(IdT id) {
const auto rawId = static_cast<std::size_t>(id) - MinId;
const auto chunk = rawId / ChunkSize;
const auto index = rawId % ChunkSize;
if (chunk >= ChunkCount) {
return nullptr;
}
if (!chunks[chunk].mask.test(index)) {
return nullptr;
}
return chunks[chunk].get(index);
}
bool destroy(IdT id) {
const auto rawId = static_cast<std::size_t>(id) - MinId;
const auto chunk = rawId / ChunkSize;
const auto index = rawId % ChunkSize;
if (chunk >= ChunkCount) {
return false;
}
if (!chunks[chunk].mask.test(index)) {
return false;
}
chunks[chunk].destroy(index);
fullChunks.clear(chunk);
return true;
}
};
} // namespace utils
} // namespace orbis

View file

@ -0,0 +1,48 @@
#pragma once
namespace orbis {
inline namespace utils {
template <typename T> struct LinkedNode {
T object;
LinkedNode *next = nullptr;
LinkedNode *prev = nullptr;
void insertNext(LinkedNode &other) {
other.next = next;
other.prev = this;
if (next != nullptr) {
next->prev = &other;
}
next = &other;
}
void insertPrev(LinkedNode &other) {
other.next = this;
other.prev = prev;
if (prev != nullptr) {
prev->next = &other;
}
prev = &other;
}
LinkedNode *erase() {
if (prev != nullptr) {
prev->next = next;
}
if (next != nullptr) {
next->prev = prev;
}
prev = nullptr;
auto result = next;
next = nullptr;
return result;
}
};
} // namespace utils
} // namespace orbis

View file

@ -0,0 +1,104 @@
#pragma once
#include <atomic>
#include <span>
#include <string>
namespace orbis {
inline namespace logs {
enum class LogLevel : unsigned char {
Always,
Fatal,
Error,
Todo,
Success,
Warning,
Notice,
Trace
};
// Currently enabled log level
inline std::atomic<LogLevel> logs_level = LogLevel::Notice;
template <typename T, typename = void> struct log_class_string {
static const T &get_object(const void *arg) {
return *static_cast<const T *>(arg);
}
static void format(std::string &out, const void *arg);
};
template <> struct log_class_string<const void *, void> {
static void format(std::string &out, const void *arg);
};
template <typename T>
struct log_class_string<T *, void> : log_class_string<const void *, void> {};
template <> struct log_class_string<const char *, void> {
static void format(std::string &out, const void *arg);
};
template <>
struct log_class_string<char *, void> : log_class_string<const char *> {};
template <>
struct log_class_string<const char8_t *, void>
: log_class_string<const char *> {};
template <>
struct log_class_string<char8_t *, void> : log_class_string<const char8_t *> {};
template <typename... Args>
using log_args_t = const void *(&&)[sizeof...(Args) + 1];
struct log_type_info {
decltype(&log_class_string<int>::format) log_string;
template <typename T> static constexpr log_type_info make() {
return log_type_info{
&log_class_string<T>::format,
};
}
};
template <typename... Args>
constexpr const log_type_info type_info_v[sizeof...(Args) + 1]{
log_type_info::make<std::decay_t<Args>>()...};
void _orbis_log_print(LogLevel lvl, const char *msg, std::string_view names,
const log_type_info *sup, ...);
template <typename... Args>
void _orbis_log_impl(LogLevel lvl, const char *msg, const char *names,
const Args &...args) {
// Fast filtering
if (logs_level.load(std::memory_order::relaxed) < lvl)
return;
_orbis_log_print(lvl, msg, names, type_info_v<Args...>,
static_cast<const void *>(&args)...);
}
} // namespace logs
} // namespace orbis
#define ORBIS_LOG_FATAL(msg, ...) \
::orbis::_orbis_log_impl(::orbis::LogLevel::Fatal, (msg), #__VA_ARGS__, \
##__VA_ARGS__)
#define ORBIS_LOG_ERROR(msg, ...) \
::orbis::_orbis_log_impl(::orbis::LogLevel::Error, (msg), #__VA_ARGS__, \
##__VA_ARGS__)
#define ORBIS_LOG_TODO(msg, ...) \
::orbis::_orbis_log_impl(::orbis::LogLevel::Todo, (msg), #__VA_ARGS__, \
##__VA_ARGS__)
#define ORBIS_LOG_SUCCESS(msg, ...) \
::orbis::_orbis_log_impl(::orbis::LogLevel::Success, (msg), #__VA_ARGS__, \
##__VA_ARGS__)
#define ORBIS_LOG_WARNING(msg, ...) \
::orbis::_orbis_log_impl(::orbis::LogLevel::Warning, (msg), #__VA_ARGS__, \
##__VA_ARGS__)
#define ORBIS_LOG_NOTICE(msg, ...) \
::orbis::_orbis_log_impl(::orbis::LogLevel::Notice, (msg), #__VA_ARGS__, \
##__VA_ARGS__)
#define ORBIS_LOG_TRACE(msg, ...) \
::orbis::_orbis_log_impl(::orbis::LogLevel::Trace, (msg), #__VA_ARGS__, \
##__VA_ARGS__)

View file

@ -0,0 +1,124 @@
#pragma once
#include <atomic>
#include <cassert>
#include <type_traits>
#include <utility>
namespace orbis {
inline namespace utils {
struct RcBase {
std::atomic<unsigned> references{0};
virtual ~RcBase() = default;
void incRef() {
if (references.fetch_add(1, std::memory_order::relaxed) > 512) {
assert(!"too many references");
}
}
// returns true if object was destroyed
bool decRef() {
if (references.fetch_sub(1, std::memory_order::relaxed) == 1) {
delete this;
return true;
}
return false;
}
};
template <typename T>
concept WithRc = requires(T t) {
t.incRef();
t.decRef();
};
template <typename T> class Ref {
T *m_ref = nullptr;
public:
Ref() = default;
template <typename OT>
requires(std::is_base_of_v<T, OT>)
Ref(OT *ref) : m_ref(ref) {
ref->incRef();
}
template <typename OT>
requires(std::is_base_of_v<T, OT>)
Ref(const Ref<OT> &other) : m_ref(other.get()) {
if (m_ref != nullptr) {
m_ref->incRef();
}
}
template <typename OT>
requires(std::is_base_of_v<T, OT>)
Ref(Ref<OT> &&other) : m_ref(other.release()) {}
Ref(const Ref &other) : m_ref(other.get()) {
if (m_ref != nullptr) {
m_ref->incRef();
}
}
Ref(Ref &&other) : m_ref(other.release()) {}
template <typename OT>
requires(std::is_base_of_v<T, OT>)
Ref &operator=(Ref<OT> &&other) {
other.swap(*this);
return *this;
}
template <typename OT>
requires(std::is_base_of_v<T, OT>)
Ref &operator=(OT *other) {
*this = Ref(other);
return *this;
}
template <typename OT>
requires(std::is_base_of_v<T, OT>)
Ref &operator=(const Ref<OT> &other) {
*this = Ref(other);
return *this;
}
Ref &operator=(const Ref &other) {
*this = Ref(other);
return *this;
}
Ref &operator=(Ref &&other) {
other.swap(*this);
return *this;
}
~Ref() {
if (m_ref != nullptr) {
m_ref->decRef();
}
}
void swap(Ref<T> &other) { std::swap(m_ref, other.m_ref); }
T *get() const { return m_ref; }
T *release() { return std::exchange(m_ref, nullptr); }
T *operator->() const { return m_ref; }
explicit operator bool() const { return m_ref != nullptr; }
bool operator==(std::nullptr_t) const { return m_ref == nullptr; }
bool operator!=(std::nullptr_t) const { return m_ref != nullptr; }
auto operator<=>(const T *other) const { return m_ref <=> other; }
auto operator<=>(const Ref &other) const = default;
};
template <WithRc T, typename... ArgsT>
requires(std::is_constructible_v<T, ArgsT...>)
Ref<T> create(ArgsT &&...args) {
auto result = new T(std::forward<ArgsT>(args)...);
return Ref<T>(result);
}
} // namespace utils
} // namespace orbis

View file

@ -0,0 +1,144 @@
#pragma once
#include <atomic>
#include <mutex>
#include <orbis/utils/AtomicOp.hpp>
namespace orbis {
inline namespace utils {
// IPC-ready shared mutex, using only writer lock is recommended
struct shared_mutex final {
enum : unsigned {
c_one = 1u << 14, // Fixed-point 1.0 value (one writer)
c_sig = 1u << 30,
c_err = 1u << 31,
};
std::atomic<unsigned> m_value{};
void impl_lock_shared(unsigned val);
void impl_unlock_shared(unsigned old);
void impl_wait();
void impl_signal();
void impl_lock(unsigned val);
void impl_unlock(unsigned old);
void impl_lock_upgrade();
public:
constexpr shared_mutex() = default;
bool try_lock_shared() {
// Conditional increment
unsigned value = m_value.load();
return value < c_one - 1 &&
m_value.compare_exchange_strong(value, value + 1);
}
// Lock with HLE acquire hint
void lock_shared() {
unsigned value = m_value.load();
if (value < c_one - 1) [[likely]] {
unsigned old = value;
if (compare_exchange_hle_acq(m_value, old, value + 1)) [[likely]] {
return;
}
}
impl_lock_shared(value + 1);
}
// Unlock with HLE release hint
void unlock_shared() {
const unsigned value = fetch_add_hle_rel(m_value, -1u);
if (value >= c_one) [[unlikely]] {
impl_unlock_shared(value);
}
}
bool try_lock() {
unsigned value = 0;
return m_value.compare_exchange_strong(value, c_one);
}
// Lock with HLE acquire hint
void lock() {
unsigned value = 0;
if (!compare_exchange_hle_acq(m_value, value, +c_one)) [[unlikely]] {
impl_lock(value);
}
}
// Unlock with HLE release hint
void unlock() {
const unsigned value = fetch_add_hle_rel(m_value, 0u - c_one);
if (value != c_one) [[unlikely]] {
impl_unlock(value);
}
}
bool try_lock_upgrade() {
unsigned value = m_value.load();
// Conditional increment, try to convert a single reader into a writer,
// ignoring other writers
return (value + c_one - 1) % c_one == 0 &&
m_value.compare_exchange_strong(value, value + c_one - 1);
}
void lock_upgrade() {
if (!try_lock_upgrade()) [[unlikely]] {
impl_lock_upgrade();
}
}
void lock_downgrade() {
// Convert to reader lock (can result in broken state)
m_value -= c_one - 1;
}
// Check whether can immediately obtain an exclusive (writer) lock
bool is_free() const { return m_value.load() == 0; }
// Check whether can immediately obtain a shared (reader) lock
bool is_lockable() const { return m_value.load() < c_one - 1; }
};
// Simplified shared (reader) lock implementation.
class reader_lock final {
shared_mutex &m_mutex;
bool m_upgraded = false;
public:
reader_lock(const reader_lock &) = delete;
reader_lock &operator=(const reader_lock &) = delete;
explicit reader_lock(shared_mutex &mutex) : m_mutex(mutex) {
m_mutex.lock_shared();
}
// One-way lock upgrade; note that the observed state could have been changed
void upgrade() {
if (!m_upgraded) {
m_mutex.lock_upgrade();
m_upgraded = true;
}
}
// Try to upgrade; if it succeeds, the observed state has NOT been changed
bool try_upgrade() {
return m_upgraded || (m_upgraded = m_mutex.try_lock_upgrade());
}
~reader_lock() { m_upgraded ? m_mutex.unlock() : m_mutex.unlock_shared(); }
};
class writer_lock final {
shared_mutex &m_mutex;
public:
writer_lock(const writer_lock &) = delete;
writer_lock &operator=(const writer_lock &) = delete;
explicit writer_lock(shared_mutex &mutex) : m_mutex(mutex) { m_mutex.lock(); }
~writer_lock() { m_mutex.unlock(); }
};
} // namespace utils
} // namespace orbis