├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── examples ├── CMakeLists.txt └── standalone │ ├── CMakeLists.txt │ ├── orbis-kernel-config │ └── orbis-config.hpp │ └── src │ └── main.cpp ├── include └── orbis │ ├── KernelContext.hpp │ ├── error.hpp │ ├── error │ ├── ErrorCode.hpp │ └── SysResult.hpp │ ├── module.hpp │ ├── module │ ├── Module.hpp │ ├── ModuleHandle.hpp │ ├── ModuleInfo.hpp │ ├── ModuleInfoEx.hpp │ └── ModuleSegment.hpp │ ├── sys │ ├── syscall.hpp │ ├── sysentry.hpp │ └── sysproto.hpp │ ├── thread.hpp │ ├── thread │ ├── Process.hpp │ ├── ProcessOps.hpp │ ├── ProcessState.hpp │ ├── RegisterId.hpp │ ├── Thread.hpp │ ├── ThreadState.hpp │ ├── cpuset.hpp │ ├── sysent.hpp │ └── types.hpp │ └── utils │ ├── AtomicOp.hpp │ ├── BitSet.hpp │ ├── IdMap.hpp │ ├── LinkedNode.hpp │ ├── Logs.hpp │ ├── Rc.hpp │ └── SharedMutex.hpp └── src ├── module.cpp ├── sys ├── sys_acct.cpp ├── sys_audit.cpp ├── sys_capability.cpp ├── sys_context.cpp ├── sys_cpuset.cpp ├── sys_descrip.cpp ├── sys_environment.cpp ├── sys_event.cpp ├── sys_exec.cpp ├── sys_exit.cpp ├── sys_fork.cpp ├── sys_generic.cpp ├── sys_jail.cpp ├── sys_ktrace.cpp ├── sys_linker.cpp ├── sys_loginclass.cpp ├── sys_mac.cpp ├── sys_module.cpp ├── sys_msg.cpp ├── sys_ntptime.cpp ├── sys_p1003_1b.cpp ├── sys_pipe.cpp ├── sys_procdesc.cpp ├── sys_process.cpp ├── sys_prot.cpp ├── sys_pty_pts.cpp ├── sys_rctl.cpp ├── sys_resource.cpp ├── sys_route.cpp ├── sys_sce.cpp ├── sys_sem.cpp ├── sys_shm.cpp ├── sys_shutdown.cpp ├── sys_sig.cpp ├── sys_subr_prof.cpp ├── sys_swap_pager.cpp ├── sys_synch.cpp ├── sys_sysctl.cpp ├── sys_thr.cpp ├── sys_time.cpp ├── sys_uipc.cpp ├── sys_uipc_mqueue.cpp ├── sys_uipc_sem.cpp ├── sys_uipc_shm.cpp ├── sys_umtx.cpp ├── sys_uuid.cpp ├── sys_vfs.cpp ├── sys_vfs_acl.cpp ├── sys_vfs_aio.cpp ├── sys_vfs_cache.cpp ├── sys_vfs_extattr.cpp ├── sys_vfs_mount.cpp ├── sys_vm_mmap.cpp └── sys_vm_unix.cpp ├── sysvec.cpp └── utils ├── Logs.cpp └── SharedMutex.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | compile_commands.json 3 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(CMAKE_POSITION_INDEPENDENT_CODE on) 2 | 3 | add_library(obj.orbis-kernel OBJECT 4 | src/module.cpp 5 | src/sysvec.cpp 6 | src/sys/sys_acct.cpp 7 | src/sys/sys_audit.cpp 8 | src/sys/sys_capability.cpp 9 | src/sys/sys_context.cpp 10 | src/sys/sys_cpuset.cpp 11 | src/sys/sys_descrip.cpp 12 | src/sys/sys_environment.cpp 13 | src/sys/sys_event.cpp 14 | src/sys/sys_exec.cpp 15 | src/sys/sys_exit.cpp 16 | src/sys/sys_fork.cpp 17 | src/sys/sys_generic.cpp 18 | src/sys/sys_jail.cpp 19 | src/sys/sys_ktrace.cpp 20 | src/sys/sys_linker.cpp 21 | src/sys/sys_loginclass.cpp 22 | src/sys/sys_mac.cpp 23 | src/sys/sys_module.cpp 24 | src/sys/sys_msg.cpp 25 | src/sys/sys_ntptime.cpp 26 | src/sys/sys_p1003_1b.cpp 27 | src/sys/sys_pipe.cpp 28 | src/sys/sys_procdesc.cpp 29 | src/sys/sys_process.cpp 30 | src/sys/sys_prot.cpp 31 | src/sys/sys_pty_pts.cpp 32 | src/sys/sys_rctl.cpp 33 | src/sys/sys_resource.cpp 34 | src/sys/sys_route.cpp 35 | src/sys/sys_sce.cpp 36 | src/sys/sys_sem.cpp 37 | src/sys/sys_shm.cpp 38 | src/sys/sys_shutdown.cpp 39 | src/sys/sys_sig.cpp 40 | src/sys/sys_subr_prof.cpp 41 | src/sys/sys_swap_pager.cpp 42 | src/sys/sys_synch.cpp 43 | src/sys/sys_sysctl.cpp 44 | src/sys/sys_thr.cpp 45 | src/sys/sys_time.cpp 46 | src/sys/sys_uipc_mqueue.cpp 47 | src/sys/sys_uipc_sem.cpp 48 | src/sys/sys_uipc_shm.cpp 49 | src/sys/sys_uipc.cpp 50 | src/sys/sys_umtx.cpp 51 | src/sys/sys_uuid.cpp 52 | src/sys/sys_vfs_acl.cpp 53 | src/sys/sys_vfs_aio.cpp 54 | src/sys/sys_vfs_cache.cpp 55 | src/sys/sys_vfs_extattr.cpp 56 | src/sys/sys_vfs_mount.cpp 57 | src/sys/sys_vfs.cpp 58 | src/sys/sys_vm_mmap.cpp 59 | src/sys/sys_vm_unix.cpp 60 | 61 | src/utils/Logs.cpp 62 | src/utils/SharedMutex.cpp 63 | ) 64 | 65 | target_link_libraries(obj.orbis-kernel PUBLIC orbis::kernel::config) 66 | 67 | target_include_directories(obj.orbis-kernel 68 | PUBLIC 69 | include 70 | 71 | PRIVATE 72 | include/orbis 73 | ) 74 | 75 | add_library(orbis-kernel STATIC) 76 | add_library(orbis-kernel-shared SHARED) 77 | add_library(orbis::kernel ALIAS orbis-kernel) 78 | add_library(orbis::kernel-shared ALIAS orbis-kernel-shared) 79 | 80 | target_link_libraries(orbis-kernel PUBLIC obj.orbis-kernel) 81 | target_link_libraries(orbis-kernel-shared PUBLIC obj.orbis-kernel) 82 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 - present RPCS4 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.25) 2 | 3 | project(orbis-kernel-examples) 4 | 5 | if("${ORBIS_KERNEL_DIR}" STREQUAL "") 6 | set(ORBIS_KERNEL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/..) 7 | cmake_path(ABSOLUTE_PATH ORBIS_KERNEL_DIR NORMALIZE) 8 | endif() 9 | 10 | set(CMAKE_CXX_STANDARD 23) 11 | add_subdirectory(standalone) 12 | add_subdirectory(${ORBIS_KERNEL_DIR} orbis-kernel EXCLUDE_FROM_ALL ) 13 | 14 | -------------------------------------------------------------------------------- /examples/standalone/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(standalone-config INTERFACE) 3 | target_include_directories(standalone-config INTERFACE orbis-kernel-config) 4 | add_library(orbis::kernel::config ALIAS standalone-config) 5 | 6 | add_executable(standalone src/main.cpp) 7 | target_include_directories(standalone PUBLIC include) 8 | 9 | target_link_libraries(standalone PUBLIC orbis::kernel) 10 | -------------------------------------------------------------------------------- /examples/standalone/orbis-kernel-config/orbis-config.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "orbis/error.hpp" 4 | #include "orbis/thread/RegisterId.hpp" 5 | #include 6 | #include 7 | 8 | namespace orbis { 9 | using int8_t = std::int8_t; 10 | using int16_t = std::int16_t; 11 | using int32_t = std::int32_t; 12 | using int64_t = std::int64_t; 13 | 14 | using uint8_t = std::uint8_t; 15 | using uint16_t = std::uint16_t; 16 | using uint32_t = std::uint32_t; 17 | using uint64_t = std::uint64_t; 18 | 19 | using size_t = uint64_t; 20 | using ssize_t = int64_t; 21 | using off_t = int64_t; 22 | 23 | using uint = uint32_t; 24 | using sint = int32_t; 25 | 26 | using slong = int64_t; 27 | using ulong = uint64_t; 28 | 29 | template using ptr = T *; 30 | template using cptr = T * const; 31 | 32 | using caddr_t = ptr; 33 | 34 | inline ErrorCode uread(void *kernelAddress, ptr userAddress, 35 | size_t size) { 36 | std::memcpy(kernelAddress, userAddress, size); 37 | return {}; 38 | } 39 | 40 | inline ErrorCode uwrite(ptr userAddress, const void *kernelAddress, 41 | size_t size) { 42 | std::memcpy(userAddress, kernelAddress, size); 43 | return {}; 44 | } 45 | 46 | inline ErrorCode ureadString(char *kernelAddress, size_t kernelSize, ptr userAddress) { 47 | std::strncpy(kernelAddress, userAddress, kernelSize); 48 | if (kernelAddress[kernelSize - 1] != '\0') { 49 | kernelAddress[kernelSize - 1] = '\0'; 50 | return ErrorCode::NAMETOOLONG; 51 | } 52 | 53 | return {}; 54 | } 55 | 56 | template T uread(ptr pointer) { 57 | T result; 58 | uread(&result, pointer, sizeof(T)); 59 | return result; 60 | } 61 | 62 | template void uwrite(ptr pointer, T data) { 63 | uwrite(pointer, &data, sizeof(T)); 64 | } 65 | 66 | uint64_t readRegister(void *context, RegisterId id); 67 | void writeRegister(void *context, RegisterId id, uint64_t value); 68 | } // namespace orbis 69 | -------------------------------------------------------------------------------- /examples/standalone/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "orbis/sys/syscall.hpp" 2 | #include "orbis/thread/Process.hpp" 3 | #include "orbis/thread/ProcessOps.hpp" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | struct Registers { 18 | std::uint64_t r15; 19 | std::uint64_t r14; 20 | std::uint64_t r13; 21 | std::uint64_t r12; 22 | std::uint64_t r11; 23 | std::uint64_t r10; 24 | std::uint64_t r9; 25 | std::uint64_t r8; 26 | std::uint64_t rdi; 27 | std::uint64_t rsi; 28 | std::uint64_t rbp; 29 | std::uint64_t rbx; 30 | std::uint64_t rdx; 31 | std::uint64_t rcx; 32 | std::uint64_t rax; 33 | std::uint64_t rsp; 34 | std::uint64_t rflags; 35 | }; 36 | 37 | namespace orbis { 38 | uint64_t readRegister(void *context, RegisterId id) { 39 | auto c = reinterpret_cast(context); 40 | switch (id) { 41 | case RegisterId::r15: return c->r15; 42 | case RegisterId::r14: return c->r14; 43 | case RegisterId::r13: return c->r13; 44 | case RegisterId::r12: return c->r12; 45 | case RegisterId::r11: return c->r11; 46 | case RegisterId::r10: return c->r10; 47 | case RegisterId::r9: return c->r9; 48 | case RegisterId::r8: return c->r8; 49 | case RegisterId::rdi: return c->rdi; 50 | case RegisterId::rsi: return c->rsi; 51 | case RegisterId::rbp: return c->rbp; 52 | case RegisterId::rbx: return c->rbx; 53 | case RegisterId::rdx: return c->rdx; 54 | case RegisterId::rcx: return c->rcx; 55 | case RegisterId::rax: return c->rax; 56 | case RegisterId::rsp: return c->rsp; 57 | case RegisterId::rflags: return c->rflags; 58 | } 59 | } 60 | 61 | void writeRegister(void *context, RegisterId id, uint64_t value) { 62 | auto c = reinterpret_cast(context); 63 | switch (id) { 64 | case RegisterId::r15: c->r15 = value; return; 65 | case RegisterId::r14: c->r14 = value; return; 66 | case RegisterId::r13: c->r13 = value; return; 67 | case RegisterId::r12: c->r12 = value; return; 68 | case RegisterId::r11: c->r11 = value; return; 69 | case RegisterId::r10: c->r10 = value; return; 70 | case RegisterId::r9: c->r9 = value; return; 71 | case RegisterId::r8: c->r8 = value; return; 72 | case RegisterId::rdi: c->rdi = value; return; 73 | case RegisterId::rsi: c->rsi = value; return; 74 | case RegisterId::rbp: c->rbp = value; return; 75 | case RegisterId::rbx: c->rbx = value; return; 76 | case RegisterId::rdx: c->rdx = value; return; 77 | case RegisterId::rcx: c->rcx = value; return; 78 | case RegisterId::rax: c->rax = value; return; 79 | case RegisterId::rsp: c->rsp = value; return; 80 | case RegisterId::rflags: c->rflags = value; return; 81 | } 82 | } 83 | } 84 | 85 | static thread_local orbis::Thread *g_guestThread = nullptr; 86 | 87 | class CPU { 88 | struct Task { 89 | orbis::Thread *thread; 90 | std::function job; 91 | }; 92 | 93 | int m_index; 94 | std::deque m_workQueue; 95 | std::condition_variable m_cv; 96 | std::mutex m_mtx; 97 | std::atomic m_terminate_flag{false}; 98 | std::thread m_hostThread{[this] { entry(); }}; 99 | 100 | public: 101 | CPU(int index) : m_index(index) {} 102 | 103 | int getIndex() const { 104 | return m_index; 105 | } 106 | 107 | void addTask(orbis::Thread *thread, std::function task) { 108 | m_workQueue.push_back({thread, std::move(task)}); 109 | m_cv.notify_one(); 110 | } 111 | 112 | ~CPU() { 113 | m_terminate_flag = true; 114 | m_cv.notify_all(); 115 | m_hostThread.join(); 116 | } 117 | 118 | void entry() { 119 | while (!m_terminate_flag) { 120 | Task task; 121 | { 122 | std::unique_lock lock(m_mtx); 123 | m_cv.wait(lock, 124 | [this] { return !m_workQueue.empty() || m_terminate_flag; }); 125 | 126 | if (m_terminate_flag) { 127 | break; 128 | } 129 | 130 | task = std::move(m_workQueue.front()); 131 | m_workQueue.pop_front(); 132 | } 133 | 134 | task.thread->state = orbis::ThreadState::RUNNING; 135 | g_guestThread = task.thread; 136 | task.job(); 137 | if (task.thread->state == orbis::ThreadState::RUNNING) { 138 | task.thread->state = orbis::ThreadState::INACTIVE; 139 | } 140 | } 141 | } 142 | }; 143 | 144 | class Event { 145 | std::condition_variable m_cv; 146 | std::mutex m_mtx; 147 | std::atomic m_fired; 148 | 149 | public: 150 | void wait() { 151 | std::unique_lock lock(m_mtx); 152 | m_cv.wait(lock, [&] { return m_fired == true; }); 153 | m_fired = false; 154 | } 155 | 156 | void fire() { 157 | m_fired = true; 158 | m_cv.notify_all(); 159 | } 160 | }; 161 | 162 | struct orbis::ProcessOps procOps = { 163 | .exit = [](orbis::Thread *, orbis::sint status) -> orbis::SysResult { 164 | std::printf("sys_exit(%u)\n", status); 165 | std::exit(status); 166 | } 167 | }; 168 | 169 | static orbis::Thread *allocateGuestThread(orbis::Process *process, 170 | orbis::lwpid_t tid) { 171 | auto guestThread = new orbis::Thread{}; 172 | guestThread->state = orbis::ThreadState::RUNQ; 173 | guestThread->tid = tid; 174 | guestThread->tproc = process; 175 | return guestThread; 176 | } 177 | 178 | 179 | static void onSysEnter(orbis::Thread *thread, int id, uint64_t *args, 180 | int argsCount) { 181 | std::printf(" [%u] sys_%u(", thread->tid, id); 182 | 183 | for (int i = 0; i < argsCount; ++i) { 184 | if (i != 0) { 185 | std::printf(", "); 186 | } 187 | 188 | std::printf("%#lx", args[i]); 189 | } 190 | 191 | std::printf(")\n"); 192 | } 193 | 194 | static void onSysExit(orbis::Thread *thread, int id, uint64_t *args, 195 | int argsCount, orbis::SysResult result) { 196 | std::printf("%c: [%u] sys_%u(", result.isError() ? 'E' : 'S', thread->tid, 197 | id); 198 | 199 | for (int i = 0; i < argsCount; ++i) { 200 | if (i != 0) { 201 | std::printf(", "); 202 | } 203 | 204 | std::printf("%#lx", args[i]); 205 | } 206 | 207 | std::printf(") -> Status %d, Value %lx:%lx\n", result.value(), 208 | thread->retval[0], thread->retval[1]); 209 | } 210 | 211 | struct KernelEventLogger : public orbis::KernelContext::EventListener { 212 | void onProcessCreated(orbis::Process *process) override { 213 | std::printf("process %u was created\n", (unsigned)process->pid); 214 | } 215 | void onProcessDeleted(orbis::pid_t pid) override { 216 | std::printf("process %u was deleted\n", (unsigned)pid); 217 | } 218 | }; 219 | 220 | int main() { 221 | KernelEventLogger eventLogger; 222 | orbis::KernelContext context; 223 | context.addEventListener(&eventLogger); 224 | auto initProc = context.createProcess(1); 225 | 226 | initProc->ops = &procOps; 227 | initProc->onSysEnter = onSysEnter; 228 | initProc->onSysExit = onSysExit; 229 | 230 | initProc->state = orbis::ProcessState::NORMAL; 231 | initProc->parentProcess = initProc; 232 | initProc->sysent = &orbis::freebsd9_sysvec; 233 | 234 | auto initMainThread = allocateGuestThread(initProc, 1); 235 | 236 | CPU cpu{0}; 237 | Event completeEvent; 238 | cpu.addTask(initMainThread, [&completeEvent] { 239 | Registers regs{}; 240 | regs.rax = orbis::kSYS_syscall; 241 | regs.rdi = orbis::kSYS_exit; 242 | regs.rsi = 0x64; 243 | g_guestThread->context = ®s; 244 | 245 | orbis::syscall_entry(g_guestThread); 246 | 247 | completeEvent.fire(); 248 | }); 249 | 250 | completeEvent.wait(); 251 | delete initMainThread; 252 | return 0; 253 | } 254 | -------------------------------------------------------------------------------- /include/orbis/KernelContext.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "orbis/thread/Process.hpp" 3 | #include "utils/LinkedNode.hpp" 4 | #include "utils/SharedMutex.hpp" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace orbis { 12 | class KernelContext { 13 | public: 14 | struct EventListener { 15 | virtual ~EventListener() = default; 16 | virtual void onProcessCreated(Process *) = 0; 17 | virtual void onProcessDeleted(pid_t pid) = 0; 18 | }; 19 | 20 | ~KernelContext() { 21 | while (m_processes != nullptr) { 22 | deleteProcess(&m_processes->object); 23 | } 24 | } 25 | 26 | void addEventListener(EventListener *listener) { 27 | m_event_listeners.push_back(listener); 28 | } 29 | 30 | void removeEventListener(EventListener *listener) { 31 | auto it = 32 | std::find(m_event_listeners.begin(), m_event_listeners.end(), listener); 33 | 34 | if (it != m_event_listeners.end()) { 35 | m_event_listeners.erase(it); 36 | } 37 | } 38 | 39 | Process *createProcess(pid_t pid) { 40 | auto newProcess = new utils::LinkedNode(); 41 | newProcess->object.context = this; 42 | newProcess->object.pid = pid; 43 | newProcess->object.state = ProcessState::NEW; 44 | 45 | { 46 | std::lock_guard lock(m_proc_mtx); 47 | if (m_processes != nullptr) { 48 | m_processes->insertPrev(*newProcess); 49 | } 50 | 51 | m_processes = newProcess; 52 | } 53 | 54 | for (auto listener : m_event_listeners) { 55 | listener->onProcessCreated(&newProcess->object); 56 | } 57 | 58 | return &newProcess->object; 59 | } 60 | 61 | void deleteProcess(Process *proc) { 62 | auto procNode = reinterpret_cast *>(proc); 63 | auto pid = proc->pid; 64 | 65 | { 66 | std::lock_guard lock(m_proc_mtx); 67 | auto next = procNode->erase(); 68 | 69 | if (procNode == m_processes) { 70 | m_processes = next; 71 | } 72 | } 73 | 74 | delete procNode; 75 | 76 | for (auto listener : m_event_listeners) { 77 | listener->onProcessDeleted(pid); 78 | } 79 | } 80 | 81 | Process *findProcessById(pid_t pid) const { 82 | std::lock_guard lock(m_proc_mtx); 83 | for (auto proc = m_processes; proc != nullptr; proc = proc->next) { 84 | if (proc->object.pid == pid) { 85 | return &proc->object; 86 | } 87 | } 88 | 89 | return nullptr; 90 | } 91 | 92 | private: 93 | mutable shared_mutex m_proc_mtx; 94 | utils::LinkedNode *m_processes = nullptr; 95 | std::vector m_event_listeners; 96 | }; 97 | } // namespace orbis -------------------------------------------------------------------------------- /include/orbis/error.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "error/SysResult.hpp" // IWYU pragma: export 4 | #include "error/ErrorCode.hpp" // IWYU pragma: export 5 | -------------------------------------------------------------------------------- /include/orbis/error/ErrorCode.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace orbis { 4 | enum class ErrorCode : int { 5 | PERM = 1, // Operation not permitted 6 | NOENT = 2, // No such file or directory 7 | SRCH = 3, // No such process 8 | INTR = 4, // Interrupted system call 9 | IO = 5, // Input/output error 10 | NXIO = 6, // Device not configured 11 | TOOBIG = 7, // Argument list too long 12 | NOEXEC = 8, // Exec format error 13 | BADF = 9, // Bad file descriptor 14 | CHILD = 10, // No child processes 15 | DEADLK = 11, // Resource deadlock avoided 16 | 17 | NOMEM = 12, // Cannot allocate memory 18 | ACCES = 13, // Permission denied 19 | FAULT = 14, // Bad address 20 | NOTBLK = 15, // Block device required 21 | BUSY = 16, // Device busy 22 | EXIST = 17, // File exists 23 | XDEV = 18, // Cross-device link 24 | NODEV = 19, // Operation not supported by device 25 | NOTDIR = 20, // Not a directory 26 | ISDIR = 21, // Is a directory 27 | INVAL = 22, // Invalid argument 28 | NFILE = 23, // Too many open files in system 29 | MFILE = 24, // Too many open files 30 | NOTTY = 25, // Inappropriate ioctl for device 31 | TXTBSY = 26, // Text file busy 32 | FBIG = 27, // File too large 33 | NOSPC = 28, // No space left on device 34 | SPIPE = 29, // Illegal seek 35 | ROFS = 30, // Read-only filesystem 36 | MLINK = 31, // Too many links 37 | PIPE = 32, // Broken pipe 38 | 39 | DOM = 33, // Numerical argument out of domain 40 | RANGE = 34, // Result too large 41 | 42 | AGAIN = 35, // Resource temporarily unavailable 43 | WOULDBLOCK = AGAIN, // Operation would block 44 | INPROGRESS = 36, // Operation now in progress 45 | ALREADY = 37, // Operation already in progress 46 | 47 | NOTSOCK = 38, // Socket operation on non-socket 48 | DESTADDRREQ = 39, // Destination address required 49 | MSGSIZE = 40, // Message too long 50 | PROTOTYPE = 41, // Protocol wrong type for socket 51 | NOPROTOOPT = 42, // Protocol not available 52 | PROTONOSUPPORT = 43, // Protocol not supported 53 | SOCKTNOSUPPORT = 44, // Socket type not supported 54 | OPNOTSUPP = 45, // Operation not supported 55 | NOTSUP = OPNOTSUPP, // Operation not supported 56 | PFNOSUPPORT = 46, // Protocol family not supported 57 | AFNOSUPPORT = 47, // Address family not supported by protocol family 58 | ADDRINUSE = 48, // Address already in use 59 | ADDRNOTAVAIL = 49, // Can't assign requested address 60 | 61 | NETDOWN = 50, // Network is down 62 | NETUNREACH = 51, // Network is unreachable 63 | NETRESET = 52, // Network dropped connection on reset 64 | CONNABORTED = 53, // Software caused connection abort 65 | CONNRESET = 54, // Connection reset by peer 66 | NOBUFS = 55, // No buffer space available 67 | ISCONN = 56, // Socket is already connected 68 | NOTCONN = 57, // Socket is not connected 69 | SHUTDOWN = 58, // Can't send after socket shutdown 70 | TOOMANYREFS = 59, // Too many references: can't splice 71 | TIMEDOUT = 60, // Operation timed out 72 | CONNREFUSED = 61, // Connection refused 73 | 74 | LOOP = 62, // Too many levels of symbolic links 75 | NAMETOOLONG = 63, // File name too long 76 | HOSTDOWN = 64, // Host is down 77 | HOSTUNREACH = 65, // No route to host 78 | NOTEMPTY = 66, // Directory not empty 79 | PROCLIM = 67, // Too many processes 80 | USERS = 68, // Too many users 81 | DQUOT = 69, // Disc quota exceeded 82 | STALE = 70, // Stale NFS file handle 83 | REMOTE = 71, // Too many levels of remote in path 84 | BADRPC = 72, // RPC struct is bad 85 | RPCMISMATCH = 73, // RPC version wrong 86 | PROGUNAVAIL = 74, // RPC prog. not avail 87 | PROGMISMATCH = 75, // Program version wrong 88 | PROCUNAVAIL = 76, // Bad procedure for program 89 | NOLCK = 77, // No locks available 90 | NOSYS = 78, // Function not implemented 91 | FTYPE = 79, // Inappropriate file type or format 92 | AUTH = 80, // Authentication error 93 | NEEDAUTH = 81, // Need authenticator 94 | IDRM = 82, // Identifier removed 95 | NOMSG = 83, // No message of desired type 96 | OVERFLOW = 84, // Value too large to be stored in data type 97 | CANCELED = 85, // Operation canceled 98 | ILSEQ = 86, // Illegal byte sequence 99 | NOATTR = 87, // Attribute not found 100 | 101 | DOOFUS = 88, // Programming error 102 | 103 | BADMSG = 89, // Bad message 104 | MULTIHOP = 90, // Multihop attempted 105 | NOLINK = 91, // Link has been severed 106 | PROTO = 92, // Protocol error 107 | 108 | NOTCAPABLE = 93, // Capabilities insufficient 109 | CAPMODE = 94, // Not permitted in capability mode 110 | }; 111 | } // namespace orbis 112 | -------------------------------------------------------------------------------- /include/orbis/error/SysResult.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace orbis { 4 | enum class ErrorCode : int; 5 | 6 | class SysResult { 7 | int mValue = 0; 8 | 9 | public: 10 | SysResult() = default; 11 | SysResult(ErrorCode ec) : mValue(-static_cast(ec)){} 12 | 13 | [[nodiscard]] static SysResult notAnError(ErrorCode ec) { 14 | SysResult result; 15 | result.mValue = static_cast(ec); 16 | return result; 17 | } 18 | 19 | [[nodiscard]] int value() const { return mValue < 0 ? -mValue : mValue; } 20 | [[nodiscard]] bool isError() const { return mValue < 0; } 21 | }; 22 | } // namespace orbis 23 | -------------------------------------------------------------------------------- /include/orbis/module.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "module/Module.hpp" // IWYU pragma: export 4 | #include "module/ModuleHandle.hpp" // IWYU pragma: export 5 | #include "module/ModuleInfo.hpp" // IWYU pragma: export 6 | #include "module/ModuleInfoEx.hpp" // IWYU pragma: export 7 | #include "module/ModuleSegment.hpp" // IWYU pragma: export 8 | -------------------------------------------------------------------------------- /include/orbis/module/Module.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleHandle.hpp" 4 | #include "ModuleSegment.hpp" 5 | 6 | #include "../utils/Rc.hpp" 7 | 8 | #include "orbis-config.hpp" 9 | #include 10 | #include 11 | #include 12 | 13 | namespace orbis { 14 | struct Thread; 15 | struct Process; 16 | 17 | struct ModuleNeeded { 18 | std::string name; 19 | std::uint16_t version; 20 | std::uint16_t attr; 21 | bool isExport; 22 | }; 23 | 24 | enum class SymbolBind : std::uint8_t { 25 | Local, 26 | Global, 27 | Weak, 28 | Unique = 10 29 | }; 30 | 31 | enum class SymbolVisibility : std::uint8_t { 32 | Default, 33 | Internal, 34 | Hidden, 35 | Protected 36 | }; 37 | 38 | enum class SymbolType : std::uint8_t { 39 | NoType, 40 | Object, 41 | Function, 42 | Section, 43 | File, 44 | Common, 45 | Tls, 46 | IFunc = 10, 47 | }; 48 | 49 | 50 | struct Symbol { 51 | std::int32_t moduleIndex; 52 | std::uint32_t libraryIndex; 53 | std::uint64_t id; 54 | std::uint64_t address; 55 | std::uint64_t size; 56 | SymbolVisibility visibility; 57 | SymbolBind bind; 58 | SymbolType type; 59 | }; 60 | 61 | struct Relocation { 62 | std::uint64_t offset; 63 | std::uint32_t relType; 64 | std::uint32_t symbolIndex; 65 | std::int64_t addend; 66 | }; 67 | 68 | struct Module { 69 | Process *proc{}; 70 | std::string vfsPath; 71 | char moduleName[256]{}; 72 | char soName[256]{}; 73 | ModuleHandle id{}; 74 | uint32_t tlsIndex{}; 75 | ptr tlsInit{}; 76 | uint32_t tlsInitSize{}; 77 | uint32_t tlsSize{}; 78 | uint32_t tlsOffset{}; 79 | uint32_t tlsAlign{}; 80 | ptr initProc{}; 81 | ptr finiProc{}; 82 | ptr ehFrameHdr{}; 83 | ptr ehFrame{}; 84 | uint32_t ehFrameHdrSize{}; 85 | uint32_t ehFrameSize{}; 86 | ModuleSegment segments[4]{}; 87 | uint32_t segmentCount{}; 88 | std::uint8_t fingerprint[20]{}; 89 | ptr base{}; 90 | uint64_t size{}; 91 | ptr stackStart{}; 92 | ptr stackEnd{}; 93 | ptr processParam{}; 94 | uint64_t processParamSize{}; 95 | ptr moduleParam{}; 96 | uint64_t moduleParamSize{}; 97 | 98 | ptr pltGot{}; 99 | 100 | uint16_t version{}; 101 | uint16_t attributes{}; 102 | uint16_t type{}; 103 | uint16_t flags{}; 104 | uint64_t entryPoint{}; 105 | 106 | uint32_t phNum{}; 107 | uint64_t phdrAddress{}; 108 | 109 | bool isTlsDone = false; 110 | 111 | std::vector symbols; 112 | std::vector pltRelocations; 113 | std::vector nonPltRelocations; 114 | std::vector neededModules; 115 | std::vector neededLibraries; 116 | std::vector> importedModules; 117 | std::vector> namespaceModules; 118 | std::vector needed; 119 | 120 | std::atomic references{0}; 121 | 122 | void incRef() { 123 | if (references.fetch_add(1, std::memory_order::relaxed) > 512) { 124 | assert(!"too many references"); 125 | } 126 | } 127 | 128 | void decRef() { 129 | if (references.fetch_sub(1, std::memory_order::relaxed) == 1 && proc != nullptr) { 130 | destroy(); 131 | } 132 | } 133 | 134 | orbis::SysResult relocate(Process *process); 135 | 136 | private: 137 | void destroy(); 138 | }; 139 | 140 | utils::Ref createModule(Thread *p, std::string vfsPath, const char *name); 141 | } // namespace orbis 142 | -------------------------------------------------------------------------------- /include/orbis/module/ModuleHandle.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace orbis { 6 | enum class ModuleHandle : std::uint32_t {}; 7 | } // namespace orbis 8 | -------------------------------------------------------------------------------- /include/orbis/module/ModuleInfo.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleSegment.hpp" 4 | 5 | #include "orbis-config.hpp" 6 | 7 | namespace orbis { 8 | struct ModuleInfo { 9 | uint64_t size; 10 | char name[256]; 11 | ModuleSegment segments[4]; 12 | uint32_t segmentCount; 13 | uint8_t fingerprint[20]; 14 | }; 15 | } // namespace orbis 16 | -------------------------------------------------------------------------------- /include/orbis/module/ModuleInfoEx.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleSegment.hpp" 4 | 5 | #include "orbis-config.hpp" 6 | 7 | namespace orbis { 8 | struct ModuleInfoEx { 9 | uint64_t size; 10 | char name[256]; 11 | uint32_t id; 12 | uint32_t tlsIndex; 13 | ptr tlsInit; 14 | uint32_t tlsInitSize; 15 | uint32_t tlsSize; 16 | uint32_t tlsOffset; 17 | uint32_t tlsAlign; 18 | ptr initProc; 19 | ptr finiProc; 20 | uint64_t reserved1; 21 | uint64_t reserved2; 22 | ptr ehFrameHdr; 23 | ptr ehFrame; 24 | uint32_t ehFrameHdrSize; 25 | uint32_t ehFrameSize; 26 | ModuleSegment segments[4]; 27 | uint32_t segmentCount; 28 | uint32_t refCount; 29 | }; 30 | } // namespace orbis 31 | -------------------------------------------------------------------------------- /include/orbis/module/ModuleSegment.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "orbis-config.hpp" 4 | 5 | namespace orbis { 6 | struct ModuleSegment { 7 | ptr addr; 8 | uint32_t size; 9 | uint32_t prot; 10 | }; 11 | } // namespace orbis 12 | -------------------------------------------------------------------------------- /include/orbis/sys/syscall.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace orbis { 4 | enum Syscall { 5 | kSYS_syscall = 0, 6 | kSYS_exit = 1, 7 | kSYS_fork = 2, 8 | kSYS_read = 3, 9 | kSYS_write = 4, 10 | kSYS_open = 5, 11 | kSYS_close = 6, 12 | kSYS_wait4 = 7, 13 | kSYS_link = 9, 14 | kSYS_unlink = 10, 15 | kSYS_chdir = 12, 16 | kSYS_fchdir = 13, 17 | kSYS_mknod = 14, 18 | kSYS_chmod = 15, 19 | kSYS_chown = 16, 20 | kSYS_break = 17, 21 | kSYS_freebsd4_getfsstat = 18, 22 | kSYS_getpid = 20, 23 | kSYS_mount = 21, 24 | kSYS_unmount = 22, 25 | kSYS_setuid = 23, 26 | kSYS_getuid = 24, 27 | kSYS_geteuid = 25, 28 | kSYS_ptrace = 26, 29 | kSYS_recvmsg = 27, 30 | kSYS_sendmsg = 28, 31 | kSYS_recvfrom = 29, 32 | kSYS_accept = 30, 33 | kSYS_getpeername = 31, 34 | kSYS_getsockname = 32, 35 | kSYS_access = 33, 36 | kSYS_chflags = 34, 37 | kSYS_fchflags = 35, 38 | kSYS_sync = 36, 39 | kSYS_kill = 37, 40 | kSYS_getppid = 39, 41 | kSYS_dup = 41, 42 | kSYS_pipe = 42, 43 | kSYS_getegid = 43, 44 | kSYS_profil = 44, 45 | kSYS_ktrace = 45, 46 | kSYS_getgid = 47, 47 | kSYS_getlogin = 49, 48 | kSYS_setlogin = 50, 49 | kSYS_acct = 51, 50 | kSYS_sigaltstack = 53, 51 | kSYS_ioctl = 54, 52 | kSYS_reboot = 55, 53 | kSYS_revoke = 56, 54 | kSYS_symlink = 57, 55 | kSYS_readlink = 58, 56 | kSYS_execve = 59, 57 | kSYS_umask = 60, 58 | kSYS_chroot = 61, 59 | kSYS_msync = 65, 60 | kSYS_vfork = 66, 61 | kSYS_sbrk = 69, 62 | kSYS_sstk = 70, 63 | kSYS_vadvise = 72, 64 | kSYS_munmap = 73, 65 | kSYS_mprotect = 74, 66 | kSYS_madvise = 75, 67 | kSYS_mincore = 78, 68 | kSYS_getgroups = 79, 69 | kSYS_setgroups = 80, 70 | kSYS_getpgrp = 81, 71 | kSYS_setpgid = 82, 72 | kSYS_setitimer = 83, 73 | kSYS_swapon = 85, 74 | kSYS_getitimer = 86, 75 | kSYS_getdtablesize = 89, 76 | kSYS_dup2 = 90, 77 | kSYS_fcntl = 92, 78 | kSYS_select = 93, 79 | kSYS_fsync = 95, 80 | kSYS_setpriority = 96, 81 | kSYS_socket = 97, 82 | kSYS_connect = 98, 83 | kSYS_getpriority = 100, 84 | kSYS_bind = 104, 85 | kSYS_setsockopt = 105, 86 | kSYS_listen = 106, 87 | kSYS_gettimeofday = 116, 88 | kSYS_getrusage = 117, 89 | kSYS_getsockopt = 118, 90 | kSYS_readv = 120, 91 | kSYS_writev = 121, 92 | kSYS_settimeofday = 122, 93 | kSYS_fchown = 123, 94 | kSYS_fchmod = 124, 95 | kSYS_setreuid = 126, 96 | kSYS_setregid = 127, 97 | kSYS_rename = 128, 98 | kSYS_flock = 131, 99 | kSYS_mkfifo = 132, 100 | kSYS_sendto = 133, 101 | kSYS_shutdown = 134, 102 | kSYS_socketpair = 135, 103 | kSYS_mkdir = 136, 104 | kSYS_rmdir = 137, 105 | kSYS_utimes = 138, 106 | kSYS_adjtime = 140, 107 | kSYS_setsid = 147, 108 | kSYS_quotactl = 148, 109 | kSYS_nlm_syscall = 154, 110 | kSYS_nfssvc = 155, 111 | kSYS_freebsd4_statfs = 157, 112 | kSYS_freebsd4_fstatfs = 158, 113 | kSYS_lgetfh = 160, 114 | kSYS_getfh = 161, 115 | kSYS_freebsd4_getdomainname = 162, 116 | kSYS_freebsd4_setdomainname = 163, 117 | kSYS_freebsd4_uname = 164, 118 | kSYS_sysarch = 165, 119 | kSYS_rtprio = 166, 120 | kSYS_semsys = 169, 121 | kSYS_msgsys = 170, 122 | kSYS_shmsys = 171, 123 | kSYS_freebsd6_pread = 173, 124 | kSYS_freebsd6_pwrite = 174, 125 | kSYS_setfib = 175, 126 | kSYS_ntp_adjtime = 176, 127 | kSYS_setgid = 181, 128 | kSYS_setegid = 182, 129 | kSYS_seteuid = 183, 130 | kSYS_stat = 188, 131 | kSYS_fstat = 189, 132 | kSYS_lstat = 190, 133 | kSYS_pathconf = 191, 134 | kSYS_fpathconf = 192, 135 | kSYS_getrlimit = 194, 136 | kSYS_setrlimit = 195, 137 | kSYS_getdirentries = 196, 138 | kSYS_freebsd6_mmap = 197, 139 | kSYS___syscall = 198, 140 | kSYS_freebsd6_lseek = 199, 141 | kSYS_freebsd6_truncate = 200, 142 | kSYS_freebsd6_ftruncate = 201, 143 | kSYS___sysctl = 202, 144 | kSYS_mlock = 203, 145 | kSYS_munlock = 204, 146 | kSYS_undelete = 205, 147 | kSYS_futimes = 206, 148 | kSYS_getpgid = 207, 149 | kSYS_poll = 209, 150 | kSYS_freebsd7___semctl = 220, 151 | kSYS_semget = 221, 152 | kSYS_semop = 222, 153 | kSYS_freebsd7_msgctl = 224, 154 | kSYS_msgget = 225, 155 | kSYS_msgsnd = 226, 156 | kSYS_msgrcv = 227, 157 | kSYS_shmat = 228, 158 | kSYS_freebsd7_shmctl = 229, 159 | kSYS_shmdt = 230, 160 | kSYS_shmget = 231, 161 | kSYS_clock_gettime = 232, 162 | kSYS_clock_settime = 233, 163 | kSYS_clock_getres = 234, 164 | kSYS_ktimer_create = 235, 165 | kSYS_ktimer_delete = 236, 166 | kSYS_ktimer_settime = 237, 167 | kSYS_ktimer_gettime = 238, 168 | kSYS_ktimer_getoverrun = 239, 169 | kSYS_nanosleep = 240, 170 | kSYS_ffclock_getcounter = 241, 171 | kSYS_ffclock_setestimate = 242, 172 | kSYS_ffclock_getestimate = 243, 173 | kSYS_clock_getcpuclockid2 = 247, 174 | kSYS_ntp_gettime = 248, 175 | kSYS_minherit = 250, 176 | kSYS_rfork = 251, 177 | kSYS_openbsd_poll = 252, 178 | kSYS_issetugid = 253, 179 | kSYS_lchown = 254, 180 | kSYS_aio_read = 255, 181 | kSYS_aio_write = 256, 182 | kSYS_lio_listio = 257, 183 | kSYS_getdents = 272, 184 | kSYS_lchmod = 274, 185 | kSYS_netbsd_lchown = 275, 186 | kSYS_lutimes = 276, 187 | kSYS_netbsd_msync = 277, 188 | kSYS_nstat = 278, 189 | kSYS_nfstat = 279, 190 | kSYS_nlstat = 280, 191 | kSYS_preadv = 289, 192 | kSYS_pwritev = 290, 193 | kSYS_freebsd4_fhstatfs = 297, 194 | kSYS_fhopen = 298, 195 | kSYS_fhstat = 299, 196 | kSYS_modnext = 300, 197 | kSYS_modstat = 301, 198 | kSYS_modfnext = 302, 199 | kSYS_modfind = 303, 200 | kSYS_kldload = 304, 201 | kSYS_kldunload = 305, 202 | kSYS_kldfind = 306, 203 | kSYS_kldnext = 307, 204 | kSYS_kldstat = 308, 205 | kSYS_kldfirstmod = 309, 206 | kSYS_getsid = 310, 207 | kSYS_setresuid = 311, 208 | kSYS_setresgid = 312, 209 | kSYS_aio_return = 314, 210 | kSYS_aio_suspend = 315, 211 | kSYS_aio_cancel = 316, 212 | kSYS_aio_error = 317, 213 | kSYS_oaio_read = 318, 214 | kSYS_oaio_write = 319, 215 | kSYS_olio_listio = 320, 216 | kSYS_yield = 321, 217 | kSYS_mlockall = 324, 218 | kSYS_munlockall = 325, 219 | kSYS___getcwd = 326, 220 | kSYS_sched_setparam = 327, 221 | kSYS_sched_getparam = 328, 222 | kSYS_sched_setscheduler = 329, 223 | kSYS_sched_getscheduler = 330, 224 | kSYS_sched_yield = 331, 225 | kSYS_sched_get_priority_max = 332, 226 | kSYS_sched_get_priority_min = 333, 227 | kSYS_sched_rr_get_interval = 334, 228 | kSYS_utrace = 335, 229 | kSYS_freebsd4_sendfile = 336, 230 | kSYS_kldsym = 337, 231 | kSYS_jail = 338, 232 | kSYS_nnpfs_syscall = 339, 233 | kSYS_sigprocmask = 340, 234 | kSYS_sigsuspend = 341, 235 | kSYS_freebsd4_sigaction = 342, 236 | kSYS_sigpending = 343, 237 | kSYS_freebsd4_sigreturn = 344, 238 | kSYS_sigtimedwait = 345, 239 | kSYS_sigwaitinfo = 346, 240 | kSYS___acl_get_file = 347, 241 | kSYS___acl_set_file = 348, 242 | kSYS___acl_get_fd = 349, 243 | kSYS___acl_set_fd = 350, 244 | kSYS___acl_delete_file = 351, 245 | kSYS___acl_delete_fd = 352, 246 | kSYS___acl_aclcheck_file = 353, 247 | kSYS___acl_aclcheck_fd = 354, 248 | kSYS_extattrctl = 355, 249 | kSYS_extattr_set_file = 356, 250 | kSYS_extattr_get_file = 357, 251 | kSYS_extattr_delete_file = 358, 252 | kSYS_aio_waitcomplete = 359, 253 | kSYS_getresuid = 360, 254 | kSYS_getresgid = 361, 255 | kSYS_kqueue = 362, 256 | kSYS_kevent = 363, 257 | kSYS_extattr_set_fd = 371, 258 | kSYS_extattr_get_fd = 372, 259 | kSYS_extattr_delete_fd = 373, 260 | kSYS___setugid = 374, 261 | kSYS_eaccess = 376, 262 | kSYS_afs3_syscall = 377, 263 | kSYS_nmount = 378, 264 | kSYS___mac_get_proc = 384, 265 | kSYS___mac_set_proc = 385, 266 | kSYS___mac_get_fd = 386, 267 | kSYS___mac_get_file = 387, 268 | kSYS___mac_set_fd = 388, 269 | kSYS___mac_set_file = 389, 270 | kSYS_kenv = 390, 271 | kSYS_lchflags = 391, 272 | kSYS_uuidgen = 392, 273 | kSYS_sendfile = 393, 274 | kSYS_mac_syscall = 394, 275 | kSYS_getfsstat = 395, 276 | kSYS_statfs = 396, 277 | kSYS_fstatfs = 397, 278 | kSYS_fhstatfs = 398, 279 | kSYS_ksem_close = 400, 280 | kSYS_ksem_post = 401, 281 | kSYS_ksem_wait = 402, 282 | kSYS_ksem_trywait = 403, 283 | kSYS_ksem_init = 404, 284 | kSYS_ksem_open = 405, 285 | kSYS_ksem_unlink = 406, 286 | kSYS_ksem_getvalue = 407, 287 | kSYS_ksem_destroy = 408, 288 | kSYS___mac_get_pid = 409, 289 | kSYS___mac_get_link = 410, 290 | kSYS___mac_set_link = 411, 291 | kSYS_extattr_set_link = 412, 292 | kSYS_extattr_get_link = 413, 293 | kSYS_extattr_delete_link = 414, 294 | kSYS___mac_execve = 415, 295 | kSYS_sigaction = 416, 296 | kSYS_sigreturn = 417, 297 | kSYS_getcontext = 421, 298 | kSYS_setcontext = 422, 299 | kSYS_swapcontext = 423, 300 | kSYS_swapoff = 424, 301 | kSYS___acl_get_link = 425, 302 | kSYS___acl_set_link = 426, 303 | kSYS___acl_delete_link = 427, 304 | kSYS___acl_aclcheck_link = 428, 305 | kSYS_sigwait = 429, 306 | kSYS_thr_create = 430, 307 | kSYS_thr_exit = 431, 308 | kSYS_thr_self = 432, 309 | kSYS_thr_kill = 433, 310 | kSYS__umtx_lock = 434, 311 | kSYS__umtx_unlock = 435, 312 | kSYS_jail_attach = 436, 313 | kSYS_extattr_list_fd = 437, 314 | kSYS_extattr_list_file = 438, 315 | kSYS_extattr_list_link = 439, 316 | kSYS_ksem_timedwait = 441, 317 | kSYS_thr_suspend = 442, 318 | kSYS_thr_wake = 443, 319 | kSYS_kldunloadf = 444, 320 | kSYS_audit = 445, 321 | kSYS_auditon = 446, 322 | kSYS_getauid = 447, 323 | kSYS_setauid = 448, 324 | kSYS_getaudit = 449, 325 | kSYS_setaudit = 450, 326 | kSYS_getaudit_addr = 451, 327 | kSYS_setaudit_addr = 452, 328 | kSYS_auditctl = 453, 329 | kSYS__umtx_op = 454, 330 | kSYS_thr_new = 455, 331 | kSYS_sigqueue = 456, 332 | kSYS_kmq_open = 457, 333 | kSYS_kmq_setattr = 458, 334 | kSYS_kmq_timedreceive = 459, 335 | kSYS_kmq_timedsend = 460, 336 | kSYS_kmq_notify = 461, 337 | kSYS_kmq_unlink = 462, 338 | kSYS_abort2 = 463, 339 | kSYS_thr_set_name = 464, 340 | kSYS_aio_fsync = 465, 341 | kSYS_rtprio_thread = 466, 342 | kSYS_sctp_peeloff = 471, 343 | kSYS_sctp_generic_sendmsg = 472, 344 | kSYS_sctp_generic_sendmsg_iov = 473, 345 | kSYS_sctp_generic_recvmsg = 474, 346 | kSYS_pread = 475, 347 | kSYS_pwrite = 476, 348 | kSYS_mmap = 477, 349 | kSYS_lseek = 478, 350 | kSYS_truncate = 479, 351 | kSYS_ftruncate = 480, 352 | kSYS_thr_kill2 = 481, 353 | kSYS_shm_open = 482, 354 | kSYS_shm_unlink = 483, 355 | kSYS_cpuset = 484, 356 | kSYS_cpuset_setid = 485, 357 | kSYS_cpuset_getid = 486, 358 | kSYS_cpuset_getaffinity = 487, 359 | kSYS_cpuset_setaffinity = 488, 360 | kSYS_faccessat = 489, 361 | kSYS_fchmodat = 490, 362 | kSYS_fchownat = 491, 363 | kSYS_fexecve = 492, 364 | kSYS_fstatat = 493, 365 | kSYS_futimesat = 494, 366 | kSYS_linkat = 495, 367 | kSYS_mkdirat = 496, 368 | kSYS_mkfifoat = 497, 369 | kSYS_mknodat = 498, 370 | kSYS_openat = 499, 371 | kSYS_readlinkat = 500, 372 | kSYS_renameat = 501, 373 | kSYS_symlinkat = 502, 374 | kSYS_unlinkat = 503, 375 | kSYS_posix_openpt = 504, 376 | kSYS_gssd_syscall = 505, 377 | kSYS_jail_get = 506, 378 | kSYS_jail_set = 507, 379 | kSYS_jail_remove = 508, 380 | kSYS_closefrom = 509, 381 | kSYS___semctl = 510, 382 | kSYS_msgctl = 511, 383 | kSYS_shmctl = 512, 384 | kSYS_lpathconf = 513, 385 | kSYS_cap_new = 514, 386 | kSYS_cap_getrights = 515, 387 | kSYS_cap_enter = 516, 388 | kSYS_cap_getmode = 517, 389 | kSYS_pdfork = 518, 390 | kSYS_pdkill = 519, 391 | kSYS_pdgetpid = 520, 392 | kSYS_pselect = 522, 393 | kSYS_getloginclass = 523, 394 | kSYS_setloginclass = 524, 395 | kSYS_rctl_get_racct = 525, 396 | kSYS_rctl_get_rules = 526, 397 | kSYS_rctl_get_limits = 527, 398 | kSYS_rctl_add_rule = 528, 399 | kSYS_rctl_remove_rule = 529, 400 | kSYS_posix_fallocate = 530, 401 | kSYS_posix_fadvise = 531, 402 | 403 | kSYS_netcontrol = 99, 404 | kSYS_netabort = 101, 405 | kSYS_netgetsockinfo = 102, 406 | kSYS_socketex = 113, 407 | kSYS_socketclose = 114, 408 | kSYS_netgetiflist = 125, 409 | kSYS_kqueueex = 141, 410 | kSYS_mtypeprotect = 379, 411 | kSYS_regmgr_call = 532, 412 | kSYS_jitshm_create = 533, 413 | kSYS_jitshm_alias = 534, 414 | kSYS_dl_get_list = 535, 415 | kSYS_dl_get_info = 536, 416 | kSYS_dl_notify_event = 537, 417 | kSYS_evf_create = 538, 418 | kSYS_evf_delete = 539, 419 | kSYS_evf_open = 540, 420 | kSYS_evf_close = 541, 421 | kSYS_evf_wait = 542, 422 | kSYS_evf_trywait = 543, 423 | kSYS_evf_set = 544, 424 | kSYS_evf_clear = 545, 425 | kSYS_evf_cancel = 546, 426 | kSYS_query_memory_protection = 547, 427 | kSYS_batch_map = 548, 428 | kSYS_osem_create = 549, 429 | kSYS_osem_delete = 550, 430 | kSYS_osem_open = 551, 431 | kSYS_osem_close = 552, 432 | kSYS_osem_wait = 553, 433 | kSYS_osem_trywait = 554, 434 | kSYS_osem_post = 555, 435 | kSYS_osem_cancel = 556, 436 | kSYS_namedobj_create = 557, 437 | kSYS_namedobj_delete = 558, 438 | kSYS_set_vm_container = 559, 439 | kSYS_debug_init = 560, 440 | kSYS_suspend_process = 561, 441 | kSYS_resume_process = 562, 442 | kSYS_opmc_enable = 563, 443 | kSYS_opmc_disable = 564, 444 | kSYS_opmc_set_ctl = 565, 445 | kSYS_opmc_set_ctr = 566, 446 | kSYS_opmc_get_ctr = 567, 447 | kSYS_budget_create = 568, 448 | kSYS_budget_delete = 569, 449 | kSYS_budget_get = 570, 450 | kSYS_budget_set = 571, 451 | kSYS_virtual_query = 572, 452 | kSYS_mdbg_call = 573, 453 | kSYS_obs_sblock_create = 574, 454 | kSYS_obs_sblock_delete = 575, 455 | kSYS_obs_sblock_enter = 576, 456 | kSYS_obs_sblock_exit = 577, 457 | kSYS_obs_sblock_xenter = 578, 458 | kSYS_obs_sblock_xexit = 579, 459 | kSYS_obs_eport_create = 580, 460 | kSYS_obs_eport_delete = 581, 461 | kSYS_obs_eport_trigger = 582, 462 | kSYS_obs_eport_open = 583, 463 | kSYS_obs_eport_close = 584, 464 | kSYS_is_in_sandbox = 585, 465 | kSYS_dmem_container = 586, 466 | kSYS_get_authinfo = 587, 467 | kSYS_mname = 588, 468 | kSYS_dynlib_dlopen = 589, 469 | kSYS_dynlib_dlclose = 590, 470 | kSYS_dynlib_dlsym = 591, 471 | kSYS_dynlib_get_list = 592, 472 | kSYS_dynlib_get_info = 593, 473 | kSYS_dynlib_load_prx = 594, 474 | kSYS_dynlib_unload_prx = 595, 475 | kSYS_dynlib_do_copy_relocations = 596, 476 | kSYS_dynlib_prepare_dlclose = 597, 477 | kSYS_dynlib_get_proc_param = 598, 478 | kSYS_dynlib_process_needed_and_relocate = 599, 479 | kSYS_sandbox_path = 600, 480 | kSYS_mdbg_service = 601, 481 | kSYS_randomized_path = 602, 482 | kSYS_rdup = 603, 483 | kSYS_dl_get_metadata = 604, 484 | kSYS_workaround8849 = 605, 485 | kSYS_is_development_mode = 606, 486 | kSYS_get_self_auth_info = 607, 487 | kSYS_dynlib_get_info_ex = 608, 488 | kSYS_budget_getid = 609, 489 | kSYS_budget_get_ptype = 610, 490 | kSYS_get_paging_stats_of_all_threads = 611, 491 | kSYS_get_proc_type_info = 612, 492 | kSYS_get_resident_count = 613, 493 | kSYS_prepare_to_suspend_process = 614, 494 | kSYS_get_resident_fmem_count = 615, 495 | kSYS_thr_get_name = 616, 496 | kSYS_set_gpo = 617, 497 | kSYS_get_paging_stats_of_all_objects = 618, 498 | kSYS_test_debug_rwmem = 619, 499 | kSYS_free_stack = 620, 500 | kSYS_suspend_system = 621, 501 | kSYS_ipmimgr_call = 622, 502 | kSYS_get_gpo = 623, 503 | kSYS_get_vm_map_timestamp = 624, 504 | kSYS_opmc_set_hw = 625, 505 | kSYS_opmc_get_hw = 626, 506 | kSYS_get_cpu_usage_all = 627, 507 | kSYS_mmap_dmem = 628, 508 | kSYS_physhm_open = 629, 509 | kSYS_physhm_unlink = 630, 510 | kSYS_resume_internal_hdd = 631, 511 | kSYS_thr_suspend_ucontext = 632, 512 | kSYS_thr_resume_ucontext = 633, 513 | kSYS_thr_get_ucontext = 634, 514 | kSYS_thr_set_ucontext = 635, 515 | kSYS_set_timezone_info = 636, 516 | kSYS_set_phys_fmem_limit = 637, 517 | kSYS_utc_to_localtime = 638, 518 | kSYS_localtime_to_utc = 639, 519 | kSYS_set_uevt = 640, 520 | kSYS_get_cpu_usage_proc = 641, 521 | kSYS_get_map_statistics = 642, 522 | kSYS_set_chicken_switches = 643, 523 | kSYS_extend_page_table_pool = 644, 524 | kSYS_extend_page_table_pool2 = 645, 525 | kSYS_get_kernel_mem_statistics = 646, 526 | kSYS_get_sdk_compiled_version = 647, 527 | kSYS_app_state_change = 648, 528 | kSYS_dynlib_get_obj_member = 649, 529 | kSYS_budget_get_ptype_of_budget = 650, 530 | kSYS_prepare_to_resume_process = 651, 531 | kSYS_process_terminate = 652, 532 | kSYS_blockpool_open = 653, 533 | kSYS_blockpool_map = 654, 534 | kSYS_blockpool_unmap = 655, 535 | kSYS_dynlib_get_info_for_libdbg = 656, 536 | kSYS_blockpool_batch = 657, 537 | kSYS_fdatasync = 658, 538 | kSYS_dynlib_get_list2 = 659, 539 | kSYS_dynlib_get_info2 = 660, 540 | kSYS_aio_submit = 661, 541 | kSYS_aio_multi_delete = 662, 542 | kSYS_aio_multi_wait = 663, 543 | kSYS_aio_multi_poll = 664, 544 | kSYS_aio_get_data = 665, 545 | kSYS_aio_multi_cancel = 666, 546 | kSYS_get_bio_usage_all = 667, 547 | kSYS_aio_create = 668, 548 | kSYS_aio_submit_cmd = 669, 549 | kSYS_aio_init = 670, 550 | kSYS_get_page_table_stats = 671, 551 | kSYS_dynlib_get_list_for_libdbg = 672, 552 | kSYS_blockpool_move = 673, 553 | kSYS_virtual_query_all = 674, 554 | kSYS_reserve_2mb_page = 675, 555 | kSYS_cpumode_yield = 676, 556 | 557 | kSYS_wait6 = 677, 558 | kSYS_cap_rights_limit = 678, 559 | kSYS_cap_ioctls_limit = 679, 560 | kSYS_cap_ioctls_get = 680, 561 | kSYS_cap_fcntls_limit = 681, 562 | kSYS_cap_fcntls_get = 682, 563 | kSYS_bindat = 683, 564 | kSYS_connectat = 684, 565 | kSYS_chflagsat = 685, 566 | kSYS_accept4 = 686, 567 | kSYS_pipe2 = 687, 568 | kSYS_aio_mlock = 688, 569 | kSYS_procctl = 689, 570 | kSYS_ppoll = 690, 571 | kSYS_futimens = 691, 572 | kSYS_utimensat = 692, 573 | kSYS_numa_getaffinity = 693, 574 | kSYS_numa_setaffinity = 694, 575 | kSYS_apr_submit = 700, 576 | kSYS_apr_resolve = 701, 577 | kSYS_apr_stat = 702, 578 | kSYS_apr_wait = 703, 579 | kSYS_apr_ctrl = 704, 580 | kSYS_get_phys_page_size = 705, 581 | kSYS_begin_app_mount = 706, 582 | kSYS_end_app_mount = 707, 583 | kSYS_fsc2h_ctrl = 708, 584 | kSYS_streamwrite = 709, 585 | kSYS_app_save = 710, 586 | kSYS_app_restore = 711, 587 | kSYS_saved_app_delete = 712, 588 | kSYS_get_ppr_sdk_compiled_version = 713, 589 | kSYS_notify_app_event = 714, 590 | kSYS_ioreq = 715, 591 | kSYS_openintr = 716, 592 | kSYS_dl_get_info_2 = 717, 593 | kSYS_acinfo_add = 718, 594 | kSYS_acinfo_delete = 719, 595 | kSYS_acinfo_get_all_for_coredump = 720, 596 | kSYS_ampr_ctrl_debug = 721, 597 | kSYS_workspace_ctrl = 722, 598 | }; 599 | } // namespace orbis 600 | -------------------------------------------------------------------------------- /include/orbis/sys/sysentry.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "orbis-config.hpp" 4 | #include "orbis/thread/sysent.hpp" 5 | 6 | namespace orbis { 7 | extern sysentvec freebsd9_sysvec; 8 | extern sysentvec freebsd11_sysvec; 9 | extern sysentvec ps4_sysvec; 10 | extern sysentvec ps5_sysvec; 11 | 12 | struct Thread; 13 | void syscall_entry(Thread *thread); 14 | const char *getSysentName(SysResult (*sysent)(Thread *, uint64_t *)); 15 | } // namespace orbis 16 | -------------------------------------------------------------------------------- /include/orbis/thread.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "thread/cpuset.hpp" // IWYU pragma: export 4 | #include "thread/Process.hpp" // IWYU pragma: export 5 | #include "thread/ProcessOps.hpp" // IWYU pragma: export 6 | #include "thread/ProcessState.hpp" // IWYU pragma: export 7 | #include "thread/sysent.hpp" // IWYU pragma: export 8 | #include "thread/Thread.hpp" // IWYU pragma: export 9 | #include "thread/ThreadState.hpp" // IWYU pragma: export 10 | #include "thread/types.hpp" // IWYU pragma: export 11 | -------------------------------------------------------------------------------- /include/orbis/thread/Process.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ProcessState.hpp" 3 | #include "orbis-config.hpp" 4 | #include "orbis/module/Module.hpp" 5 | #include "orbis/utils/IdMap.hpp" 6 | #include "orbis/utils/SharedMutex.hpp" 7 | #include "../thread/types.hpp" 8 | #include "../thread/Thread.hpp" 9 | 10 | #include 11 | 12 | namespace orbis { 13 | class KernelContext; 14 | struct Thread; 15 | struct ProcessOps; 16 | struct sysentvec; 17 | 18 | struct Process { 19 | KernelContext *context = nullptr; 20 | pid_t pid = -1; 21 | sysentvec *sysent = nullptr; 22 | ProcessState state = ProcessState::NEW; 23 | Process *parentProcess = nullptr; 24 | shared_mutex mtx; 25 | void (*onSysEnter)(Thread *thread, int id, uint64_t *args, int argsCount) = nullptr; 26 | void (*onSysExit)(Thread *thread, int id, uint64_t *args, int argsCount, SysResult result) = nullptr; 27 | ptr processParam = nullptr; 28 | uint64_t processParamSize = 0; 29 | const ProcessOps *ops = nullptr; 30 | 31 | std::uint64_t nextTlsSlot = 1; 32 | std::uint64_t lastTlsOffset = 0; 33 | 34 | utils::RcIdMap modulesMap; 35 | utils::OwningIdMap threadsMap; 36 | utils::RcIdMap fileDescriptors; 37 | }; 38 | } // namespace orbis 39 | -------------------------------------------------------------------------------- /include/orbis/thread/ProcessOps.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../error/SysResult.hpp" 3 | #include "../module/ModuleHandle.hpp" 4 | #include "orbis-config.hpp" 5 | #include "../thread/types.hpp" 6 | 7 | namespace orbis { 8 | struct Thread; 9 | struct Module; 10 | 11 | struct ProcessOps { 12 | SysResult (*mmap)(Thread *thread, caddr_t addr, size_t len, sint prot, sint flags, sint fd, off_t pos); 13 | SysResult (*munmap)(Thread *thread, ptr addr, size_t len); 14 | SysResult (*msync)(Thread *thread, ptr addr, size_t len, sint flags); 15 | SysResult (*mprotect)(Thread *thread, ptr addr, size_t len, sint prot); 16 | SysResult (*minherit)(Thread *thread, ptr addr, size_t len, sint inherit); 17 | SysResult (*madvise)(Thread *thread, ptr addr, size_t len, sint behav); 18 | SysResult (*mincore)(Thread *thread, ptr addr, size_t len, ptr vec); 19 | SysResult (*mlock)(Thread *thread, ptr addr, size_t len); 20 | SysResult (*mlockall)(Thread *thread, sint how); 21 | SysResult (*munlockall)(Thread *thread); 22 | SysResult (*munlock)(Thread *thread, ptr addr, size_t len); 23 | SysResult (*virtual_query)(Thread *thread, ptr addr, sint flags, ptr info, ulong infoSize); 24 | 25 | SysResult (*open)(Thread *thread, ptr path, sint flags, sint mode); 26 | SysResult (*close)(Thread *thread, sint fd); 27 | SysResult (*ioctl)(Thread *thread, sint fd, ulong com, caddr_t argp); 28 | SysResult (*write)(Thread *thread, sint fd, ptr data, ulong size); 29 | SysResult (*read)(Thread *thread, sint fd, ptr data, ulong size); 30 | SysResult (*pread)(Thread *thread, sint fd, ptr data, ulong size, ulong offset); 31 | SysResult (*pwrite)(Thread *thread, sint fd, ptr data, ulong size, ulong offset); 32 | SysResult (*lseek)(Thread *thread, sint fd, ulong offset, sint whence); 33 | SysResult (*ftruncate)(Thread *thread, sint fd, off_t length); 34 | SysResult (*truncate)(Thread *thread, ptr path, off_t length); 35 | 36 | SysResult (*dynlib_get_obj_member)(Thread *thread, ModuleHandle handle, uint64_t index, ptr> addrp); 37 | SysResult (*dynlib_dlsym)(Thread *thread, ModuleHandle handle, ptr symbol, ptr> addrp); 38 | SysResult (*dynlib_do_copy_relocations)(Thread *thread); 39 | SysResult (*dynlib_load_prx)(Thread *thread, ptr name, uint64_t arg1, ptr pHandle, uint64_t arg3); 40 | SysResult (*dynlib_unload_prx)(Thread *thread, ModuleHandle handle); 41 | 42 | SysResult (*thr_create)(Thread *thread, ptr ctxt, ptr arg, sint flags); 43 | SysResult (*thr_new)(Thread *thread, ptr param, sint param_size); 44 | SysResult (*thr_exit)(Thread *thread, ptr state); 45 | SysResult (*thr_kill)(Thread *thread, slong id, sint sig); 46 | SysResult (*thr_kill2)(Thread *thread, pid_t pid, slong id, sint sig); 47 | SysResult (*thr_suspend)(Thread *thread, ptr timeout); 48 | SysResult (*thr_wake)(Thread *thread, slong id); 49 | SysResult (*thr_set_name)(Thread *thread, slong id, ptr name); 50 | 51 | SysResult (*exit)(Thread *thread, sint status); 52 | 53 | SysResult (*processNeeded)(Thread *thread); 54 | SysResult (*registerEhFrames)(Thread *thread); 55 | }; 56 | } // namespace orbis 57 | -------------------------------------------------------------------------------- /include/orbis/thread/ProcessState.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace orbis { 6 | enum class ProcessState : std::uint32_t { 7 | NEW, // In creation 8 | NORMAL, // threads can be run 9 | ZOMBIE 10 | }; 11 | } // namespace orbis 12 | -------------------------------------------------------------------------------- /include/orbis/thread/RegisterId.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace orbis { 4 | enum class RegisterId { 5 | r15, 6 | r14, 7 | r13, 8 | r12, 9 | r11, 10 | r10, 11 | r9, 12 | r8, 13 | rdi, 14 | rsi, 15 | rbp, 16 | rbx, 17 | rdx, 18 | rcx, 19 | rax, 20 | rsp, 21 | rflags, 22 | }; 23 | } // namespace orbis 24 | -------------------------------------------------------------------------------- /include/orbis/thread/Thread.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "orbis-config.hpp" 4 | #include "types.hpp" 5 | #include "ThreadState.hpp" 6 | 7 | #include 8 | 9 | namespace orbis { 10 | struct Process; 11 | struct Thread { 12 | std::mutex lock; 13 | Process *tproc = nullptr; 14 | uint64_t retval[2]{}; 15 | void *context{}; 16 | ptr stackStart; 17 | ptr stackEnd; 18 | uint64_t fsBase{}; 19 | uint64_t gsBase{}; 20 | char name[32]; 21 | 22 | uint64_t sigMask[4] = { 23 | 0x7fff'ffff, 24 | 0 25 | }; 26 | 27 | lwpid_t tid = -1; 28 | ThreadState state = ThreadState::INACTIVE; 29 | }; 30 | } // namespace orbis 31 | -------------------------------------------------------------------------------- /include/orbis/thread/ThreadState.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace orbis { 6 | enum class ThreadState : std::uint32_t { INACTIVE, INHIBITED, CAN_RUN, RUNQ, RUNNING }; 7 | } // namespace orbis 8 | -------------------------------------------------------------------------------- /include/orbis/thread/cpuset.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "orbis-config.hpp" 4 | 5 | namespace orbis { 6 | static constexpr auto NCPUBITS = sizeof(slong) * 8; 7 | static constexpr auto NCPUWORDS = 128 / NCPUBITS; 8 | 9 | struct cpuset { 10 | slong bits[NCPUWORDS]; 11 | }; 12 | } // namespace orbis 13 | -------------------------------------------------------------------------------- /include/orbis/thread/sysent.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "orbis-config.hpp" 4 | 5 | namespace orbis { 6 | struct Thread; 7 | using sy_call_t = SysResult(Thread *, uint64_t *); 8 | 9 | struct sysent { 10 | sint narg; 11 | sy_call_t *call; 12 | }; 13 | 14 | struct sysentvec { 15 | sint size; 16 | const sysent *table; 17 | }; 18 | } // namespace orbis 19 | -------------------------------------------------------------------------------- /include/orbis/thread/types.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "orbis-config.hpp" 3 | 4 | namespace orbis { 5 | using lwpid_t = int32_t; 6 | using pid_t = int64_t; 7 | using uid_t = uint32_t; 8 | using gid_t = uint32_t; 9 | } // namespace orbis 10 | -------------------------------------------------------------------------------- /include/orbis/utils/AtomicOp.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace orbis { 8 | inline namespace utils { 9 | // Atomic operation; returns old value, or pair of old value and return value 10 | // (cancel op if evaluates to false) 11 | template > 12 | inline std::conditional_t, T, std::pair> 13 | atomic_fetch_op(std::atomic &v, F func) { 14 | T _new, old = v.load(); 15 | while (true) { 16 | _new = old; 17 | if constexpr (std::is_void_v) { 18 | std::invoke(func, _new); 19 | if (v.compare_exchange_strong(old, _new)) [[likely]] { 20 | return old; 21 | } 22 | } else { 23 | RT ret = std::invoke(func, _new); 24 | if (!ret || v.compare_exchange_strong(old, _new)) [[likely]] { 25 | return {old, std::move(ret)}; 26 | } 27 | } 28 | } 29 | } 30 | 31 | // Atomic operation; returns function result value, function is the lambda 32 | template > 33 | inline RT atomic_op(std::atomic &v, F func) { 34 | T _new, old = v.load(); 35 | while (true) { 36 | _new = old; 37 | if constexpr (std::is_void_v) { 38 | std::invoke(func, _new); 39 | if (v.compare_exchange_strong(old, _new)) [[likely]] { 40 | return; 41 | } 42 | } else { 43 | RT result = std::invoke(func, _new); 44 | if (v.compare_exchange_strong(old, _new)) [[likely]] { 45 | return result; 46 | } 47 | } 48 | } 49 | } 50 | 51 | #if defined(__ATOMIC_HLE_ACQUIRE) && defined(__ATOMIC_HLE_RELEASE) 52 | static constexpr int s_hle_ack = __ATOMIC_SEQ_CST | __ATOMIC_HLE_ACQUIRE; 53 | static constexpr int s_hle_rel = __ATOMIC_SEQ_CST | __ATOMIC_HLE_RELEASE; 54 | #else 55 | static constexpr int s_hle_ack = __ATOMIC_SEQ_CST; 56 | static constexpr int s_hle_rel = __ATOMIC_SEQ_CST; 57 | #endif 58 | 59 | template 60 | inline bool compare_exchange_hle_acq(std::atomic &dest, T &comp, T exch) { 61 | static_assert(sizeof(T) == 4 || sizeof(T) == 8); 62 | static_assert(std::atomic::is_always_lock_free); 63 | return __atomic_compare_exchange(reinterpret_cast(&dest), &comp, &exch, 64 | false, s_hle_ack, s_hle_ack); 65 | } 66 | 67 | template 68 | inline T fetch_add_hle_rel(std::atomic &dest, T value) { 69 | static_assert(sizeof(T) == 4 || sizeof(T) == 8); 70 | static_assert(std::atomic::is_always_lock_free); 71 | return __atomic_fetch_add(reinterpret_cast(&dest), value, s_hle_rel); 72 | } 73 | } // namespace utils 74 | } // namespace orbis 75 | -------------------------------------------------------------------------------- /include/orbis/utils/BitSet.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | namespace orbis { 7 | inline namespace utils { 8 | template struct BitSet { 9 | using chunk_type = std::uint64_t; 10 | static constexpr auto BitsPerChunk = sizeof(chunk_type) * 8; 11 | static constexpr auto ChunkCount = (Count + BitsPerChunk - 1) / BitsPerChunk; 12 | chunk_type _bits[ChunkCount]{}; 13 | 14 | constexpr std::size_t countr_one() const { 15 | std::size_t result = 0; 16 | for (auto bits : _bits) { 17 | auto count = std::countr_one(bits); 18 | result += count; 19 | 20 | if (count != BitsPerChunk) { 21 | break; 22 | } 23 | } 24 | 25 | return result; 26 | } 27 | 28 | constexpr std::size_t countr_zero(std::size_t offset = 0) const { 29 | std::size_t result = 0; 30 | 31 | if (auto chunkOffset = offset % BitsPerChunk) { 32 | auto count = 33 | std::countr_zero(_bits[offset / BitsPerChunk] >> chunkOffset); 34 | 35 | if (count != BitsPerChunk) { 36 | return count + offset; 37 | } 38 | 39 | offset = (offset + BitsPerChunk - 1) & ~(BitsPerChunk - 1); 40 | } 41 | 42 | for (auto i = offset / BitsPerChunk; i < ChunkCount; ++i) { 43 | auto count = std::countr_zero(_bits[i]); 44 | result += count; 45 | 46 | if (count != BitsPerChunk) { 47 | break; 48 | } 49 | } 50 | /* 51 | for (auto bits : _bits) { 52 | auto count = std::countr_zero(bits); 53 | result += count; 54 | 55 | if (count != BitsPerChunk) { 56 | break; 57 | } 58 | } 59 | */ 60 | 61 | return result + offset; 62 | } 63 | 64 | bool empty() const { 65 | for (auto bits : _bits) { 66 | if (bits != 0) { 67 | return false; 68 | } 69 | } 70 | 71 | return true; 72 | } 73 | 74 | bool full() const { 75 | if constexpr (Count < BitsPerChunk) { 76 | return _bits[0] == (static_cast(1) << Count) - 1; 77 | } 78 | 79 | for (auto bits : _bits) { 80 | if (bits != ~static_cast(0)) { 81 | return false; 82 | } 83 | } 84 | 85 | return true; 86 | } 87 | 88 | constexpr void clear(std::size_t index) { 89 | _bits[index / BitsPerChunk] &= 90 | ~(static_cast(1) << (index % BitsPerChunk)); 91 | } 92 | 93 | constexpr void set(std::size_t index) { 94 | _bits[index / BitsPerChunk] |= static_cast(1) 95 | << (index % BitsPerChunk); 96 | } 97 | 98 | constexpr bool test(std::size_t index) const { 99 | return (_bits[index / BitsPerChunk] & 100 | (static_cast(1) << (index % BitsPerChunk))) != 0; 101 | } 102 | }; 103 | } // namespace utils 104 | } // namespace orbis 105 | -------------------------------------------------------------------------------- /include/orbis/utils/IdMap.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "BitSet.hpp" 4 | #include "Rc.hpp" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace orbis { 13 | inline namespace utils { 14 | template 16 | requires(MaxId > MinId) 17 | class RcIdMap { 18 | static constexpr auto ChunkSize = std::min(MaxId - MinId, 64); 19 | static constexpr auto ChunkCount = 20 | (MaxId - MinId + ChunkSize - 1) / ChunkSize; 21 | 22 | struct IdMapChunk { 23 | BitSet mask = {}; 24 | T *objects[ChunkSize]{}; 25 | 26 | ~IdMapChunk() { 27 | std::size_t index = mask.countr_zero(); 28 | 29 | while (index < ChunkSize) { 30 | objects[index]->decRef(); 31 | index = mask.countr_zero(index + 1); 32 | } 33 | } 34 | 35 | std::size_t insert(T *object) { 36 | std::size_t index = mask.countr_one(); 37 | mask.set(index); 38 | objects[index] = object; 39 | 40 | return index; 41 | } 42 | 43 | T *get(std::size_t index) { return objects[index]; } 44 | 45 | void remove(std::size_t index) { 46 | objects[index]->decRef(); 47 | objects[index] = nullptr; 48 | mask.clear(index); 49 | } 50 | }; 51 | 52 | IdMapChunk m_chunks[ChunkCount]{}; 53 | BitSet m_fullChunks; 54 | 55 | public: 56 | static constexpr auto npos = static_cast(~static_cast(0)); 57 | 58 | struct end_iterator {}; 59 | 60 | class iterator { 61 | const IdMapChunk *chunks = nullptr; 62 | std::size_t chunk = 0; 63 | std::size_t index = 0; 64 | 65 | public: 66 | iterator(const IdMapChunk *chunks) : chunks(chunks) { findNext(); } 67 | 68 | iterator &operator++() { 69 | ++index; 70 | findNext(); 71 | return *this; 72 | } 73 | 74 | std::pair operator*() const { 75 | return {static_cast(chunk * ChunkSize + index + MinId), 76 | chunks[chunk].objects[index]}; 77 | } 78 | 79 | bool operator!=(const end_iterator &) const { return chunk < ChunkCount; } 80 | bool operator==(const end_iterator &) const { return chunk >= ChunkCount; } 81 | 82 | private: 83 | void findNext() { 84 | while (chunk < ChunkCount) { 85 | index = chunks[chunk].mask.countr_zero(index); 86 | 87 | if (index < ChunkSize) { 88 | break; 89 | } 90 | 91 | index = 0; 92 | chunk++; 93 | } 94 | } 95 | }; 96 | 97 | void walk(auto cb) { 98 | for (std::size_t chunk = 0; chunk < ChunkCount; ++chunk) { 99 | std::size_t index = m_chunks[chunk].mask.countr_zero(); 100 | 101 | while (index < ChunkSize) { 102 | cb(static_cast(index + chunk * ChunkSize + MinId), 103 | m_chunks[chunk].objects[index]); 104 | 105 | index = m_chunks[chunk].mask.countr_zero(index + 1); 106 | } 107 | } 108 | } 109 | 110 | iterator begin() const { return iterator{m_chunks}; } 111 | 112 | end_iterator end() const { return {}; } 113 | 114 | private: 115 | IdT insert_impl(T *object) { 116 | auto page = m_fullChunks.countr_one(); 117 | 118 | if (page == ChunkCount) { 119 | return npos; 120 | } 121 | 122 | auto index = m_chunks[page].insert(object); 123 | 124 | if (m_chunks[page].mask.full()) { 125 | m_fullChunks.set(page); 126 | } 127 | 128 | return {static_cast(page * ChunkSize + index + MinId)}; 129 | } 130 | 131 | public: 132 | IdT insert(T *object) { 133 | auto result = insert_impl(object); 134 | 135 | if (result != npos) { 136 | object->incRef(); 137 | } 138 | 139 | return result; 140 | } 141 | 142 | IdT insert(const Ref &ref) { return insert(ref.get()); } 143 | 144 | IdT insert(Ref &&ref) { 145 | auto object = ref.release(); 146 | auto result = insert_impl(object); 147 | 148 | if (result == npos) { 149 | object->decRef(); 150 | } 151 | 152 | return result; 153 | } 154 | 155 | T *get(IdT id) { 156 | const auto rawId = static_cast(id) - MinId; 157 | 158 | if (rawId >= MaxId - MinId) { 159 | return nullptr; 160 | } 161 | 162 | const auto chunk = rawId / ChunkSize; 163 | const auto index = rawId % ChunkSize; 164 | 165 | if (!m_chunks[chunk].mask.test(index)) { 166 | return nullptr; 167 | } 168 | 169 | return m_chunks[chunk].get(index); 170 | } 171 | 172 | bool remove(IdT id) { 173 | const auto rawId = static_cast(id) - MinId; 174 | 175 | if (rawId >= MaxId - MinId) { 176 | return false; 177 | } 178 | 179 | const auto chunk = rawId / ChunkSize; 180 | const auto index = rawId % ChunkSize; 181 | 182 | if (!m_chunks[chunk].mask.test(index)) { 183 | return false; 184 | } 185 | 186 | m_chunks[chunk].remove(index); 187 | m_fullChunks.clear(chunk); 188 | return true; 189 | } 190 | }; 191 | 192 | template 194 | requires(MaxId > MinId) 195 | struct OwningIdMap { 196 | static constexpr auto ChunkSize = std::min(MaxId - MinId, 64); 197 | static constexpr auto ChunkCount = 198 | (MaxId - MinId + ChunkSize - 1) / ChunkSize; 199 | 200 | struct IdMapChunk { 201 | BitSet mask = {}; 202 | alignas(T) std::byte objects[sizeof(T) * ChunkSize]; 203 | 204 | ~IdMapChunk() { 205 | std::size_t pageOffset = 0; 206 | 207 | for (auto page : mask._bits) { 208 | auto tmp = page; 209 | 210 | while (true) { 211 | const auto index = std::countr_zero(tmp); 212 | 213 | if (index >= 64) { 214 | break; 215 | } 216 | 217 | tmp &= ~(static_cast(1) << index); 218 | destroy(pageOffset + index); 219 | } 220 | 221 | pageOffset += 64; 222 | } 223 | } 224 | 225 | template 226 | std::pair emplace_new(ArgsT &&...args) { 227 | std::size_t index = mask.countr_one(); 228 | 229 | if (index >= ChunkSize) { 230 | return {}; 231 | } 232 | 233 | mask.set(index); 234 | 235 | return {index, 236 | std::construct_at(get(index), std::forward(args)...)}; 237 | } 238 | 239 | T *get(std::size_t index) { 240 | return reinterpret_cast(objects + sizeof(T) * index); 241 | } 242 | 243 | void destroy(std::size_t index) { 244 | std::destroy_at(get(index)); 245 | mask.clear(index); 246 | } 247 | }; 248 | 249 | IdMapChunk chunks[ChunkCount]{}; 250 | BitSet fullChunks; 251 | 252 | template 253 | requires(std::is_constructible_v) 254 | std::pair emplace(ArgsT &&...args) { 255 | auto page = fullChunks.countr_one(); 256 | 257 | if (page == ChunkCount) { 258 | return {}; 259 | } 260 | 261 | auto newElem = chunks[page].emplace_new(std::forward(args)...); 262 | 263 | if (chunks[page].mask.full()) { 264 | fullChunks.set(page); 265 | } 266 | 267 | return {static_cast(page * ChunkSize + newElem.first + MinId), 268 | newElem.second}; 269 | } 270 | 271 | T *get(IdT id) { 272 | const auto rawId = static_cast(id) - MinId; 273 | const auto chunk = rawId / ChunkSize; 274 | const auto index = rawId % ChunkSize; 275 | 276 | if (chunk >= ChunkCount) { 277 | return nullptr; 278 | } 279 | 280 | if (!chunks[chunk].mask.test(index)) { 281 | return nullptr; 282 | } 283 | 284 | return chunks[chunk].get(index); 285 | } 286 | 287 | bool destroy(IdT id) { 288 | const auto rawId = static_cast(id) - MinId; 289 | const auto chunk = rawId / ChunkSize; 290 | const auto index = rawId % ChunkSize; 291 | 292 | if (chunk >= ChunkCount) { 293 | return false; 294 | } 295 | 296 | if (!chunks[chunk].mask.test(index)) { 297 | return false; 298 | } 299 | 300 | chunks[chunk].destroy(index); 301 | fullChunks.clear(chunk); 302 | return true; 303 | } 304 | }; 305 | } // namespace utils 306 | } // namespace orbis 307 | -------------------------------------------------------------------------------- /include/orbis/utils/LinkedNode.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace orbis { 4 | inline namespace utils { 5 | template struct LinkedNode { 6 | T object; 7 | LinkedNode *next = nullptr; 8 | LinkedNode *prev = nullptr; 9 | 10 | void insertNext(LinkedNode &other) { 11 | other.next = next; 12 | other.prev = this; 13 | 14 | if (next != nullptr) { 15 | next->prev = &other; 16 | } 17 | 18 | next = &other; 19 | } 20 | 21 | void insertPrev(LinkedNode &other) { 22 | other.next = this; 23 | other.prev = prev; 24 | 25 | if (prev != nullptr) { 26 | prev->next = &other; 27 | } 28 | 29 | prev = &other; 30 | } 31 | 32 | LinkedNode *erase() { 33 | if (prev != nullptr) { 34 | prev->next = next; 35 | } 36 | 37 | if (next != nullptr) { 38 | next->prev = prev; 39 | } 40 | 41 | prev = nullptr; 42 | auto result = next; 43 | next = nullptr; 44 | return result; 45 | } 46 | }; 47 | } // namespace utils 48 | } // namespace orbis 49 | -------------------------------------------------------------------------------- /include/orbis/utils/Logs.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | namespace orbis { 7 | inline namespace logs { 8 | enum class LogLevel : unsigned char { 9 | Always, 10 | Fatal, 11 | Error, 12 | Todo, 13 | Success, 14 | Warning, 15 | Notice, 16 | Trace 17 | }; 18 | 19 | // Currently enabled log level 20 | inline std::atomic logs_level = LogLevel::Notice; 21 | 22 | template struct log_class_string { 23 | static const T &get_object(const void *arg) { 24 | return *static_cast(arg); 25 | } 26 | static void format(std::string &out, const void *arg); 27 | }; 28 | 29 | template <> struct log_class_string { 30 | static void format(std::string &out, const void *arg); 31 | }; 32 | 33 | template 34 | struct log_class_string : log_class_string {}; 35 | 36 | template <> struct log_class_string { 37 | static void format(std::string &out, const void *arg); 38 | }; 39 | 40 | template <> 41 | struct log_class_string : log_class_string {}; 42 | 43 | template <> 44 | struct log_class_string 45 | : log_class_string {}; 46 | 47 | template <> 48 | struct log_class_string : log_class_string {}; 49 | 50 | template 51 | using log_args_t = const void *(&&)[sizeof...(Args) + 1]; 52 | 53 | struct log_type_info { 54 | decltype(&log_class_string::format) log_string; 55 | 56 | template static constexpr log_type_info make() { 57 | return log_type_info{ 58 | &log_class_string::format, 59 | }; 60 | } 61 | }; 62 | 63 | template 64 | constexpr const log_type_info type_info_v[sizeof...(Args) + 1]{ 65 | log_type_info::make>()...}; 66 | 67 | void _orbis_log_print(LogLevel lvl, const char *msg, std::string_view names, 68 | const log_type_info *sup, ...); 69 | 70 | template 71 | void _orbis_log_impl(LogLevel lvl, const char *msg, const char *names, 72 | const Args &...args) { 73 | // Fast filtering 74 | if (logs_level.load(std::memory_order::relaxed) < lvl) 75 | return; 76 | 77 | _orbis_log_print(lvl, msg, names, type_info_v, 78 | static_cast(&args)...); 79 | } 80 | 81 | } // namespace logs 82 | } // namespace orbis 83 | 84 | #define ORBIS_LOG_FATAL(msg, ...) \ 85 | ::orbis::_orbis_log_impl(::orbis::LogLevel::Fatal, (msg), #__VA_ARGS__, \ 86 | ##__VA_ARGS__) 87 | #define ORBIS_LOG_ERROR(msg, ...) \ 88 | ::orbis::_orbis_log_impl(::orbis::LogLevel::Error, (msg), #__VA_ARGS__, \ 89 | ##__VA_ARGS__) 90 | #define ORBIS_LOG_TODO(msg, ...) \ 91 | ::orbis::_orbis_log_impl(::orbis::LogLevel::Todo, (msg), #__VA_ARGS__, \ 92 | ##__VA_ARGS__) 93 | #define ORBIS_LOG_SUCCESS(msg, ...) \ 94 | ::orbis::_orbis_log_impl(::orbis::LogLevel::Success, (msg), #__VA_ARGS__, \ 95 | ##__VA_ARGS__) 96 | #define ORBIS_LOG_WARNING(msg, ...) \ 97 | ::orbis::_orbis_log_impl(::orbis::LogLevel::Warning, (msg), #__VA_ARGS__, \ 98 | ##__VA_ARGS__) 99 | #define ORBIS_LOG_NOTICE(msg, ...) \ 100 | ::orbis::_orbis_log_impl(::orbis::LogLevel::Notice, (msg), #__VA_ARGS__, \ 101 | ##__VA_ARGS__) 102 | #define ORBIS_LOG_TRACE(msg, ...) \ 103 | ::orbis::_orbis_log_impl(::orbis::LogLevel::Trace, (msg), #__VA_ARGS__, \ 104 | ##__VA_ARGS__) 105 | -------------------------------------------------------------------------------- /include/orbis/utils/Rc.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace orbis { 9 | inline namespace utils { 10 | struct RcBase { 11 | std::atomic references{0}; 12 | 13 | virtual ~RcBase() = default; 14 | 15 | void incRef() { 16 | if (references.fetch_add(1, std::memory_order::relaxed) > 512) { 17 | assert(!"too many references"); 18 | } 19 | } 20 | 21 | // returns true if object was destroyed 22 | bool decRef() { 23 | if (references.fetch_sub(1, std::memory_order::relaxed) == 1) { 24 | delete this; 25 | return true; 26 | } 27 | 28 | return false; 29 | } 30 | }; 31 | 32 | template 33 | concept WithRc = requires(T t) { 34 | t.incRef(); 35 | t.decRef(); 36 | }; 37 | 38 | template class Ref { 39 | T *m_ref = nullptr; 40 | 41 | public: 42 | Ref() = default; 43 | 44 | template 45 | requires(std::is_base_of_v) 46 | Ref(OT *ref) : m_ref(ref) { 47 | ref->incRef(); 48 | } 49 | 50 | template 51 | requires(std::is_base_of_v) 52 | Ref(const Ref &other) : m_ref(other.get()) { 53 | if (m_ref != nullptr) { 54 | m_ref->incRef(); 55 | } 56 | } 57 | 58 | template 59 | requires(std::is_base_of_v) 60 | Ref(Ref &&other) : m_ref(other.release()) {} 61 | 62 | Ref(const Ref &other) : m_ref(other.get()) { 63 | if (m_ref != nullptr) { 64 | m_ref->incRef(); 65 | } 66 | } 67 | Ref(Ref &&other) : m_ref(other.release()) {} 68 | 69 | template 70 | requires(std::is_base_of_v) 71 | Ref &operator=(Ref &&other) { 72 | other.swap(*this); 73 | return *this; 74 | } 75 | 76 | template 77 | requires(std::is_base_of_v) 78 | Ref &operator=(OT *other) { 79 | *this = Ref(other); 80 | return *this; 81 | } 82 | 83 | template 84 | requires(std::is_base_of_v) 85 | Ref &operator=(const Ref &other) { 86 | *this = Ref(other); 87 | return *this; 88 | } 89 | 90 | Ref &operator=(const Ref &other) { 91 | *this = Ref(other); 92 | return *this; 93 | } 94 | 95 | Ref &operator=(Ref &&other) { 96 | other.swap(*this); 97 | return *this; 98 | } 99 | 100 | ~Ref() { 101 | if (m_ref != nullptr) { 102 | m_ref->decRef(); 103 | } 104 | } 105 | 106 | void swap(Ref &other) { std::swap(m_ref, other.m_ref); } 107 | T *get() const { return m_ref; } 108 | T *release() { return std::exchange(m_ref, nullptr); } 109 | T *operator->() const { return m_ref; } 110 | explicit operator bool() const { return m_ref != nullptr; } 111 | bool operator==(std::nullptr_t) const { return m_ref == nullptr; } 112 | bool operator!=(std::nullptr_t) const { return m_ref != nullptr; } 113 | auto operator<=>(const T *other) const { return m_ref <=> other; } 114 | auto operator<=>(const Ref &other) const = default; 115 | }; 116 | 117 | template 118 | requires(std::is_constructible_v) 119 | Ref create(ArgsT &&...args) { 120 | auto result = new T(std::forward(args)...); 121 | return Ref(result); 122 | } 123 | } // namespace utils 124 | } // namespace orbis 125 | -------------------------------------------------------------------------------- /include/orbis/utils/SharedMutex.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace orbis { 8 | inline namespace utils { 9 | // IPC-ready shared mutex, using only writer lock is recommended 10 | struct shared_mutex final { 11 | enum : unsigned { 12 | c_one = 1u << 14, // Fixed-point 1.0 value (one writer) 13 | c_sig = 1u << 30, 14 | c_err = 1u << 31, 15 | }; 16 | 17 | std::atomic m_value{}; 18 | 19 | void impl_lock_shared(unsigned val); 20 | void impl_unlock_shared(unsigned old); 21 | void impl_wait(); 22 | void impl_signal(); 23 | void impl_lock(unsigned val); 24 | void impl_unlock(unsigned old); 25 | void impl_lock_upgrade(); 26 | 27 | public: 28 | constexpr shared_mutex() = default; 29 | 30 | bool try_lock_shared() { 31 | // Conditional increment 32 | unsigned value = m_value.load(); 33 | return value < c_one - 1 && 34 | m_value.compare_exchange_strong(value, value + 1); 35 | } 36 | 37 | // Lock with HLE acquire hint 38 | void lock_shared() { 39 | unsigned value = m_value.load(); 40 | if (value < c_one - 1) [[likely]] { 41 | unsigned old = value; 42 | if (compare_exchange_hle_acq(m_value, old, value + 1)) [[likely]] { 43 | return; 44 | } 45 | } 46 | 47 | impl_lock_shared(value + 1); 48 | } 49 | 50 | // Unlock with HLE release hint 51 | void unlock_shared() { 52 | const unsigned value = fetch_add_hle_rel(m_value, -1u); 53 | if (value >= c_one) [[unlikely]] { 54 | impl_unlock_shared(value); 55 | } 56 | } 57 | 58 | bool try_lock() { 59 | unsigned value = 0; 60 | return m_value.compare_exchange_strong(value, c_one); 61 | } 62 | 63 | // Lock with HLE acquire hint 64 | void lock() { 65 | unsigned value = 0; 66 | if (!compare_exchange_hle_acq(m_value, value, +c_one)) [[unlikely]] { 67 | impl_lock(value); 68 | } 69 | } 70 | 71 | // Unlock with HLE release hint 72 | void unlock() { 73 | const unsigned value = fetch_add_hle_rel(m_value, 0u - c_one); 74 | if (value != c_one) [[unlikely]] { 75 | impl_unlock(value); 76 | } 77 | } 78 | 79 | bool try_lock_upgrade() { 80 | unsigned value = m_value.load(); 81 | 82 | // Conditional increment, try to convert a single reader into a writer, 83 | // ignoring other writers 84 | return (value + c_one - 1) % c_one == 0 && 85 | m_value.compare_exchange_strong(value, value + c_one - 1); 86 | } 87 | 88 | void lock_upgrade() { 89 | if (!try_lock_upgrade()) [[unlikely]] { 90 | impl_lock_upgrade(); 91 | } 92 | } 93 | 94 | void lock_downgrade() { 95 | // Convert to reader lock (can result in broken state) 96 | m_value -= c_one - 1; 97 | } 98 | 99 | // Check whether can immediately obtain an exclusive (writer) lock 100 | bool is_free() const { return m_value.load() == 0; } 101 | 102 | // Check whether can immediately obtain a shared (reader) lock 103 | bool is_lockable() const { return m_value.load() < c_one - 1; } 104 | }; 105 | 106 | // Simplified shared (reader) lock implementation. 107 | class reader_lock final { 108 | shared_mutex &m_mutex; 109 | bool m_upgraded = false; 110 | 111 | public: 112 | reader_lock(const reader_lock &) = delete; 113 | reader_lock &operator=(const reader_lock &) = delete; 114 | explicit reader_lock(shared_mutex &mutex) : m_mutex(mutex) { 115 | m_mutex.lock_shared(); 116 | } 117 | 118 | // One-way lock upgrade; note that the observed state could have been changed 119 | void upgrade() { 120 | if (!m_upgraded) { 121 | m_mutex.lock_upgrade(); 122 | m_upgraded = true; 123 | } 124 | } 125 | 126 | // Try to upgrade; if it succeeds, the observed state has NOT been changed 127 | bool try_upgrade() { 128 | return m_upgraded || (m_upgraded = m_mutex.try_lock_upgrade()); 129 | } 130 | 131 | ~reader_lock() { m_upgraded ? m_mutex.unlock() : m_mutex.unlock_shared(); } 132 | }; 133 | 134 | class writer_lock final { 135 | shared_mutex &m_mutex; 136 | 137 | public: 138 | writer_lock(const writer_lock &) = delete; 139 | writer_lock &operator=(const writer_lock &) = delete; 140 | explicit writer_lock(shared_mutex &mutex) : m_mutex(mutex) { m_mutex.lock(); } 141 | ~writer_lock() { m_mutex.unlock(); } 142 | }; 143 | } // namespace utils 144 | } // namespace orbis 145 | -------------------------------------------------------------------------------- /src/module.cpp: -------------------------------------------------------------------------------- 1 | #include "module/Module.hpp" 2 | #include "thread.hpp" 3 | #include 4 | 5 | #include "module/Module.hpp" 6 | #include "thread/Process.hpp" 7 | #include 8 | 9 | // TODO: move relocations to the platform specific code 10 | enum RelType { 11 | kRelNone, 12 | kRel64, 13 | kRelPc32, 14 | kRelGot32, 15 | kRelPlt32, 16 | kRelCopy, 17 | kRelGlobDat, 18 | kRelJumpSlot, 19 | kRelRelative, 20 | kRelGotPcRel, 21 | kRel32, 22 | kRel32s, 23 | kRel16, 24 | kRelPc16, 25 | kRel8, 26 | kRelPc8, 27 | kRelDtpMod64, 28 | kRelDtpOff64, 29 | kRelTpOff64, 30 | kRelTlsGd, 31 | kRelTlsLd, 32 | kRelDtpOff32, 33 | kRelGotTpOff, 34 | kRelTpOff32, 35 | kRelPc64, 36 | kRelGotOff64, 37 | kRelGotPc32, 38 | kRelGot64, 39 | kRelGotPcRel64, 40 | kRelGotPc64, 41 | kRelGotPlt64, 42 | kRelPltOff64, 43 | kRelSize32, 44 | kRelSize64, 45 | kRelGotPc32TlsDesc, 46 | kRelTlsDescCall, 47 | kRelTlsDesc, 48 | kRelIRelative, 49 | kRelRelative64, 50 | }; 51 | 52 | static std::uint64_t calculateTlsOffset(std::uint64_t prevOffset, 53 | std::uint64_t size, 54 | std::uint64_t align) { 55 | return (prevOffset + size + align - 1) & ~(align - 1); 56 | } 57 | 58 | static void allocateTlsOffset(orbis::Process *process, orbis::Module *module) { 59 | if (module->isTlsDone) { 60 | return; 61 | } 62 | 63 | auto offset = 64 | calculateTlsOffset(module->tlsIndex == 1 ? 0 : process->lastTlsOffset, 65 | module->tlsSize, module->tlsAlign); 66 | 67 | module->tlsOffset = offset; 68 | process->lastTlsOffset = offset; 69 | module->isTlsDone = true; 70 | } 71 | 72 | static orbis::SysResult doRelocation(orbis::Process *process, 73 | orbis::Module *module, 74 | orbis::Relocation rel) { 75 | auto symbol = module->symbols.at(rel.symbolIndex); 76 | 77 | auto A = rel.addend; 78 | auto B = reinterpret_cast(module->base); 79 | auto where = reinterpret_cast(B + rel.offset); 80 | auto where32 = reinterpret_cast(B + rel.offset); 81 | auto P = reinterpret_cast(where); 82 | 83 | auto findDefModule = [module, symbol] { 84 | if (symbol.moduleIndex == -1 || symbol.bind == orbis::SymbolBind::Local) { 85 | return std::pair(module, symbol.address); 86 | } 87 | 88 | auto &defModule = module->importedModules.at(symbol.moduleIndex); 89 | if (!defModule) { 90 | return std::pair(module, symbol.address); 91 | } 92 | 93 | auto library = module->neededLibraries.at(symbol.libraryIndex); 94 | 95 | std::vector foundInLibs; 96 | for (auto defSym : defModule->symbols) { 97 | if (defSym.id != symbol.id || defSym.bind == orbis::SymbolBind::Local) { 98 | continue; 99 | } 100 | 101 | if (defSym.visibility == orbis::SymbolVisibility::Hidden) { 102 | std::printf("Ignoring hidden symbol\n"); 103 | continue; 104 | } 105 | 106 | auto defLib = defModule->neededLibraries.at(defSym.libraryIndex); 107 | 108 | if (defLib.name == library.name) { 109 | return std::pair(defModule.get(), defSym.address); 110 | } 111 | 112 | foundInLibs.push_back(defLib.name); 113 | } 114 | 115 | for (auto nsDefModule : defModule->namespaceModules) { 116 | for (auto defSym : nsDefModule->symbols) { 117 | if (defSym.id != symbol.id || defSym.bind == orbis::SymbolBind::Local) { 118 | continue; 119 | } 120 | 121 | if (defSym.visibility == orbis::SymbolVisibility::Hidden) { 122 | std::printf("Ignoring hidden symbol\n"); 123 | continue; 124 | } 125 | 126 | auto defLib = nsDefModule->neededLibraries.at(defSym.libraryIndex); 127 | 128 | if (defLib.name == library.name) { 129 | return std::pair(nsDefModule.get(), defSym.address); 130 | } 131 | } 132 | } 133 | 134 | std::printf("'%s' ('%s') uses undefined symbol '%llx' in '%s' ('%s') module\n", 135 | module->moduleName, module->soName, (unsigned long long)symbol.id, defModule->moduleName, defModule->soName); 136 | if (foundInLibs.size() > 0) { 137 | std::printf("Requested library is '%s', exists in libraries: [", 138 | library.name.c_str()); 139 | 140 | for (bool isFirst = true; auto &lib : foundInLibs) { 141 | if (isFirst) { 142 | isFirst = false; 143 | } else { 144 | std::printf(", "); 145 | } 146 | 147 | std::printf("'%s'", lib.c_str()); 148 | } 149 | std::printf("]\n"); 150 | } 151 | return std::pair(module, symbol.address); 152 | }; 153 | 154 | switch (rel.relType) { 155 | case kRelNone: 156 | return {}; 157 | case kRel64: { 158 | auto [defObj, S] = findDefModule(); 159 | *where = reinterpret_cast(defObj->base) + S + A; 160 | return {}; 161 | } 162 | return {}; 163 | case kRelPc32: { 164 | auto [defObj, S] = findDefModule(); 165 | *where32 = reinterpret_cast(defObj->base) + S + A - P; 166 | return {}; 167 | } 168 | // case kRelCopy: 169 | // return{}; 170 | case kRelGlobDat: { 171 | auto [defObj, S] = findDefModule(); 172 | *where = reinterpret_cast(defObj->base) + S; 173 | return {}; 174 | } 175 | case kRelJumpSlot: { 176 | bool isLazyBind = false; // TODO 177 | if (isLazyBind) { 178 | *where += B; 179 | } else { 180 | auto [defObj, S] = findDefModule(); 181 | *where = reinterpret_cast(defObj->base) + S; 182 | } 183 | return {}; 184 | } 185 | 186 | case kRelRelative: 187 | *where = B + A; 188 | return {}; 189 | case kRelDtpMod64: { 190 | auto [defObj, S] = findDefModule(); 191 | *where += defObj->tlsIndex; 192 | return {}; 193 | } 194 | case kRelDtpOff64: { 195 | auto [defObj, S] = findDefModule(); 196 | *where += S + A; 197 | return {}; 198 | } 199 | case kRelTpOff64: { 200 | auto [defObj, S] = findDefModule(); 201 | if (!defObj->isTlsDone) { 202 | allocateTlsOffset(process, module); 203 | } 204 | *where = S - defObj->tlsOffset + A; 205 | return {}; 206 | } 207 | case kRelDtpOff32: { 208 | auto [defObj, S] = findDefModule(); 209 | *where32 += S + A; 210 | return {}; 211 | } 212 | case kRelTpOff32: { 213 | auto [defObj, S] = findDefModule(); 214 | if (!defObj->isTlsDone) { 215 | allocateTlsOffset(process, module); 216 | } 217 | *where32 = S - defObj->tlsOffset + A; 218 | return {}; 219 | } 220 | } 221 | 222 | std::fprintf(stderr, "unimplemented relocation type %u\n", 223 | (unsigned)rel.relType); 224 | std::abort(); 225 | return {}; 226 | } 227 | 228 | orbis::SysResult orbis::Module::relocate(Process *process) { 229 | for (auto rel : pltRelocations) { 230 | auto result = doRelocation(process, this, rel); 231 | 232 | if (result.isError()) { 233 | return result; 234 | } 235 | } 236 | 237 | pltRelocations = {}; 238 | 239 | for (auto rel : nonPltRelocations) { 240 | auto result = doRelocation(process, this, rel); 241 | 242 | if (result.isError()) { 243 | return result; 244 | } 245 | } 246 | 247 | nonPltRelocations = {}; 248 | 249 | return {}; 250 | } 251 | 252 | void orbis::Module::destroy() { 253 | std::lock_guard lock(proc->mtx); 254 | proc->modulesMap.remove(id); 255 | } 256 | -------------------------------------------------------------------------------- /src/sys/sys_acct.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | #include "error.hpp" 3 | 4 | orbis::SysResult orbis::sys_acct(Thread *thread, ptr path) { return ErrorCode::NOSYS; } 5 | -------------------------------------------------------------------------------- /src/sys/sys_audit.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_audit(Thread *thread, ptr record, uint length) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_auditon(Thread *thread, sint cmd, ptr data, uint length) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys_getauid(Thread *thread, ptr auid) { return ErrorCode::NOSYS; } 6 | orbis::SysResult orbis::sys_setauid(Thread *thread, ptr auid) { return ErrorCode::NOSYS; } 7 | orbis::SysResult orbis::sys_getaudit(Thread *thread, ptr auditinfo) { return ErrorCode::NOSYS; } 8 | orbis::SysResult orbis::sys_setaudit(Thread *thread, ptr auditinfo) { return ErrorCode::NOSYS; } 9 | orbis::SysResult orbis::sys_getaudit_addr(Thread *thread, ptr auditinfo_addr, uint length) { return ErrorCode::NOSYS; } 10 | orbis::SysResult orbis::sys_setaudit_addr(Thread *thread, ptr auditinfo_addr, uint length) { return ErrorCode::NOSYS; } 11 | orbis::SysResult orbis::sys_auditctl(Thread *thread, ptr path) { return ErrorCode::NOSYS; } 12 | -------------------------------------------------------------------------------- /src/sys/sys_capability.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_cap_enter(Thread *thread) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_cap_getmode(Thread *thread, ptr modep) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys_cap_new(Thread *thread, sint fd, uint64_t rights) { return ErrorCode::NOSYS; } 6 | orbis::SysResult orbis::sys_cap_getrights(Thread *thread, sint fd, ptr rights) { return ErrorCode::NOSYS; } 7 | -------------------------------------------------------------------------------- /src/sys/sys_context.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_getcontext(Thread *thread, ptr ucp) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_setcontext(Thread *thread, ptr ucp) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys_swapcontext(Thread *thread, ptr oucp, ptr ucp) { return ErrorCode::NOSYS; } 6 | -------------------------------------------------------------------------------- /src/sys/sys_cpuset.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_cpuset(Thread *thread, ptr setid) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_cpuset_setid(Thread *thread, cpuwhich_t which, id_t id, cpusetid_t setid) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys_cpuset_getid(Thread *thread, cpulevel_t level, cpuwhich_t which, id_t id, ptr setid) { return ErrorCode::NOSYS; } 6 | orbis::SysResult orbis::sys_cpuset_getaffinity(Thread *thread, cpulevel_t level, cpuwhich_t which, id_t id, size_t cpusetsize, ptr mask) { return ErrorCode::NOSYS; } 7 | orbis::SysResult orbis::sys_cpuset_setaffinity(Thread *thread, cpulevel_t level, cpuwhich_t which, id_t id, size_t cpusetsize, ptr mask) { return ErrorCode::NOSYS; } 8 | -------------------------------------------------------------------------------- /src/sys/sys_descrip.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_getdtablesize(Thread *thread) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_dup2(Thread *thread, uint from, uint to) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys_dup(Thread *thread, uint fd) { return ErrorCode::NOSYS; } 6 | orbis::SysResult orbis::sys_fcntl(Thread *thread, sint fd, sint cmd, slong arg) { return ErrorCode::NOSYS; } 7 | orbis::SysResult orbis::sys_close(Thread *thread, sint fd) { 8 | if (auto close = thread->tproc->ops->close) { 9 | return close(thread, fd); 10 | } 11 | 12 | return ErrorCode::NOSYS; 13 | } 14 | orbis::SysResult orbis::sys_closefrom(Thread *thread, sint lowfd) { return ErrorCode::NOSYS; } 15 | orbis::SysResult orbis::sys_fstat(Thread *thread, sint fd, ptr ub) { return ErrorCode::NOSYS; } 16 | orbis::SysResult orbis::sys_nfstat(Thread *thread, sint fd, ptr sb) { return ErrorCode::NOSYS; } 17 | orbis::SysResult orbis::sys_fpathconf(Thread *thread, sint fd, sint name) { return ErrorCode::NOSYS; } 18 | orbis::SysResult orbis::sys_flock(Thread *thread, sint fd, sint how) { return ErrorCode::NOSYS; } 19 | -------------------------------------------------------------------------------- /src/sys/sys_environment.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_kenv(Thread *thread, sint what, ptr name, ptr value, sint len) { return ErrorCode::NOSYS; } 4 | -------------------------------------------------------------------------------- /src/sys/sys_event.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_kqueue(Thread *thread) { 4 | return {}; 5 | } 6 | 7 | orbis::SysResult orbis::sys_kevent(Thread *thread, sint fd, ptr changelist, sint nchanges, ptr eventlist, sint nevents, ptr timeout) { 8 | return {}; 9 | } 10 | -------------------------------------------------------------------------------- /src/sys/sys_exec.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_execve(Thread *thread, ptr fname, ptr> argv, ptr> envv) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_fexecve(Thread *thread, sint fd, ptr> argv, ptr> envv) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys___mac_execve(Thread *thread, ptr fname, ptr> argv, ptr> envv, ptr mac_p) { return ErrorCode::NOSYS; } 6 | -------------------------------------------------------------------------------- /src/sys/sys_exit.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_exit(Thread *thread, sint status) { 4 | if (auto exit = thread->tproc->ops->exit) { 5 | return exit(thread, status); 6 | } 7 | 8 | return ErrorCode::NOSYS; 9 | } 10 | orbis::SysResult orbis::sys_abort2(Thread *thread, ptr why, sint narg, ptr> args) { return ErrorCode::NOSYS; } 11 | orbis::SysResult orbis::sys_wait4(Thread *thread, sint pid, ptr status, sint options, ptr rusage) { return ErrorCode::NOSYS; } 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/sys/sys_fork.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_fork(Thread *thread) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_pdfork(Thread *thread, ptr fdp, sint flags) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys_vfork(Thread *thread) { return ErrorCode::NOSYS; } 6 | orbis::SysResult orbis::sys_rfork(Thread *thread, sint flags) { return ErrorCode::NOSYS; } 7 | -------------------------------------------------------------------------------- /src/sys/sys_generic.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_read(Thread *thread, sint fd, ptr buf, size_t nbyte) { 4 | if (auto read = thread->tproc->ops->read) { 5 | return read(thread, fd, buf, nbyte); 6 | } 7 | 8 | return ErrorCode::NOSYS; 9 | } 10 | orbis::SysResult orbis::sys_pread(Thread *thread, sint fd, ptr buf, size_t nbyte, off_t offset) { 11 | if (auto pread = thread->tproc->ops->pread) { 12 | return pread(thread, fd, buf, nbyte, offset); 13 | } 14 | 15 | return ErrorCode::NOSYS; 16 | } 17 | orbis::SysResult orbis::sys_freebsd6_pread(Thread *thread, sint fd, ptr buf, size_t nbyte, sint, off_t offset) { 18 | return sys_pread(thread, fd, buf, nbyte, offset); 19 | } 20 | orbis::SysResult orbis::sys_readv(Thread *thread, sint fd, ptr iovp, uint iovcnt) { return ErrorCode::NOSYS; } 21 | orbis::SysResult orbis::sys_preadv(Thread *thread, sint fd, ptr iovp, uint iovcnt, off_t offset) { return ErrorCode::NOSYS; } 22 | orbis::SysResult orbis::sys_write(Thread *thread, sint fd, ptr buf, size_t nbyte) { 23 | if (auto write = thread->tproc->ops->write) { 24 | return write(thread, fd, buf, nbyte); 25 | } 26 | 27 | return ErrorCode::NOSYS; 28 | } 29 | orbis::SysResult orbis::sys_pwrite(Thread *thread, sint fd, ptr buf, size_t nbyte, off_t offset) { 30 | if (auto pwrite = thread->tproc->ops->pwrite) { 31 | return pwrite(thread, fd, buf, nbyte, offset); 32 | } 33 | return ErrorCode::NOSYS; 34 | } 35 | orbis::SysResult orbis::sys_freebsd6_pwrite(Thread *thread, sint fd, ptr buf, size_t nbyte, sint, off_t offset) { 36 | return sys_pwrite(thread, fd, buf, nbyte, offset); 37 | } 38 | orbis::SysResult orbis::sys_writev(Thread *thread, sint fd, ptr iovp, uint iovcnt) { return ErrorCode::NOSYS; } 39 | orbis::SysResult orbis::sys_pwritev(Thread *thread, sint fd, ptr iovp, uint iovcnt, off_t offset) { return ErrorCode::NOSYS; } 40 | orbis::SysResult orbis::sys_ftruncate(Thread *thread, sint fd, off_t length) { 41 | if (auto ftruncate = thread->tproc->ops->ftruncate) { 42 | return ftruncate(thread, fd, length); 43 | } 44 | return ErrorCode::NOSYS; 45 | } 46 | orbis::SysResult orbis::sys_freebsd6_ftruncate(Thread *thread, sint fd, sint, off_t length) { 47 | return sys_ftruncate(thread, fd, length); 48 | } 49 | orbis::SysResult orbis::sys_ioctl(Thread *thread, sint fd, ulong com, caddr_t data) { 50 | if (auto ioctl = thread->tproc->ops->ioctl) { 51 | return ioctl(thread, fd, com, data); 52 | } 53 | return ErrorCode::NOSYS; 54 | } 55 | orbis::SysResult orbis::sys_pselect(Thread *thread, sint nd, ptr in, ptr ou, ptr ex, ptr ts, ptr sm) { return ErrorCode::NOSYS; } 56 | orbis::SysResult orbis::sys_select(Thread *thread, sint nd, ptr in, ptr out, ptr ex, ptr tv) { return ErrorCode::NOSYS; } 57 | orbis::SysResult orbis::sys_poll(Thread *thread, ptr fds, uint nfds, sint timeout) { return ErrorCode::NOSYS; } 58 | orbis::SysResult orbis::sys_openbsd_poll(Thread *thread, ptr fds, uint nfds, sint timeout) { return ErrorCode::NOSYS; } 59 | 60 | orbis::SysResult orbis::sys_nlm_syscall(Thread *thread, sint debug_level, sint grace_period, sint addr_count, ptr> addrs) { return ErrorCode::NOSYS; } 61 | orbis::SysResult orbis::sys_nfssvc(Thread *thread, sint flag, caddr_t argp) { return ErrorCode::NOSYS; } 62 | orbis::SysResult orbis::sys_sysarch(Thread *thread, sint op, ptr parms) { 63 | if (op == 129) { 64 | auto fs = uread((ptr)parms); 65 | std::printf("sys_sysarch: set FS to 0x%zx\n", (std::size_t)fs); 66 | thread->fsBase = fs; 67 | return {}; 68 | } 69 | 70 | std::printf("sys_sysarch(op = %d, parms = %p): unknown op\n", op, parms); 71 | return {}; 72 | } 73 | orbis::SysResult orbis::sys_nnpfs_syscall(Thread *thread, sint operation, ptr a_pathP, sint opcode, ptr a_paramsP, sint a_followSymlinks) { return ErrorCode::NOSYS; } 74 | orbis::SysResult orbis::sys_afs3_syscall(Thread *thread, slong syscall, slong param1, slong param2, slong param3, slong param4, slong param5, slong param6) { return ErrorCode::NOSYS; } 75 | orbis::SysResult orbis::sys_gssd_syscall(Thread *thread, ptr path) { return ErrorCode::NOSYS; } 76 | -------------------------------------------------------------------------------- /src/sys/sys_jail.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_jail(Thread *thread, ptr jail) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_jail_set(Thread *thread, ptr iovp, uint iovcnt, sint flags) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys_jail_get(Thread *thread, ptr iovp, uint iovcnt, sint flags) { return ErrorCode::NOSYS; } 6 | orbis::SysResult orbis::sys_jail_remove(Thread *thread, sint jid) { return ErrorCode::NOSYS; } 7 | orbis::SysResult orbis::sys_jail_attach(Thread *thread, sint jid) { return ErrorCode::NOSYS; } 8 | -------------------------------------------------------------------------------- /src/sys/sys_ktrace.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_ktrace(Thread *thread, ptr fname, sint ops, sint facs, sint pit) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_utrace(Thread *thread, ptr addr, size_t len) { return ErrorCode::NOSYS; } 5 | -------------------------------------------------------------------------------- /src/sys/sys_linker.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_kldload(Thread *thread, ptr file) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_kldunload(Thread *thread, sint fileid) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys_kldunloadf(Thread *thread, slong fileid, sint flags) { return ErrorCode::NOSYS; } 6 | orbis::SysResult orbis::sys_kldfind(Thread *thread, ptr name) { return ErrorCode::NOSYS; } 7 | orbis::SysResult orbis::sys_kldnext(Thread *thread, sint fileid) { return ErrorCode::NOSYS; } 8 | orbis::SysResult orbis::sys_kldstat(Thread *thread, sint fileid, ptr stat) { return ErrorCode::NOSYS; } 9 | orbis::SysResult orbis::sys_kldfirstmod(Thread *thread, sint fileid) { return ErrorCode::NOSYS; } 10 | orbis::SysResult orbis::sys_kldsym(Thread *thread, sint fileid, sint cmd, ptr data) { return ErrorCode::NOSYS; } 11 | -------------------------------------------------------------------------------- /src/sys/sys_loginclass.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_getloginclass(Thread *thread, ptr namebuf, size_t namelen) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_setloginclass(Thread *thread, ptr namebuf) { return ErrorCode::NOSYS; } 5 | -------------------------------------------------------------------------------- /src/sys/sys_mac.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys___mac_get_pid(Thread *thread, pid_t pid, ptr mac_p) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys___mac_get_proc(Thread *thread, ptr mac_p) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys___mac_set_proc(Thread *thread, ptr mac_p) { return ErrorCode::NOSYS; } 6 | orbis::SysResult orbis::sys___mac_get_fd(Thread *thread, sint fd, ptr mac_p) { return ErrorCode::NOSYS; } 7 | orbis::SysResult orbis::sys___mac_get_file(Thread *thread, ptr path, ptr mac_p) { return ErrorCode::NOSYS; } 8 | orbis::SysResult orbis::sys___mac_set_fd(Thread *thread, sint fd, ptr mac_p) { return ErrorCode::NOSYS; } 9 | orbis::SysResult orbis::sys___mac_set_file(Thread *thread, ptr path, ptr mac_p) { return ErrorCode::NOSYS; } 10 | orbis::SysResult orbis::sys___mac_get_link(Thread *thread, ptr path_p, ptr mac_p) { return ErrorCode::NOSYS; } 11 | orbis::SysResult orbis::sys___mac_set_link(Thread *thread, ptr path_p, ptr mac_p) { return ErrorCode::NOSYS; } 12 | orbis::SysResult orbis::sys_mac_syscall(Thread *thread, ptr policy, sint call, ptr arg) { return ErrorCode::NOSYS; } 13 | -------------------------------------------------------------------------------- /src/sys/sys_module.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_modnext(Thread *thread, sint modid) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_modfnext(Thread *thread, sint modid) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys_modstat(Thread *thread, sint modid, ptr stat) { return ErrorCode::NOSYS; } 6 | orbis::SysResult orbis::sys_modfind(Thread *thread, ptr name) { return ErrorCode::NOSYS; } 7 | -------------------------------------------------------------------------------- /src/sys/sys_msg.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_msgctl(Thread *thread, sint msqid, sint cmd, ptr buf) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_msgget(Thread *thread, key_t key, sint msgflg) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys_msgsnd(Thread *thread, sint msqid, ptr msgp, size_t msgsz, sint msgflg) { return ErrorCode::NOSYS; } 6 | orbis::SysResult orbis::sys_msgrcv(Thread *thread, sint msqid, ptr msgp, size_t msgsz, slong msgtyp, sint msgflg) { return ErrorCode::NOSYS; } 7 | orbis::SysResult orbis::sys_msgsys(Thread *thread, sint which, sint a2, sint a3, sint a4, sint a5, sint a6) { return ErrorCode::NOSYS; } 8 | -------------------------------------------------------------------------------- /src/sys/sys_ntptime.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_ntp_gettime(Thread *thread, ptr ntvp) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_ntp_adjtime(Thread *thread, ptr tp) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys_adjtime(Thread *thread, ptr delta, ptr olddelta) { return ErrorCode::NOSYS; } 6 | -------------------------------------------------------------------------------- /src/sys/sys_p1003_1b.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_sched_setparam(Thread *thread, pid_t pid, ptr param) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_sched_getparam(Thread *thread, pid_t pid, ptr param) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys_sched_setscheduler(Thread *thread, pid_t pid, sint policy, ptr param) { return ErrorCode::NOSYS; } 6 | orbis::SysResult orbis::sys_sched_getscheduler(Thread *thread, pid_t pid) { return ErrorCode::NOSYS; } 7 | orbis::SysResult orbis::sys_sched_yield(Thread *thread) { return ErrorCode::NOSYS; } 8 | orbis::SysResult orbis::sys_sched_get_priority_max(Thread *thread, sint policy) { return ErrorCode::NOSYS; } 9 | orbis::SysResult orbis::sys_sched_get_priority_min(Thread *thread, sint policy) { return ErrorCode::NOSYS; } 10 | orbis::SysResult orbis::sys_sched_rr_get_interval(Thread *thread, pid_t pid, ptr interval) { return ErrorCode::NOSYS; } 11 | -------------------------------------------------------------------------------- /src/sys/sys_pipe.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_pipe(Thread *thread) { return ErrorCode::NOSYS; } 4 | -------------------------------------------------------------------------------- /src/sys/sys_procdesc.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_pdgetpid(Thread *thread, sint fd, ptr pidp) { return ErrorCode::NOSYS; } 4 | -------------------------------------------------------------------------------- /src/sys/sys_process.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_ptrace(Thread *thread, sint req, pid_t pid, caddr_t addr, sint data) { return ErrorCode::NOSYS; } 4 | -------------------------------------------------------------------------------- /src/sys/sys_prot.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_getpid(Thread *thread) { 4 | thread->retval[0] = thread->tid; 5 | return {}; 6 | } 7 | orbis::SysResult orbis::sys_getppid(Thread *thread) { return ErrorCode::NOSYS; } 8 | orbis::SysResult orbis::sys_getpgrp(Thread *thread) { return ErrorCode::NOSYS; } 9 | orbis::SysResult orbis::sys_getpgid(Thread *thread, pid_t pid) { return ErrorCode::NOSYS; } 10 | orbis::SysResult orbis::sys_getsid(Thread *thread, pid_t pid) { return ErrorCode::NOSYS; } 11 | orbis::SysResult orbis::sys_getuid(Thread *thread) { return ErrorCode::NOSYS; } 12 | orbis::SysResult orbis::sys_geteuid(Thread *thread) { return ErrorCode::NOSYS; } 13 | orbis::SysResult orbis::sys_getgid(Thread *thread) { return ErrorCode::NOSYS; } 14 | orbis::SysResult orbis::sys_getegid(Thread *thread) { return ErrorCode::NOSYS; } 15 | orbis::SysResult orbis::sys_getgroups(Thread *thread, uint gidsetsize, ptr gidset) { return ErrorCode::NOSYS; } 16 | orbis::SysResult orbis::sys_setsid(Thread *thread) { return ErrorCode::NOSYS; } 17 | orbis::SysResult orbis::sys_setpgid(Thread *thread, sint pid, sint pgid) { return ErrorCode::NOSYS; } 18 | orbis::SysResult orbis::sys_setuid(Thread *thread, uid_t uid) { return ErrorCode::NOSYS; } 19 | orbis::SysResult orbis::sys_seteuid(Thread *thread, uid_t euid) { return ErrorCode::NOSYS; } 20 | orbis::SysResult orbis::sys_setgid(Thread *thread, gid_t gid) { return ErrorCode::NOSYS; } 21 | orbis::SysResult orbis::sys_setegid(Thread *thread, gid_t egid) { return ErrorCode::NOSYS; } 22 | orbis::SysResult orbis::sys_setgroups(Thread *thread, uint gidsetsize, ptr gidset) { return ErrorCode::NOSYS; } 23 | orbis::SysResult orbis::sys_setreuid(Thread *thread, sint ruid, sint euid) { return ErrorCode::NOSYS; } 24 | orbis::SysResult orbis::sys_setregid(Thread *thread, sint rgid, sint egid) { return ErrorCode::NOSYS; } 25 | orbis::SysResult orbis::sys_setresuid(Thread *thread, uid_t ruid, uid_t euid, uid_t suid) { return ErrorCode::NOSYS; } 26 | orbis::SysResult orbis::sys_setresgid(Thread *thread, gid_t rgid, gid_t egid, gid_t sgid) { return ErrorCode::NOSYS; } 27 | orbis::SysResult orbis::sys_getresuid(Thread *thread, ptr ruid, ptr euid, ptr suid) { return ErrorCode::NOSYS; } 28 | orbis::SysResult orbis::sys_getresgid(Thread *thread, ptr rgid, ptr egid, ptr sgid) { return ErrorCode::NOSYS; } 29 | orbis::SysResult orbis::sys_issetugid(Thread *thread) { return ErrorCode::NOSYS; } 30 | orbis::SysResult orbis::sys___setugid(Thread *thread, sint flags) { return ErrorCode::NOSYS; } 31 | orbis::SysResult orbis::sys_getlogin(Thread *thread, ptr namebuf, uint namelen) { return ErrorCode::NOSYS; } 32 | orbis::SysResult orbis::sys_setlogin(Thread *thread, ptr namebuf) { return ErrorCode::NOSYS; } 33 | -------------------------------------------------------------------------------- /src/sys/sys_pty_pts.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_posix_openpt(Thread *thread, sint flags) { return ErrorCode::NOSYS; } 4 | -------------------------------------------------------------------------------- /src/sys/sys_rctl.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_rctl_get_racct(Thread *thread, ptr inbufp, size_t inbuflen, ptr outbuf, size_t outbuflen) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_rctl_get_rules(Thread *thread, ptr inbufp, size_t inbuflen, ptr outbuf, size_t outbuflen) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys_rctl_get_limits(Thread *thread, ptr inbufp, size_t inbuflen, ptr outbuf, size_t outbuflen) { return ErrorCode::NOSYS; } 6 | orbis::SysResult orbis::sys_rctl_add_rule(Thread *thread, ptr inbufp, size_t inbuflen, ptr outbuf, size_t outbuflen) { return ErrorCode::NOSYS; } 7 | orbis::SysResult orbis::sys_rctl_remove_rule(Thread *thread, ptr inbufp, size_t inbuflen, ptr outbuf, size_t outbuflen) { return ErrorCode::NOSYS; } 8 | -------------------------------------------------------------------------------- /src/sys/sys_resource.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_getpriority(Thread *thread, sint which, sint who) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_setpriority(Thread *thread, sint which, sint who, sint prio) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys_rtprio_thread(Thread *thread, sint function, lwpid_t lwpid, ptr rtp) { 6 | std::printf("sys_rtprio_thread: unimplemented\n"); 7 | return {}; 8 | } 9 | orbis::SysResult orbis::sys_rtprio(Thread *thread, sint function, pid_t pid, ptr rtp) { return ErrorCode::NOSYS; } 10 | orbis::SysResult orbis::sys_setrlimit(Thread *thread, uint which, ptr rlp) { return ErrorCode::NOSYS; } 11 | orbis::SysResult orbis::sys_getrlimit(Thread *thread, uint which, ptr rlp) { return ErrorCode::NOSYS; } 12 | orbis::SysResult orbis::sys_getrusage(Thread *thread, sint who, ptr rusage) { return ErrorCode::NOSYS; } 13 | -------------------------------------------------------------------------------- /src/sys/sys_route.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_setfib(Thread *thread, sint fib) { return ErrorCode::NOSYS; } 4 | -------------------------------------------------------------------------------- /src/sys/sys_sce.cpp: -------------------------------------------------------------------------------- 1 | #include "error.hpp" 2 | #include "module/ModuleInfo.hpp" 3 | #include "module/ModuleInfoEx.hpp" 4 | #include "sys/sysproto.hpp" 5 | 6 | orbis::SysResult orbis::sys_netcontrol(Thread *thread, sint fd, uint op, 7 | ptr buf, uint nbuf) { 8 | return ErrorCode::NOSYS; 9 | } 10 | orbis::SysResult orbis::sys_netabort(Thread *thread /* TODO */) { 11 | return ErrorCode::NOSYS; 12 | } 13 | orbis::SysResult orbis::sys_netgetsockinfo(Thread *thread /* TODO */) { 14 | return ErrorCode::NOSYS; 15 | } 16 | orbis::SysResult orbis::sys_socketex(Thread *thread, ptr name, 17 | sint domain, sint type, sint protocol) { 18 | return ErrorCode::NOSYS; 19 | } 20 | orbis::SysResult orbis::sys_socketclose(Thread *thread /* TODO */) { 21 | return ErrorCode::NOSYS; 22 | } 23 | orbis::SysResult orbis::sys_netgetiflist(Thread *thread /* TODO */) { 24 | return ErrorCode::NOSYS; 25 | } 26 | orbis::SysResult orbis::sys_kqueueex(Thread *thread /* TODO */) { 27 | return ErrorCode::NOSYS; 28 | } 29 | orbis::SysResult orbis::sys_mtypeprotect(Thread *thread /* TODO */) { 30 | return ErrorCode::NOSYS; 31 | } 32 | orbis::SysResult orbis::sys_regmgr_call(Thread *thread, uint32_t op, 33 | uint32_t id, ptr result, ptr value, 34 | uint64_t type) { 35 | if (op == 25) { 36 | struct nonsys_int { 37 | union { 38 | uint64_t encoded_id; 39 | struct { 40 | uint8_t data[4]; 41 | uint8_t table; 42 | uint8_t index; 43 | uint16_t checksum; 44 | } encoded_id_parts; 45 | }; 46 | uint32_t unk; 47 | uint32_t value; 48 | }; 49 | 50 | auto int_value = reinterpret_cast(value); 51 | 52 | std::printf(" encoded_id = %lx\n", int_value->encoded_id); 53 | std::printf(" data[0] = %02x\n", int_value->encoded_id_parts.data[0]); 54 | std::printf(" data[1] = %02x\n", int_value->encoded_id_parts.data[1]); 55 | std::printf(" data[2] = %02x\n", int_value->encoded_id_parts.data[2]); 56 | std::printf(" data[3] = %02x\n", int_value->encoded_id_parts.data[3]); 57 | std::printf(" table = %u\n", int_value->encoded_id_parts.table); 58 | std::printf(" index = %u\n", int_value->encoded_id_parts.index); 59 | std::printf(" checksum = %x\n", int_value->encoded_id_parts.checksum); 60 | std::printf(" unk = %x\n", int_value->unk); 61 | std::printf(" value = %x\n", int_value->value); 62 | } 63 | 64 | return{}; 65 | 66 | } 67 | orbis::SysResult orbis::sys_jitshm_create(Thread *thread /* TODO */) { 68 | return ErrorCode::NOSYS; 69 | } 70 | orbis::SysResult orbis::sys_jitshm_alias(Thread *thread /* TODO */) { 71 | return ErrorCode::NOSYS; 72 | } 73 | orbis::SysResult orbis::sys_dl_get_list(Thread *thread /* TODO */) { 74 | return ErrorCode::NOSYS; 75 | } 76 | orbis::SysResult orbis::sys_dl_get_info(Thread *thread /* TODO */) { 77 | return ErrorCode::NOSYS; 78 | } 79 | orbis::SysResult orbis::sys_dl_notify_event(Thread *thread /* TODO */) { 80 | return ErrorCode::NOSYS; 81 | } 82 | orbis::SysResult orbis::sys_evf_create(Thread *thread, ptr name, 83 | sint flag, ptr evf) { 84 | return ErrorCode::NOSYS; 85 | } 86 | orbis::SysResult orbis::sys_evf_delete(Thread *thread, sint fd) { 87 | return ErrorCode::NOSYS; 88 | } 89 | orbis::SysResult orbis::sys_evf_open(Thread *thread, ptr name) { 90 | return ErrorCode::NOSYS; 91 | } 92 | orbis::SysResult orbis::sys_evf_close(Thread *thread, sint fd) { 93 | return ErrorCode::NOSYS; 94 | } 95 | orbis::SysResult orbis::sys_evf_wait(Thread *thread /* TODO */) { 96 | return ErrorCode::NOSYS; 97 | } 98 | orbis::SysResult orbis::sys_evf_trywait(Thread *thread /* TODO */) { 99 | return ErrorCode::NOSYS; 100 | } 101 | orbis::SysResult orbis::sys_evf_set(Thread *thread, sint fd) { 102 | return ErrorCode::NOSYS; 103 | } 104 | orbis::SysResult orbis::sys_evf_clear(Thread *thread, sint fd) { 105 | return ErrorCode::NOSYS; 106 | } 107 | orbis::SysResult orbis::sys_evf_cancel(Thread *thread, sint fd) { 108 | return ErrorCode::NOSYS; 109 | } 110 | orbis::SysResult orbis::sys_query_memory_protection(Thread *thread /* TODO */) { 111 | return ErrorCode::NOSYS; 112 | } 113 | orbis::SysResult orbis::sys_batch_map(Thread *thread /* TODO */) { 114 | return ErrorCode::NOSYS; 115 | } 116 | orbis::SysResult orbis::sys_osem_create(Thread *thread /* TODO */) { 117 | return ErrorCode::NOSYS; 118 | } 119 | orbis::SysResult orbis::sys_osem_delete(Thread *thread /* TODO */) { 120 | return ErrorCode::NOSYS; 121 | } 122 | orbis::SysResult orbis::sys_osem_open(Thread *thread /* TODO */) { 123 | return ErrorCode::NOSYS; 124 | } 125 | orbis::SysResult orbis::sys_osem_close(Thread *thread /* TODO */) { 126 | return ErrorCode::NOSYS; 127 | } 128 | orbis::SysResult orbis::sys_osem_wait(Thread *thread /* TODO */) { 129 | return ErrorCode::NOSYS; 130 | } 131 | orbis::SysResult orbis::sys_osem_trywait(Thread *thread /* TODO */) { 132 | return ErrorCode::NOSYS; 133 | } 134 | orbis::SysResult orbis::sys_osem_post(Thread *thread /* TODO */) { 135 | return ErrorCode::NOSYS; 136 | } 137 | orbis::SysResult orbis::sys_osem_cancel(Thread *thread /* TODO */) { 138 | return ErrorCode::NOSYS; 139 | } 140 | orbis::SysResult orbis::sys_namedobj_create(Thread *thread, ptr name, ptr object, uint64_t type) { 141 | std::printf("sys_namedobj_create(name = %s, object = %p, type = 0x%lx) -> %d\n", name, object, type, 1); 142 | thread->retval[0] = 1; 143 | return {}; 144 | } 145 | orbis::SysResult orbis::sys_namedobj_delete(Thread *thread /* TODO */) { 146 | std::printf("TODO: sys_namedobj_delete\n"); 147 | return {}; 148 | } 149 | orbis::SysResult orbis::sys_set_vm_container(Thread *thread /* TODO */) { 150 | return ErrorCode::NOSYS; 151 | } 152 | orbis::SysResult orbis::sys_debug_init(Thread *thread /* TODO */) { 153 | return ErrorCode::NOSYS; 154 | } 155 | orbis::SysResult orbis::sys_suspend_process(Thread *thread, pid_t pid) { 156 | return ErrorCode::NOSYS; 157 | } 158 | orbis::SysResult orbis::sys_resume_process(Thread *thread, pid_t pid) { 159 | return ErrorCode::NOSYS; 160 | } 161 | orbis::SysResult orbis::sys_opmc_enable(Thread *thread /* TODO */) { 162 | return ErrorCode::NOSYS; 163 | } 164 | orbis::SysResult orbis::sys_opmc_disable(Thread *thread /* TODO */) { 165 | return ErrorCode::NOSYS; 166 | } 167 | orbis::SysResult orbis::sys_opmc_set_ctl(Thread *thread /* TODO */) { 168 | return ErrorCode::NOSYS; 169 | } 170 | orbis::SysResult orbis::sys_opmc_set_ctr(Thread *thread /* TODO */) { 171 | return ErrorCode::NOSYS; 172 | } 173 | orbis::SysResult orbis::sys_opmc_get_ctr(Thread *thread /* TODO */) { 174 | return ErrorCode::NOSYS; 175 | } 176 | orbis::SysResult orbis::sys_budget_create(Thread *thread /* TODO */) { 177 | return ErrorCode::NOSYS; 178 | } 179 | orbis::SysResult orbis::sys_budget_delete(Thread *thread /* TODO */) { 180 | return ErrorCode::NOSYS; 181 | } 182 | orbis::SysResult orbis::sys_budget_get(Thread *thread /* TODO */) { 183 | return ErrorCode::NOSYS; 184 | } 185 | orbis::SysResult orbis::sys_budget_set(Thread *thread /* TODO */) { 186 | return ErrorCode::NOSYS; 187 | } 188 | orbis::SysResult orbis::sys_virtual_query(Thread *thread, ptr addr, 189 | uint64_t unk, ptr info, 190 | size_t infosz) { 191 | if (auto virtual_query = thread->tproc->ops->virtual_query) { 192 | return virtual_query(thread, addr, unk, info, infosz); 193 | } 194 | 195 | return ErrorCode::NOSYS; 196 | } 197 | orbis::SysResult orbis::sys_mdbg_call(Thread *thread /* TODO */) { 198 | return ErrorCode::NOSYS; 199 | } 200 | orbis::SysResult orbis::sys_obs_sblock_create(Thread *thread /* TODO */) { 201 | return ErrorCode::NOSYS; 202 | } 203 | orbis::SysResult orbis::sys_obs_sblock_delete(Thread *thread /* TODO */) { 204 | return ErrorCode::NOSYS; 205 | } 206 | orbis::SysResult orbis::sys_obs_sblock_enter(Thread *thread /* TODO */) { 207 | return ErrorCode::NOSYS; 208 | } 209 | orbis::SysResult orbis::sys_obs_sblock_exit(Thread *thread /* TODO */) { 210 | return ErrorCode::NOSYS; 211 | } 212 | orbis::SysResult orbis::sys_obs_sblock_xenter(Thread *thread /* TODO */) { 213 | return ErrorCode::NOSYS; 214 | } 215 | orbis::SysResult orbis::sys_obs_sblock_xexit(Thread *thread /* TODO */) { 216 | return ErrorCode::NOSYS; 217 | } 218 | orbis::SysResult orbis::sys_obs_eport_create(Thread *thread /* TODO */) { 219 | return ErrorCode::NOSYS; 220 | } 221 | orbis::SysResult orbis::sys_obs_eport_delete(Thread *thread /* TODO */) { 222 | return ErrorCode::NOSYS; 223 | } 224 | orbis::SysResult orbis::sys_obs_eport_trigger(Thread *thread /* TODO */) { 225 | return ErrorCode::NOSYS; 226 | } 227 | orbis::SysResult orbis::sys_obs_eport_open(Thread *thread /* TODO */) { 228 | return ErrorCode::NOSYS; 229 | } 230 | orbis::SysResult orbis::sys_obs_eport_close(Thread *thread /* TODO */) { 231 | return ErrorCode::NOSYS; 232 | } 233 | orbis::SysResult orbis::sys_is_in_sandbox(Thread *thread /* TODO */) { 234 | std::printf("sys_is_in_sandbox() -> 0\n"); 235 | return{}; 236 | } 237 | orbis::SysResult orbis::sys_dmem_container(Thread *thread) { 238 | thread->retval[0] = 0; // returns default direct memory device 239 | return {}; 240 | } 241 | orbis::SysResult orbis::sys_get_authinfo(Thread *thread, pid_t pid, ptr info) { 242 | struct authinfo { 243 | uint64_t a; 244 | uint64_t b; 245 | }; 246 | 247 | std::memset(info, 0, 136); 248 | ((authinfo *)info)->b = ~0; 249 | 250 | return {}; 251 | } 252 | orbis::SysResult orbis::sys_mname(Thread *thread, ptr address, uint64_t length, ptr name) { 253 | std::printf("sys_mname(%p, %p, '%s')\n", address, (char *)address + length, name); 254 | return {}; 255 | } 256 | orbis::SysResult orbis::sys_dynlib_dlopen(Thread *thread /* TODO */) { 257 | return ErrorCode::NOSYS; 258 | } 259 | orbis::SysResult orbis::sys_dynlib_dlclose(Thread *thread /* TODO */) { 260 | return ErrorCode::NOSYS; 261 | } 262 | orbis::SysResult orbis::sys_dynlib_dlsym(Thread *thread, SceKernelModule handle, 263 | ptr symbol, 264 | ptr> addrp) { 265 | if (thread->tproc->ops->dynlib_dlsym) { 266 | return thread->tproc->ops->dynlib_dlsym(thread, handle, symbol, addrp); 267 | } 268 | 269 | return ErrorCode::NOSYS; 270 | } 271 | orbis::SysResult orbis::sys_dynlib_get_list(Thread *thread, 272 | ptr pArray, 273 | size_t numArray, 274 | ptr pActualNum) { 275 | std::size_t actualNum = 0; 276 | for (auto [id, module] : thread->tproc->modulesMap) { 277 | if (actualNum >= numArray) { 278 | break; 279 | } 280 | 281 | pArray[actualNum++] = id; 282 | } 283 | *pActualNum = actualNum; 284 | return {}; 285 | } 286 | orbis::SysResult orbis::sys_dynlib_get_info(Thread *thread, 287 | SceKernelModule handle, 288 | ptr pInfo) { 289 | auto module = thread->tproc->modulesMap.get(handle); 290 | 291 | if (module == nullptr) { 292 | return ErrorCode::SRCH; 293 | } 294 | 295 | if (pInfo->size != sizeof(ModuleInfo)) { 296 | return ErrorCode::INVAL; 297 | } 298 | 299 | ModuleInfo result = {}; 300 | result.size = sizeof(ModuleInfo); 301 | std::strncpy(result.name, module->moduleName, sizeof(result.name)); 302 | std::memcpy(result.segments, module->segments, 303 | sizeof(ModuleSegment) * module->segmentCount); 304 | result.segmentCount = module->segmentCount; 305 | std::memcpy(result.fingerprint, module->fingerprint, 306 | sizeof(result.fingerprint)); 307 | uwrite(pInfo, result); 308 | return {}; 309 | } 310 | orbis::SysResult 311 | orbis::sys_dynlib_load_prx(Thread *thread, ptr name, uint64_t arg1, ptr pHandle, uint64_t arg3) { 312 | if (auto dynlib_load_prx = thread->tproc->ops->dynlib_load_prx) { 313 | return dynlib_load_prx(thread, name, arg1, pHandle, arg3); 314 | } 315 | 316 | return ErrorCode::NOSYS; 317 | } 318 | orbis::SysResult 319 | orbis::sys_dynlib_unload_prx(Thread *thread, SceKernelModule handle) { 320 | if (auto dynlib_unload_prx = thread->tproc->ops->dynlib_unload_prx) { 321 | return dynlib_unload_prx(thread, handle); 322 | } 323 | 324 | return ErrorCode::NOSYS; 325 | } 326 | orbis::SysResult 327 | orbis::sys_dynlib_do_copy_relocations(Thread *thread) { 328 | if (auto dynlib_do_copy_relocations = thread->tproc->ops->dynlib_do_copy_relocations) { 329 | return dynlib_do_copy_relocations(thread); 330 | } 331 | 332 | return ErrorCode::NOSYS; 333 | } 334 | orbis::SysResult orbis::sys_dynlib_prepare_dlclose(Thread *thread /* TODO */) { 335 | return ErrorCode::NOSYS; 336 | } 337 | 338 | // template using le = T; 339 | 340 | orbis::SysResult orbis::sys_dynlib_get_proc_param(Thread *thread, 341 | ptr> procParam, 342 | ptr procParamSize) { 343 | auto proc = thread->tproc; 344 | *procParam = proc->processParam; 345 | *procParamSize = proc->processParamSize; 346 | return {}; 347 | } 348 | orbis::SysResult orbis::sys_dynlib_process_needed_and_relocate(Thread *thread) { 349 | if (auto processNeeded = thread->tproc->ops->processNeeded) { 350 | auto result = processNeeded(thread); 351 | 352 | if (result.value() != 0) { 353 | return result; 354 | } 355 | } 356 | 357 | for (auto [id, module] : thread->tproc->modulesMap) { 358 | auto result = module->relocate(thread->tproc); 359 | if (result.isError()) { 360 | return result; 361 | } 362 | } 363 | 364 | if (auto registerEhFrames = thread->tproc->ops->registerEhFrames) { 365 | auto result = registerEhFrames(thread); 366 | 367 | if (result.value() != 0) { 368 | return result; 369 | } 370 | } 371 | 372 | return {}; 373 | } 374 | orbis::SysResult orbis::sys_sandbox_path(Thread *thread /* TODO */) { 375 | return ErrorCode::NOSYS; 376 | } 377 | 378 | struct mdbg_property { 379 | orbis::int32_t unk; 380 | orbis::int32_t unk2; 381 | orbis::uint64_t addr_ptr; 382 | orbis::uint64_t areaSize; 383 | orbis::int64_t unk3; 384 | orbis::int64_t unk4; 385 | char name[32]; 386 | }; 387 | 388 | orbis::SysResult orbis::sys_mdbg_service(Thread *thread, uint32_t op, ptr arg0, ptr arg1) { 389 | std::printf("sys_mdbg_service(op = %d, arg0 = %p, arg1 = %p)\n", op, arg0, arg1); 390 | 391 | switch (op) { 392 | case 1: { 393 | auto *prop = (mdbg_property *)arg0; 394 | std::printf( 395 | "sys_mdbg_service set property (name='%s', address=0x%lx, size=%lu)\n", 396 | prop->name, prop->addr_ptr, prop->areaSize); 397 | break; 398 | } 399 | 400 | case 3: { 401 | std::printf("sys_mdbg_service: ERROR CODE: %X\n", (unsigned)reinterpret_cast(arg0)); 402 | break; 403 | } 404 | 405 | case 7: { 406 | std::printf("sys_mdbg_service: %s\n", (char *)arg0); 407 | break; 408 | } 409 | 410 | default: 411 | break; 412 | } 413 | 414 | return{}; 415 | } 416 | orbis::SysResult orbis::sys_randomized_path(Thread *thread /* TODO */) { 417 | std::printf("TODO: sys_randomized_path()\n"); 418 | return ErrorCode::NOSYS; 419 | } 420 | orbis::SysResult orbis::sys_rdup(Thread *thread /* TODO */) { 421 | return ErrorCode::NOSYS; 422 | } 423 | orbis::SysResult orbis::sys_dl_get_metadata(Thread *thread /* TODO */) { 424 | return ErrorCode::NOSYS; 425 | } 426 | orbis::SysResult orbis::sys_workaround8849(Thread *thread /* TODO */) { 427 | return ErrorCode::NOSYS; 428 | } 429 | orbis::SysResult orbis::sys_is_development_mode(Thread *thread /* TODO */) { 430 | return ErrorCode::NOSYS; 431 | } 432 | orbis::SysResult orbis::sys_get_self_auth_info(Thread *thread /* TODO */) { 433 | return ErrorCode::NOSYS; 434 | } 435 | orbis::SysResult 436 | orbis::sys_dynlib_get_info_ex(Thread *thread, SceKernelModule handle, 437 | ptr unk, 438 | ptr destModuleInfoEx) { 439 | auto module = thread->tproc->modulesMap.get(handle); 440 | if (module == nullptr) { 441 | return ErrorCode::SRCH; 442 | } 443 | 444 | if (destModuleInfoEx->size != sizeof(ModuleInfoEx)) { 445 | return ErrorCode::INVAL; 446 | } 447 | 448 | ModuleInfoEx result = {}; 449 | result.size = sizeof(ModuleInfoEx); 450 | std::strncpy(result.name, module->moduleName, sizeof(result.name)); 451 | result.id = std::to_underlying(handle); 452 | result.tlsIndex = module->tlsIndex; 453 | result.tlsInit = module->tlsInit; 454 | result.tlsInitSize = module->tlsInitSize; 455 | result.tlsSize = module->tlsSize; 456 | result.tlsOffset = module->tlsOffset; 457 | result.tlsAlign = module->tlsAlign; 458 | result.initProc = module->initProc; 459 | result.finiProc = module->finiProc; 460 | result.ehFrameHdr = module->ehFrameHdr; 461 | result.ehFrame = module->ehFrame; 462 | result.ehFrameHdrSize = module->ehFrameHdrSize; 463 | result.ehFrameSize = module->ehFrameSize; 464 | std::memcpy(result.segments, module->segments, 465 | sizeof(ModuleSegment) * module->segmentCount); 466 | result.segmentCount = module->segmentCount; 467 | result.refCount = module->references.load(std::memory_order::relaxed); 468 | uwrite(destModuleInfoEx, result); 469 | 470 | return {}; 471 | } 472 | orbis::SysResult orbis::sys_budget_getid(Thread *thread) { 473 | return ErrorCode::NOSYS; 474 | } 475 | orbis::SysResult orbis::sys_budget_get_ptype(Thread *thread, sint budgetId) { 476 | thread->retval[0] = 1; 477 | return {}; 478 | } 479 | orbis::SysResult 480 | orbis::sys_get_paging_stats_of_all_threads(Thread *thread /* TODO */) { 481 | return ErrorCode::NOSYS; 482 | } 483 | orbis::SysResult orbis::sys_get_proc_type_info(Thread *thread, 484 | ptr destProcessInfo) { 485 | std::printf("TODO: sys_get_proc_type_info\n"); 486 | 487 | struct dargs { 488 | uint64_t size = sizeof(dargs); 489 | uint32_t ptype; 490 | uint32_t pflags; 491 | } args = { 492 | .ptype = 1, 493 | .pflags = 0 494 | }; 495 | 496 | uwrite((ptr)destProcessInfo, args); 497 | return{}; 498 | } 499 | orbis::SysResult orbis::sys_get_resident_count(Thread *thread, pid_t pid) { 500 | return ErrorCode::NOSYS; 501 | } 502 | orbis::SysResult orbis::sys_prepare_to_suspend_process(Thread *thread, 503 | pid_t pid) { 504 | return ErrorCode::NOSYS; 505 | } 506 | orbis::SysResult orbis::sys_get_resident_fmem_count(Thread *thread, pid_t pid) { 507 | return ErrorCode::NOSYS; 508 | } 509 | orbis::SysResult orbis::sys_thr_get_name(Thread *thread, lwpid_t lwpid) { 510 | return ErrorCode::NOSYS; 511 | } 512 | orbis::SysResult orbis::sys_set_gpo(Thread *thread /* TODO */) { 513 | return ErrorCode::NOSYS; 514 | } 515 | orbis::SysResult 516 | orbis::sys_get_paging_stats_of_all_objects(Thread *thread /* TODO */) { 517 | return ErrorCode::NOSYS; 518 | } 519 | orbis::SysResult orbis::sys_test_debug_rwmem(Thread *thread /* TODO */) { 520 | return ErrorCode::NOSYS; 521 | } 522 | orbis::SysResult orbis::sys_free_stack(Thread *thread /* TODO */) { 523 | return ErrorCode::NOSYS; 524 | } 525 | orbis::SysResult orbis::sys_suspend_system(Thread *thread /* TODO */) { 526 | return ErrorCode::NOSYS; 527 | } 528 | 529 | enum ImpiOpcode { 530 | kIpmiCreateClient = 2 531 | }; 532 | 533 | struct IpmiCreateClientParams { 534 | orbis::ptr arg0; 535 | orbis::ptr name; 536 | orbis::ptr arg2; 537 | }; 538 | static_assert(sizeof(IpmiCreateClientParams) == 0x18); 539 | 540 | orbis::SysResult orbis::sys_ipmimgr_call(Thread *thread, uint64_t id, uint64_t arg2, ptr result, ptr params, uint64_t paramsSize, uint64_t arg6) { 541 | std::printf("TODO: sys_ipmimgr_call(id = %lld)\n", (unsigned long long)id); 542 | 543 | if (id == kIpmiCreateClient) { 544 | if (paramsSize != sizeof(IpmiCreateClientParams)) { 545 | return ErrorCode::INVAL; 546 | } 547 | 548 | auto createParams = (ptr)params; 549 | 550 | std::printf("ipmi create client(%p, '%s', %p)\n", 551 | (void *)createParams->arg0, 552 | (char *)createParams->name, 553 | (void *)createParams->arg2 554 | ); 555 | 556 | return{}; 557 | } 558 | 559 | if (id == 1131 || id == 1024 || id == 800) { 560 | thread->retval[0] = -0x40004; // HACK 561 | return {}; 562 | // return -0x40004; 563 | } 564 | 565 | if (id == 3) { 566 | if (result) { 567 | *result = 0; 568 | } 569 | return {}; 570 | } 571 | 572 | return {}; 573 | } 574 | orbis::SysResult orbis::sys_get_gpo(Thread *thread /* TODO */) { 575 | return ErrorCode::NOSYS; 576 | } 577 | orbis::SysResult orbis::sys_get_vm_map_timestamp(Thread *thread /* TODO */) { 578 | return ErrorCode::NOSYS; 579 | } 580 | orbis::SysResult orbis::sys_opmc_set_hw(Thread *thread /* TODO */) { 581 | return ErrorCode::NOSYS; 582 | } 583 | orbis::SysResult orbis::sys_opmc_get_hw(Thread *thread /* TODO */) { 584 | return ErrorCode::NOSYS; 585 | } 586 | orbis::SysResult orbis::sys_get_cpu_usage_all(Thread *thread /* TODO */) { 587 | return ErrorCode::NOSYS; 588 | } 589 | orbis::SysResult orbis::sys_mmap_dmem(Thread *thread /* TODO */) { 590 | return ErrorCode::NOSYS; 591 | } 592 | orbis::SysResult orbis::sys_physhm_open(Thread *thread /* TODO */) { 593 | return ErrorCode::NOSYS; 594 | } 595 | orbis::SysResult orbis::sys_physhm_unlink(Thread *thread /* TODO */) { 596 | return ErrorCode::NOSYS; 597 | } 598 | orbis::SysResult orbis::sys_resume_internal_hdd(Thread *thread /* TODO */) { 599 | return ErrorCode::NOSYS; 600 | } 601 | orbis::SysResult orbis::sys_thr_suspend_ucontext(Thread *thread /* TODO */) { 602 | return ErrorCode::NOSYS; 603 | } 604 | orbis::SysResult orbis::sys_thr_resume_ucontext(Thread *thread /* TODO */) { 605 | return ErrorCode::NOSYS; 606 | } 607 | orbis::SysResult orbis::sys_thr_get_ucontext(Thread *thread /* TODO */) { 608 | return ErrorCode::NOSYS; 609 | } 610 | orbis::SysResult orbis::sys_thr_set_ucontext(Thread *thread /* TODO */) { 611 | return ErrorCode::NOSYS; 612 | } 613 | orbis::SysResult orbis::sys_set_timezone_info(Thread *thread /* TODO */) { 614 | return ErrorCode::NOSYS; 615 | } 616 | orbis::SysResult orbis::sys_set_phys_fmem_limit(Thread *thread /* TODO */) { 617 | return ErrorCode::NOSYS; 618 | } 619 | orbis::SysResult orbis::sys_utc_to_localtime(Thread *thread /* TODO */) { 620 | return ErrorCode::NOSYS; 621 | } 622 | orbis::SysResult orbis::sys_localtime_to_utc(Thread *thread /* TODO */) { 623 | return ErrorCode::NOSYS; 624 | } 625 | orbis::SysResult orbis::sys_set_uevt(Thread *thread /* TODO */) { 626 | return ErrorCode::NOSYS; 627 | } 628 | orbis::SysResult orbis::sys_get_cpu_usage_proc(Thread *thread /* TODO */) { 629 | return ErrorCode::NOSYS; 630 | } 631 | orbis::SysResult orbis::sys_get_map_statistics(Thread *thread /* TODO */) { 632 | return ErrorCode::NOSYS; 633 | } 634 | orbis::SysResult orbis::sys_set_chicken_switches(Thread *thread /* TODO */) { 635 | return ErrorCode::NOSYS; 636 | } 637 | orbis::SysResult orbis::sys_extend_page_table_pool(Thread *thread) { 638 | return ErrorCode::NOSYS; 639 | } 640 | orbis::SysResult orbis::sys_extend_page_table_pool2(Thread *thread) { 641 | return ErrorCode::NOSYS; 642 | } 643 | orbis::SysResult 644 | orbis::sys_get_kernel_mem_statistics(Thread *thread /* TODO */) { 645 | return ErrorCode::NOSYS; 646 | } 647 | orbis::SysResult 648 | orbis::sys_get_sdk_compiled_version(Thread *thread /* TODO */) { 649 | return ErrorCode::NOSYS; 650 | } 651 | orbis::SysResult orbis::sys_app_state_change(Thread *thread /* TODO */) { 652 | return ErrorCode::NOSYS; 653 | } 654 | orbis::SysResult orbis::sys_dynlib_get_obj_member(Thread *thread, SceKernelModule handle, uint64_t index, ptr> addrp) { 655 | if (auto dynlib_get_obj_member = thread->tproc->ops->dynlib_get_obj_member) { 656 | return dynlib_get_obj_member(thread, handle, index, addrp); 657 | } 658 | 659 | return ErrorCode::NOSYS; 660 | } 661 | orbis::SysResult 662 | orbis::sys_budget_get_ptype_of_budget(Thread *thread /* TODO */) { 663 | return ErrorCode::NOSYS; 664 | } 665 | orbis::SysResult 666 | orbis::sys_prepare_to_resume_process(Thread *thread /* TODO */) { 667 | return ErrorCode::NOSYS; 668 | } 669 | orbis::SysResult orbis::sys_process_terminate(Thread *thread /* TODO */) { 670 | return ErrorCode::NOSYS; 671 | } 672 | orbis::SysResult orbis::sys_blockpool_open(Thread *thread /* TODO */) { 673 | return ErrorCode::NOSYS; 674 | } 675 | orbis::SysResult orbis::sys_blockpool_map(Thread *thread /* TODO */) { 676 | return ErrorCode::NOSYS; 677 | } 678 | orbis::SysResult orbis::sys_blockpool_unmap(Thread *thread /* TODO */) { 679 | return ErrorCode::NOSYS; 680 | } 681 | orbis::SysResult 682 | orbis::sys_dynlib_get_info_for_libdbg(Thread *thread /* TODO */) { 683 | return ErrorCode::NOSYS; 684 | } 685 | orbis::SysResult orbis::sys_blockpool_batch(Thread *thread /* TODO */) { 686 | return ErrorCode::NOSYS; 687 | } 688 | orbis::SysResult orbis::sys_fdatasync(Thread *thread /* TODO */) { 689 | return ErrorCode::NOSYS; 690 | } 691 | orbis::SysResult orbis::sys_dynlib_get_list2(Thread *thread /* TODO */) { 692 | return ErrorCode::NOSYS; 693 | } 694 | orbis::SysResult orbis::sys_dynlib_get_info2(Thread *thread /* TODO */) { 695 | return ErrorCode::NOSYS; 696 | } 697 | orbis::SysResult orbis::sys_aio_submit(Thread *thread /* TODO */) { 698 | return ErrorCode::NOSYS; 699 | } 700 | orbis::SysResult orbis::sys_aio_multi_delete(Thread *thread /* TODO */) { 701 | return ErrorCode::NOSYS; 702 | } 703 | orbis::SysResult orbis::sys_aio_multi_wait(Thread *thread /* TODO */) { 704 | return ErrorCode::NOSYS; 705 | } 706 | orbis::SysResult orbis::sys_aio_multi_poll(Thread *thread /* TODO */) { 707 | return ErrorCode::NOSYS; 708 | } 709 | orbis::SysResult orbis::sys_aio_get_data(Thread *thread /* TODO */) { 710 | return ErrorCode::NOSYS; 711 | } 712 | orbis::SysResult orbis::sys_aio_multi_cancel(Thread *thread /* TODO */) { 713 | return ErrorCode::NOSYS; 714 | } 715 | orbis::SysResult orbis::sys_get_bio_usage_all(Thread *thread /* TODO */) { 716 | return ErrorCode::NOSYS; 717 | } 718 | orbis::SysResult orbis::sys_aio_create(Thread *thread /* TODO */) { 719 | return ErrorCode::NOSYS; 720 | } 721 | orbis::SysResult orbis::sys_aio_submit_cmd(Thread *thread /* TODO */) { 722 | return ErrorCode::NOSYS; 723 | } 724 | orbis::SysResult orbis::sys_aio_init(Thread *thread /* TODO */) { 725 | return ErrorCode::NOSYS; 726 | } 727 | orbis::SysResult orbis::sys_get_page_table_stats(Thread *thread /* TODO */) { 728 | return ErrorCode::NOSYS; 729 | } 730 | orbis::SysResult 731 | orbis::sys_dynlib_get_list_for_libdbg(Thread *thread /* TODO */) { 732 | return ErrorCode::NOSYS; 733 | } 734 | orbis::SysResult orbis::sys_blockpool_move(Thread *thread /* TODO */) { 735 | return ErrorCode::NOSYS; 736 | } 737 | orbis::SysResult orbis::sys_virtual_query_all(Thread *thread /* TODO */) { 738 | return ErrorCode::NOSYS; 739 | } 740 | orbis::SysResult orbis::sys_reserve_2mb_page(Thread *thread /* TODO */) { 741 | return ErrorCode::NOSYS; 742 | } 743 | orbis::SysResult orbis::sys_cpumode_yield(Thread *thread /* TODO */) { 744 | return ErrorCode::NOSYS; 745 | } 746 | orbis::SysResult orbis::sys_wait6(Thread *thread /* TODO */) { 747 | return ErrorCode::NOSYS; 748 | } 749 | orbis::SysResult orbis::sys_cap_rights_limit(Thread *thread /* TODO */) { 750 | return ErrorCode::NOSYS; 751 | } 752 | orbis::SysResult orbis::sys_cap_ioctls_limit(Thread *thread /* TODO */) { 753 | return ErrorCode::NOSYS; 754 | } 755 | orbis::SysResult orbis::sys_cap_ioctls_get(Thread *thread /* TODO */) { 756 | return ErrorCode::NOSYS; 757 | } 758 | orbis::SysResult orbis::sys_cap_fcntls_limit(Thread *thread /* TODO */) { 759 | return ErrorCode::NOSYS; 760 | } 761 | orbis::SysResult orbis::sys_cap_fcntls_get(Thread *thread /* TODO */) { 762 | return ErrorCode::NOSYS; 763 | } 764 | orbis::SysResult orbis::sys_bindat(Thread *thread /* TODO */) { 765 | return ErrorCode::NOSYS; 766 | } 767 | orbis::SysResult orbis::sys_connectat(Thread *thread /* TODO */) { 768 | return ErrorCode::NOSYS; 769 | } 770 | orbis::SysResult orbis::sys_chflagsat(Thread *thread /* TODO */) { 771 | return ErrorCode::NOSYS; 772 | } 773 | orbis::SysResult orbis::sys_accept4(Thread *thread /* TODO */) { 774 | return ErrorCode::NOSYS; 775 | } 776 | orbis::SysResult orbis::sys_pipe2(Thread *thread /* TODO */) { 777 | return ErrorCode::NOSYS; 778 | } 779 | orbis::SysResult orbis::sys_aio_mlock(Thread *thread /* TODO */) { 780 | return ErrorCode::NOSYS; 781 | } 782 | orbis::SysResult orbis::sys_procctl(Thread *thread /* TODO */) { 783 | return ErrorCode::NOSYS; 784 | } 785 | orbis::SysResult orbis::sys_ppoll(Thread *thread /* TODO */) { 786 | return ErrorCode::NOSYS; 787 | } 788 | orbis::SysResult orbis::sys_futimens(Thread *thread /* TODO */) { 789 | return ErrorCode::NOSYS; 790 | } 791 | orbis::SysResult orbis::sys_utimensat(Thread *thread /* TODO */) { 792 | return ErrorCode::NOSYS; 793 | } 794 | orbis::SysResult orbis::sys_numa_getaffinity(Thread *thread /* TODO */) { 795 | return ErrorCode::NOSYS; 796 | } 797 | orbis::SysResult orbis::sys_numa_setaffinity(Thread *thread /* TODO */) { 798 | return ErrorCode::NOSYS; 799 | } 800 | orbis::SysResult orbis::sys_apr_submit(Thread *thread /* TODO */) { 801 | return ErrorCode::NOSYS; 802 | } 803 | orbis::SysResult orbis::sys_apr_resolve(Thread *thread /* TODO */) { 804 | return ErrorCode::NOSYS; 805 | } 806 | orbis::SysResult orbis::sys_apr_stat(Thread *thread /* TODO */) { 807 | return ErrorCode::NOSYS; 808 | } 809 | orbis::SysResult orbis::sys_apr_wait(Thread *thread /* TODO */) { 810 | return ErrorCode::NOSYS; 811 | } 812 | orbis::SysResult orbis::sys_apr_ctrl(Thread *thread /* TODO */) { 813 | return ErrorCode::NOSYS; 814 | } 815 | orbis::SysResult orbis::sys_get_phys_page_size(Thread *thread /* TODO */) { 816 | return ErrorCode::NOSYS; 817 | } 818 | orbis::SysResult orbis::sys_begin_app_mount(Thread *thread /* TODO */) { 819 | return ErrorCode::NOSYS; 820 | } 821 | orbis::SysResult orbis::sys_end_app_mount(Thread *thread /* TODO */) { 822 | return ErrorCode::NOSYS; 823 | } 824 | orbis::SysResult orbis::sys_fsc2h_ctrl(Thread *thread /* TODO */) { 825 | return ErrorCode::NOSYS; 826 | } 827 | orbis::SysResult orbis::sys_streamwrite(Thread *thread /* TODO */) { 828 | return ErrorCode::NOSYS; 829 | } 830 | orbis::SysResult orbis::sys_app_save(Thread *thread /* TODO */) { 831 | return ErrorCode::NOSYS; 832 | } 833 | orbis::SysResult orbis::sys_app_restore(Thread *thread /* TODO */) { 834 | return ErrorCode::NOSYS; 835 | } 836 | orbis::SysResult orbis::sys_saved_app_delete(Thread *thread /* TODO */) { 837 | return ErrorCode::NOSYS; 838 | } 839 | orbis::SysResult 840 | orbis::sys_get_ppr_sdk_compiled_version(Thread *thread /* TODO */) { 841 | return ErrorCode::NOSYS; 842 | } 843 | orbis::SysResult orbis::sys_notify_app_event(Thread *thread /* TODO */) { 844 | return ErrorCode::NOSYS; 845 | } 846 | orbis::SysResult orbis::sys_ioreq(Thread *thread /* TODO */) { 847 | return ErrorCode::NOSYS; 848 | } 849 | orbis::SysResult orbis::sys_openintr(Thread *thread /* TODO */) { 850 | return ErrorCode::NOSYS; 851 | } 852 | orbis::SysResult orbis::sys_dl_get_info_2(Thread *thread /* TODO */) { 853 | return ErrorCode::NOSYS; 854 | } 855 | orbis::SysResult orbis::sys_acinfo_add(Thread *thread /* TODO */) { 856 | return ErrorCode::NOSYS; 857 | } 858 | orbis::SysResult orbis::sys_acinfo_delete(Thread *thread /* TODO */) { 859 | return ErrorCode::NOSYS; 860 | } 861 | orbis::SysResult 862 | orbis::sys_acinfo_get_all_for_coredump(Thread *thread /* TODO */) { 863 | return ErrorCode::NOSYS; 864 | } 865 | orbis::SysResult orbis::sys_ampr_ctrl_debug(Thread *thread /* TODO */) { 866 | return ErrorCode::NOSYS; 867 | } 868 | orbis::SysResult orbis::sys_workspace_ctrl(Thread *thread /* TODO */) { 869 | return ErrorCode::NOSYS; 870 | } 871 | -------------------------------------------------------------------------------- /src/sys/sys_sem.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys___semctl(Thread *thread, sint semid, sint semnum, sint cmd, ptr arg) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_semget(Thread *thread, key_t key, sint nsems, sint semflg) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys_semop(Thread *thread, sint semid, ptr sops, size_t nspos) { return ErrorCode::NOSYS; } 6 | orbis::SysResult orbis::sys_semsys(Thread *thread, sint which, sint a2, sint a3, sint a4, sint a5) { return ErrorCode::NOSYS; } 7 | -------------------------------------------------------------------------------- /src/sys/sys_shm.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_shmdt(Thread *thread, ptr shmaddr) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_shmat(Thread *thread, sint shmid, ptr shmaddr, sint shmflg) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys_shmctl(Thread *thread, sint shmid, sint cmd, ptr buf) { return ErrorCode::NOSYS; } 6 | orbis::SysResult orbis::sys_shmget(Thread *thread, key_t key, size_t size, sint shmflg) { return ErrorCode::NOSYS; } 7 | orbis::SysResult orbis::sys_shmsys(Thread *thread, sint which, sint a2, sint a3, sint a4) { return ErrorCode::NOSYS; } 8 | -------------------------------------------------------------------------------- /src/sys/sys_shutdown.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_reboot(Thread *thread, sint opt) { return ErrorCode::NOSYS; } 4 | -------------------------------------------------------------------------------- /src/sys/sys_sig.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_sigaction(Thread *thread, sint sig, ptr act, ptr oact) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_sigprocmask(Thread *thread, sint how, ptr set, ptr oset) { 5 | if (oset) { 6 | for (std::size_t i = 0; i < 2; ++i) { 7 | oset[i] = thread->sigMask[i]; 8 | } 9 | } 10 | 11 | if (set) { 12 | switch (how) { 13 | case 0: // unblock 14 | for (std::size_t i = 0; i < 2; ++i) { 15 | thread->sigMask[i] &= ~set[i]; 16 | } 17 | case 1: // block 18 | for (std::size_t i = 0; i < 2; ++i) { 19 | thread->sigMask[i] |= set[i]; 20 | } 21 | break; 22 | case 3: // set 23 | for (std::size_t i = 0; i < 2; ++i) { 24 | thread->sigMask[i] = set[i]; 25 | } 26 | break; 27 | 28 | default: 29 | return ErrorCode::INVAL; 30 | } 31 | } 32 | return {}; 33 | } 34 | orbis::SysResult orbis::sys_sigwait(Thread *thread, ptr set, ptr sig) { return ErrorCode::NOSYS; } 35 | orbis::SysResult orbis::sys_sigtimedwait(Thread *thread, ptr set, ptr info, ptr timeout) { return ErrorCode::NOSYS; } 36 | orbis::SysResult orbis::sys_sigwaitinfo(Thread *thread, ptr set, ptr info) { return ErrorCode::NOSYS; } 37 | orbis::SysResult orbis::sys_sigpending(Thread *thread, ptr set) { return ErrorCode::NOSYS; } 38 | orbis::SysResult orbis::sys_sigsuspend(Thread *thread, ptr set) { return ErrorCode::NOSYS; } 39 | orbis::SysResult orbis::sys_sigaltstack(Thread *thread, ptr ss, ptr oss) { return ErrorCode::NOSYS; } 40 | orbis::SysResult orbis::sys_kill(Thread *thread, sint pid, sint signum) { return ErrorCode::NOSYS; } 41 | orbis::SysResult orbis::sys_pdkill(Thread *thread, sint fd, sint signum) { return ErrorCode::NOSYS; } 42 | orbis::SysResult orbis::sys_sigqueue(Thread *thread, pid_t pid, sint signum, ptr value) { return ErrorCode::NOSYS; } 43 | orbis::SysResult orbis::sys_sigreturn(Thread *thread, ptr sigcntxp) { return ErrorCode::NOSYS; } 44 | orbis::SysResult orbis::nosys(Thread *thread) { return ErrorCode::NOSYS; } 45 | -------------------------------------------------------------------------------- /src/sys/sys_subr_prof.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_profil(Thread *thread, caddr_t samples, size_t size, size_t offset, uint scale) { return ErrorCode::NOSYS; } 4 | -------------------------------------------------------------------------------- /src/sys/sys_swap_pager.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_swapon(Thread *thread, ptr name) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_swapoff(Thread *thread, ptr name) { return ErrorCode::NOSYS; } 5 | -------------------------------------------------------------------------------- /src/sys/sys_synch.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_yield(Thread *thread) { return ErrorCode::NOSYS; } 4 | -------------------------------------------------------------------------------- /src/sys/sys_sysctl.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr name, 4 | uint namelen, ptr old, 5 | ptr oldlenp, ptr new_, 6 | size_t newlen) { 7 | enum sysctl_ctl { unspec, kern, vm, vfs, net, debug, hw, machdep, user }; 8 | 9 | // machdep.tsc_freq 10 | 11 | enum sysctl_kern { 12 | usrstack = 33, 13 | kern_14 = 14, 14 | kern_37 = 37, 15 | 16 | // FIXME 17 | smp_cpus = 1000, 18 | sdk_version, 19 | sched_cpusetsize, 20 | proc_ptc, 21 | 22 | }; 23 | 24 | enum sysctl_hw { 25 | pagesize = 7, 26 | }; 27 | 28 | enum sysctl_machdep { 29 | // FIXME 30 | tsc_freq = 1000 31 | }; 32 | 33 | // for (unsigned int i = 0; i < namelen; ++i) { 34 | // std::printf(" name[%u] = %u\n", i, name[i]); 35 | // } 36 | 37 | if (namelen == 3) { 38 | // 1 - 14 - 41 - debug flags? 39 | 40 | if (name[0] == 1 && name[1] == 14 && name[2] == 41) { 41 | // std::printf(" kern.14.41\n"); 42 | 43 | if (*oldlenp != 4 || new_ != nullptr || newlen != 0) { 44 | return ErrorCode::INVAL; 45 | } 46 | 47 | *(uint32_t *)old = 0; 48 | return {}; 49 | } 50 | } 51 | 52 | if (namelen == 4) { 53 | // 1 - 14 - 35 - 2 54 | 55 | // sceKernelGetAppInfo 56 | struct app_info { 57 | char unk[72]; 58 | }; 59 | 60 | if (name[0] == 1 && name[1] == 14 && name[2] == 35) { 61 | // std::printf(" kern.14.35.%u\n", name[3]); 62 | memset(old, 0, sizeof(app_info)); 63 | return {}; 64 | } 65 | } 66 | 67 | if (namelen == 2) { 68 | switch (name[0]) { 69 | case sysctl_ctl::unspec: { 70 | switch (name[1]) { 71 | case 3: { 72 | std::printf(" unspec - get name of '%s'\n", 73 | std::string((char *)new_, newlen).c_str()); 74 | auto searchName = std::string_view((char *)new_, newlen); 75 | auto *dest = (std::uint32_t *)old; 76 | std::uint32_t count = 0; 77 | 78 | if (searchName == "kern.smp.cpus") { 79 | if (*oldlenp < 2 * sizeof(uint32_t)) { 80 | return ErrorCode::INVAL; 81 | } 82 | 83 | dest[count++] = kern; 84 | dest[count++] = smp_cpus; 85 | } else if (searchName == "machdep.tsc_freq") { 86 | if (*oldlenp < 2 * sizeof(uint32_t)) { 87 | return ErrorCode::INVAL; 88 | } 89 | 90 | dest[count++] = machdep; 91 | dest[count++] = tsc_freq; 92 | } else if (searchName == "kern.sdk_version") { 93 | if (*oldlenp < 2 * sizeof(uint32_t)) { 94 | return ErrorCode::INVAL; 95 | } 96 | 97 | dest[count++] = kern; 98 | dest[count++] = sdk_version; 99 | } else if (searchName == "kern.sched.cpusetsize") { 100 | if (*oldlenp < 2 * sizeof(uint32_t)) { 101 | return ErrorCode::INVAL; 102 | } 103 | 104 | dest[count++] = kern; 105 | dest[count++] = sched_cpusetsize; 106 | } else if (searchName == "kern.proc.ptc") { 107 | if (*oldlenp < 2 * sizeof(uint32_t)) { 108 | std::printf(" kern.proc.ptc error\n"); 109 | return ErrorCode::INVAL; 110 | } 111 | 112 | dest[count++] = kern; 113 | dest[count++] = proc_ptc; 114 | } 115 | 116 | if (count == 0) { 117 | return ErrorCode::SRCH; 118 | } 119 | 120 | *oldlenp = count * sizeof(uint32_t); 121 | return {}; 122 | } 123 | 124 | default: 125 | break; 126 | } 127 | std::printf(" unspec_%u\n", name[1]); 128 | return {}; 129 | } 130 | 131 | case sysctl_ctl::kern: 132 | switch (name[1]) { 133 | case sysctl_kern::usrstack: { 134 | if (*oldlenp != 8 || new_ != nullptr || newlen != 0) { 135 | return ErrorCode::INVAL; 136 | } 137 | 138 | std::printf("Reporting stack at %p\n", thread->stackEnd); 139 | *(ptr *)old = thread->stackEnd; 140 | return {}; 141 | } 142 | 143 | case sysctl_kern::smp_cpus: 144 | if (*oldlenp != 4 || new_ != nullptr || newlen != 0) { 145 | return ErrorCode::INVAL; 146 | } 147 | 148 | *(uint32_t *)old = 1; 149 | break; 150 | 151 | case sysctl_kern::sdk_version: { 152 | if (*oldlenp != 4 || new_ != nullptr || newlen != 0) { 153 | return ErrorCode::INVAL; 154 | } 155 | 156 | auto processParam = 157 | reinterpret_cast(thread->tproc->processParam); 158 | 159 | auto sdkVersion = processParam // 160 | + sizeof(uint64_t) // size 161 | + sizeof(uint32_t) // magic 162 | + sizeof(uint32_t); // entryCount 163 | 164 | std::printf("Reporting SDK version %x\n", 165 | *reinterpret_cast(sdkVersion)); 166 | *(uint32_t *)old = *reinterpret_cast(sdkVersion); 167 | break; 168 | } 169 | 170 | case sysctl_kern::sched_cpusetsize: 171 | if (*oldlenp != 4 || new_ != nullptr || newlen != 0) { 172 | return ErrorCode::INVAL; 173 | } 174 | 175 | *(std::uint32_t *)old = 4; 176 | break; 177 | 178 | case sysctl_kern::kern_37: { 179 | struct kern37_value { 180 | std::uint64_t size; 181 | std::uint64_t unk[7]; 182 | }; 183 | 184 | if (*oldlenp != sizeof(kern37_value) || new_ != nullptr || 185 | newlen != 0) { 186 | return ErrorCode::INVAL; 187 | } 188 | 189 | auto value = (kern37_value *)old; 190 | value->size = sizeof(kern37_value); 191 | break; 192 | } 193 | 194 | case sysctl_kern::proc_ptc: { 195 | if (*oldlenp != 8 || new_ != nullptr || newlen != 0) { 196 | return ErrorCode::INVAL; 197 | } 198 | 199 | *(std::uint64_t *)old = 1357; 200 | } 201 | 202 | default: 203 | return ErrorCode::INVAL; 204 | } 205 | break; 206 | 207 | case sysctl_ctl::vm: 208 | case sysctl_ctl::vfs: 209 | case sysctl_ctl::net: 210 | case sysctl_ctl::debug: 211 | return ErrorCode::INVAL; 212 | 213 | case sysctl_ctl::hw: 214 | switch (name[1]) { 215 | case sysctl_hw::pagesize: 216 | if (*oldlenp != 4 || new_ != nullptr || newlen != 0) { 217 | return ErrorCode::INVAL; 218 | } 219 | 220 | *(uint32_t *)old = 0x4000; 221 | break; 222 | 223 | default: 224 | break; 225 | } 226 | break; 227 | 228 | case sysctl_ctl::machdep: 229 | switch (name[1]) { 230 | case sysctl_machdep::tsc_freq: { 231 | if (*oldlenp != 8 || new_ != nullptr || newlen != 0) { 232 | return ErrorCode::INVAL; 233 | } 234 | 235 | *(uint64_t *)old = 1000000000ull; 236 | return {}; 237 | 238 | default: 239 | return ErrorCode::INVAL; 240 | } 241 | } 242 | case sysctl_ctl::user: 243 | return ErrorCode::INVAL; 244 | } 245 | } 246 | 247 | return {}; 248 | } 249 | -------------------------------------------------------------------------------- /src/sys/sys_thr.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_thr_create(Thread *thread, ptr ctxt, ptr arg, sint flags) { 4 | if (auto thr_create = thread->tproc->ops->thr_create) { 5 | return thr_create(thread, ctxt, arg, flags); 6 | } 7 | 8 | return ErrorCode::NOSYS; 9 | } 10 | 11 | orbis::SysResult orbis::sys_thr_new(Thread *thread, ptr param, sint param_size) { 12 | if (auto thr_new = thread->tproc->ops->thr_new) { 13 | return thr_new(thread, param, param_size); 14 | } 15 | 16 | return ErrorCode::NOSYS; 17 | } 18 | 19 | orbis::SysResult orbis::sys_thr_self(Thread *thread, ptr id) { 20 | uwrite(id, (slong)thread->tid); 21 | return {}; 22 | } 23 | 24 | orbis::SysResult orbis::sys_thr_exit(Thread *thread, ptr state) { 25 | if (auto thr_exit = thread->tproc->ops->thr_exit) { 26 | return thr_exit(thread, state); 27 | } 28 | return ErrorCode::NOSYS; 29 | } 30 | 31 | orbis::SysResult orbis::sys_thr_kill(Thread *thread, slong id, sint sig) { 32 | if (auto thr_kill = thread->tproc->ops->thr_kill) { 33 | return thr_kill(thread, id, sig); 34 | } 35 | 36 | return ErrorCode::NOSYS; 37 | } 38 | 39 | orbis::SysResult orbis::sys_thr_kill2(Thread *thread, pid_t pid, slong id, sint sig) { 40 | if (auto thr_kill2 = thread->tproc->ops->thr_kill2) { 41 | return thr_kill2(thread, pid, id, sig); 42 | } 43 | 44 | return ErrorCode::NOSYS; 45 | } 46 | 47 | orbis::SysResult orbis::sys_thr_suspend(Thread *thread, ptr timeout) { 48 | if (auto thr_suspend = thread->tproc->ops->thr_suspend) { 49 | return thr_suspend(thread, timeout); 50 | } 51 | 52 | return ErrorCode::NOSYS; 53 | } 54 | 55 | orbis::SysResult orbis::sys_thr_wake(Thread *thread, slong id) { 56 | if (auto thr_wake = thread->tproc->ops->thr_wake) { 57 | return thr_wake(thread, id); 58 | } 59 | 60 | return ErrorCode::NOSYS; 61 | } 62 | 63 | orbis::SysResult orbis::sys_thr_set_name(Thread *thread, slong id, ptr name) { 64 | if (auto thr_set_name = thread->tproc->ops->thr_set_name) { 65 | return thr_set_name(thread, id, name); 66 | } 67 | 68 | return ErrorCode::NOSYS; 69 | } 70 | -------------------------------------------------------------------------------- /src/sys/sys_time.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_clock_gettime(Thread *thread, clockid_t clock_id, ptr tp) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_clock_settime(Thread *thread, clockid_t clock_id, ptr tp) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys_clock_getres(Thread *thread, clockid_t clock_id, ptr tp) { return ErrorCode::NOSYS; } 6 | orbis::SysResult orbis::sys_nanosleep(Thread *thread, ptr rqtp, ptr rmtp) { return ErrorCode::NOSYS; } 7 | orbis::SysResult orbis::sys_gettimeofday(Thread *thread, ptr tp, ptr tzp) { return ErrorCode::NOSYS; } 8 | orbis::SysResult orbis::sys_settimeofday(Thread *thread, ptr tp, ptr tzp) { return ErrorCode::NOSYS; } 9 | orbis::SysResult orbis::sys_getitimer(Thread *thread, uint which, ptr itv) { return ErrorCode::NOSYS; } 10 | orbis::SysResult orbis::sys_setitimer(Thread *thread, uint which, ptr itv, ptr oitv) { return ErrorCode::NOSYS; } 11 | orbis::SysResult orbis::sys_ktimer_create(Thread *thread, clockid_t clock_id, ptr evp, ptr timerid) { return ErrorCode::NOSYS; } 12 | orbis::SysResult orbis::sys_ktimer_delete(Thread *thread, sint timerid) { return ErrorCode::NOSYS; } 13 | orbis::SysResult orbis::sys_ktimer_settime(Thread *thread, sint timerid, sint flags, ptr value, ptr ovalue) { return ErrorCode::NOSYS; } 14 | orbis::SysResult orbis::sys_ktimer_gettime(Thread *thread, sint timerid, ptr value) { return ErrorCode::NOSYS; } 15 | orbis::SysResult orbis::sys_ktimer_getoverrun(Thread *thread, sint timerid) { return ErrorCode::NOSYS; } 16 | -------------------------------------------------------------------------------- /src/sys/sys_uipc.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_socket(Thread *thread, sint domain, sint type, sint protocol) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_bind(Thread *thread, sint s, caddr_t name, sint namelen) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys_listen(Thread *thread, sint s, sint backlog) { return ErrorCode::NOSYS; } 6 | orbis::SysResult orbis::sys_accept(Thread *thread, sint s, ptr from, ptr fromlenaddr) { return ErrorCode::NOSYS; } 7 | orbis::SysResult orbis::sys_connect(Thread *thread, sint s, caddr_t name, sint namelen) { return ErrorCode::NOSYS; } 8 | orbis::SysResult orbis::sys_socketpair(Thread *thread, sint domain, sint type, sint protocol, ptr rsv) { return ErrorCode::NOSYS; } 9 | orbis::SysResult orbis::sys_sendto(Thread *thread, sint s, caddr_t buf, size_t len, sint flags, caddr_t to, sint tolen) { return ErrorCode::NOSYS; } 10 | orbis::SysResult orbis::sys_sendmsg(Thread *thread, sint s, ptr msg, sint flags) { return ErrorCode::NOSYS; } 11 | orbis::SysResult orbis::sys_recvfrom(Thread *thread, sint s, caddr_t buf, size_t len, sint flags, ptr from, ptr fromlenaddr) { return ErrorCode::NOSYS; } 12 | orbis::SysResult orbis::sys_recvmsg(Thread *thread, sint s, ptr msg, sint flags) { return ErrorCode::NOSYS; } 13 | orbis::SysResult orbis::sys_shutdown(Thread *thread, sint s, sint how) { return ErrorCode::NOSYS; } 14 | orbis::SysResult orbis::sys_setsockopt(Thread *thread, sint s, sint level, sint name, caddr_t val, sint valsize) { return ErrorCode::NOSYS; } 15 | orbis::SysResult orbis::sys_getsockopt(Thread *thread, sint s, sint level, sint name, caddr_t val, ptr avalsize) { return ErrorCode::NOSYS; } 16 | orbis::SysResult orbis::sys_getsockname(Thread *thread, sint fdes, ptr asa, ptr alen) { return ErrorCode::NOSYS; } 17 | orbis::SysResult orbis::sys_getpeername(Thread *thread, sint fdes, ptr asa, ptr alen) { return ErrorCode::NOSYS; } 18 | orbis::SysResult orbis::sys_sendfile(Thread *thread, sint fd, sint s, off_t offset, size_t nbytes, ptr hdtr, ptr sbytes, sint flags) { return ErrorCode::NOSYS; } 19 | orbis::SysResult orbis::sys_sctp_peeloff(Thread *thread, sint sd, uint32_t name) { return ErrorCode::NOSYS; } 20 | orbis::SysResult orbis::sys_sctp_generic_sendmsg(Thread *thread, sint sd, caddr_t msg, sint mlen, caddr_t to, __socklen_t tolen, ptr sinfo, sint flags) { return ErrorCode::NOSYS; } 21 | orbis::SysResult orbis::sys_sctp_generic_sendmsg_iov(Thread *thread, sint sd, ptr iov, sint iovlen, caddr_t to, __socklen_t tolen, ptr sinfo, sint flags) { return ErrorCode::NOSYS; } 22 | orbis::SysResult orbis::sys_sctp_generic_recvmsg(Thread *thread, sint sd, ptr iov, sint iovlen, caddr_t from, __socklen_t fromlen, ptr sinfo, sint flags) { return ErrorCode::NOSYS; } 23 | -------------------------------------------------------------------------------- /src/sys/sys_uipc_mqueue.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_kmq_open(Thread *thread, ptr path, sint flags, mode_t mode, ptr attr) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_kmq_unlink(Thread *thread, ptr path) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys_kmq_setattr(Thread *thread, sint mqd, ptr attr, ptr oattr) { return ErrorCode::NOSYS; } 6 | orbis::SysResult orbis::sys_kmq_timedreceive(Thread *thread, sint mqd, ptr msg_ptr, size_t msg_len, ptr msg_prio, ptr abstimeout) { return ErrorCode::NOSYS; } 7 | orbis::SysResult orbis::sys_kmq_timedsend(Thread *thread, sint mqd, ptr msg_ptr, size_t msg_len, ptr msg_prio, ptr abstimeout) { return ErrorCode::NOSYS; } 8 | orbis::SysResult orbis::sys_kmq_notify(Thread *thread, sint mqd, ptr sigev) { return ErrorCode::NOSYS; } 9 | -------------------------------------------------------------------------------- /src/sys/sys_uipc_sem.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_ksem_init(Thread *thread, ptr idp, uint value) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_ksem_open(Thread *thread, ptr idp, ptr name, sint oflag, mode_t mode, uint value) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys_ksem_unlink(Thread *thread, ptr name) { return ErrorCode::NOSYS; } 6 | orbis::SysResult orbis::sys_ksem_close(Thread *thread, semid_t id) { return ErrorCode::NOSYS; } 7 | orbis::SysResult orbis::sys_ksem_post(Thread *thread, semid_t id) { return ErrorCode::NOSYS; } 8 | orbis::SysResult orbis::sys_ksem_wait(Thread *thread, semid_t id) { return ErrorCode::NOSYS; } 9 | orbis::SysResult orbis::sys_ksem_timedwait(Thread *thread, semid_t id, ptr abstime) { return ErrorCode::NOSYS; } 10 | orbis::SysResult orbis::sys_ksem_trywait(Thread *thread, semid_t id) { return ErrorCode::NOSYS; } 11 | orbis::SysResult orbis::sys_ksem_getvalue(Thread *thread, semid_t id, ptr value) { return ErrorCode::NOSYS; } 12 | orbis::SysResult orbis::sys_ksem_destroy(Thread *thread, semid_t id) { return ErrorCode::NOSYS; } 13 | -------------------------------------------------------------------------------- /src/sys/sys_uipc_shm.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_shm_open(Thread *thread, ptr path, sint flags, mode_t mode) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_shm_unlink(Thread *thread, ptr path) { return ErrorCode::NOSYS; } 5 | -------------------------------------------------------------------------------- /src/sys/sys_umtx.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys__umtx_lock(Thread *thread, ptr umtx) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys__umtx_unlock(Thread *thread, ptr umtx) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys__umtx_op(Thread *thread, ptr obj, sint op, ulong val, ptr uaddr1, ptr uaddr2) { 6 | std::printf("TODO: sys__umtx_op\n"); 7 | return {}; 8 | } 9 | -------------------------------------------------------------------------------- /src/sys/sys_uuid.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_uuidgen(Thread *thread, ptr store, sint count) { return ErrorCode::NOSYS; } 4 | -------------------------------------------------------------------------------- /src/sys/sys_vfs.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | #include "utils/Logs.hpp" 3 | 4 | orbis::SysResult orbis::sys_sync(Thread *thread) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys_quotactl(Thread *thread, ptr path, sint cmd, sint uid, caddr_t arg) { return ErrorCode::NOSYS; } 6 | orbis::SysResult orbis::sys_statfs(Thread *thread, ptr path, ptr buf) { return ErrorCode::NOSYS; } 7 | orbis::SysResult orbis::sys_fstatfs(Thread *thread, sint fd, ptr buf) { return ErrorCode::NOSYS; } 8 | orbis::SysResult orbis::sys_getfsstat(Thread *thread, ptr buf, slong bufsize, sint flags) { return ErrorCode::NOSYS; } 9 | orbis::SysResult orbis::sys_fchdir(Thread *thread, sint fd) { return ErrorCode::NOSYS; } 10 | orbis::SysResult orbis::sys_chdir(Thread *thread, ptr path) { return ErrorCode::NOSYS; } 11 | orbis::SysResult orbis::sys_chroot(Thread *thread, ptr path) { return ErrorCode::NOSYS; } 12 | orbis::SysResult orbis::sys_open(Thread *thread, ptr path, sint flags, sint mode) { 13 | ORBIS_LOG_NOTICE("sys_open", path, flags, mode); 14 | if (auto open = thread->tproc->ops->open) { 15 | return open(thread, path, flags, mode); 16 | } 17 | 18 | return ErrorCode::NOSYS; 19 | } 20 | orbis::SysResult orbis::sys_openat(Thread *thread, sint fd, ptr path, sint flag, mode_t mode) { return ErrorCode::NOSYS; } 21 | orbis::SysResult orbis::sys_mknod(Thread *thread, ptr path, sint mode, sint dev) { return ErrorCode::NOSYS; } 22 | orbis::SysResult orbis::sys_mknodat(Thread *thread, sint fd, ptr path, mode_t mode, dev_t dev) { return ErrorCode::NOSYS; } 23 | orbis::SysResult orbis::sys_mkfifo(Thread *thread, ptr path, sint mode) { return ErrorCode::NOSYS; } 24 | orbis::SysResult orbis::sys_mkfifoat(Thread *thread, sint fd, ptr path, mode_t mode) { return ErrorCode::NOSYS; } 25 | orbis::SysResult orbis::sys_link(Thread *thread, ptr path, ptr link) { return ErrorCode::NOSYS; } 26 | orbis::SysResult orbis::sys_linkat(Thread *thread, sint fd1, ptr path1, sint fd2, ptr path2, sint flag) { return ErrorCode::NOSYS; } 27 | orbis::SysResult orbis::sys_symlink(Thread *thread, ptr path, ptr link) { return ErrorCode::NOSYS; } 28 | orbis::SysResult orbis::sys_symlinkat(Thread *thread, ptr path1, sint fd, ptr path2) { return ErrorCode::NOSYS; } 29 | orbis::SysResult orbis::sys_undelete(Thread *thread, ptr path) { return ErrorCode::NOSYS; } 30 | orbis::SysResult orbis::sys_unlink(Thread *thread, ptr path) { return ErrorCode::NOSYS; } 31 | orbis::SysResult orbis::sys_unlinkat(Thread *thread, sint fd, ptr path, sint flag) { return ErrorCode::NOSYS; } 32 | orbis::SysResult orbis::sys_lseek(Thread *thread, sint fd, off_t offset, sint whence) { 33 | if (auto lseek = thread->tproc->ops->lseek) { 34 | return lseek(thread, fd, offset, whence); 35 | } 36 | return ErrorCode::NOSYS; 37 | } 38 | orbis::SysResult orbis::sys_freebsd6_lseek(Thread *thread, sint fd, sint, off_t offset, sint whence) { 39 | return sys_lseek(thread, fd, offset, whence); 40 | } 41 | orbis::SysResult orbis::sys_access(Thread *thread, ptr path, sint flags) { return ErrorCode::NOSYS; } 42 | orbis::SysResult orbis::sys_faccessat(Thread *thread, sint fd, ptr path, sint mode, sint flag) { return ErrorCode::NOSYS; } 43 | orbis::SysResult orbis::sys_eaccess(Thread *thread, ptr path, sint flags) { return ErrorCode::NOSYS; } 44 | orbis::SysResult orbis::sys_stat(Thread *thread, ptr path, ptr ub) { return ErrorCode::NOSYS; } 45 | orbis::SysResult orbis::sys_fstatat(Thread *thread, sint fd, ptr path, ptr buf, sint flag) { return ErrorCode::NOSYS; } 46 | orbis::SysResult orbis::sys_lstat(Thread *thread, ptr path, ptr ub) { return ErrorCode::NOSYS; } 47 | orbis::SysResult orbis::sys_nstat(Thread *thread, ptr path, ptr ub) { return ErrorCode::NOSYS; } 48 | orbis::SysResult orbis::sys_nlstat(Thread *thread, ptr path, ptr ub) { return ErrorCode::NOSYS; } 49 | orbis::SysResult orbis::sys_pathconf(Thread *thread, ptr path, sint name) { return ErrorCode::NOSYS; } 50 | orbis::SysResult orbis::sys_lpathconf(Thread *thread, ptr path, sint name) { return ErrorCode::NOSYS; } 51 | orbis::SysResult orbis::sys_readlink(Thread *thread, ptr path, ptr buf, size_t count) { return ErrorCode::NOSYS; } 52 | orbis::SysResult orbis::sys_readlinkat(Thread *thread, sint fd, ptr path, ptr buf, size_t bufsize) { return ErrorCode::NOSYS; } 53 | orbis::SysResult orbis::sys_chflags(Thread *thread, ptr path, sint flags) { return ErrorCode::NOSYS; } 54 | orbis::SysResult orbis::sys_lchflags(Thread *thread, ptr path, sint flags) { return ErrorCode::NOSYS; } 55 | orbis::SysResult orbis::sys_fchflags(Thread *thread, sint fd, sint flags) { return ErrorCode::NOSYS; } 56 | orbis::SysResult orbis::sys_chmod(Thread *thread, ptr path, sint mode) { return ErrorCode::NOSYS; } 57 | orbis::SysResult orbis::sys_fchmodat(Thread *thread, sint fd, ptr path, mode_t mode, sint flag) { return ErrorCode::NOSYS; } 58 | orbis::SysResult orbis::sys_lchmod(Thread *thread, ptr path, mode_t mode) { return ErrorCode::NOSYS; } 59 | orbis::SysResult orbis::sys_fchmod(Thread *thread, sint fd, sint mode) { return ErrorCode::NOSYS; } 60 | orbis::SysResult orbis::sys_chown(Thread *thread, ptr path, sint uid, sint gid) { return ErrorCode::NOSYS; } 61 | orbis::SysResult orbis::sys_fchownat(Thread *thread, sint fd, ptr path, uid_t uid, gid_t gid, sint flag) { return ErrorCode::NOSYS; } 62 | orbis::SysResult orbis::sys_lchown(Thread *thread, ptr path, sint uid, sint gid) { return ErrorCode::NOSYS; } 63 | orbis::SysResult orbis::sys_fchown(Thread *thread, sint fd, sint uid, sint gid) { return ErrorCode::NOSYS; } 64 | orbis::SysResult orbis::sys_utimes(Thread *thread, ptr path, ptr tptr) { return ErrorCode::NOSYS; } 65 | orbis::SysResult orbis::sys_futimesat(Thread *thread, sint fd, ptr path, ptr times) { return ErrorCode::NOSYS; } 66 | orbis::SysResult orbis::sys_lutimes(Thread *thread, ptr path, ptr tptr) { return ErrorCode::NOSYS; } 67 | orbis::SysResult orbis::sys_futimes(Thread *thread, sint fd, ptr tptr) { return ErrorCode::NOSYS; } 68 | orbis::SysResult orbis::sys_truncate(Thread *thread, ptr path, off_t length) { 69 | if (auto truncate = thread->tproc->ops->truncate) { 70 | return truncate(thread, path, length); 71 | } 72 | return ErrorCode::NOSYS; 73 | } 74 | orbis::SysResult orbis::sys_freebsd6_truncate(Thread *thread, ptr path, sint, off_t length) { 75 | return sys_truncate(thread, path, length); 76 | } 77 | orbis::SysResult orbis::sys_fsync(Thread *thread, sint fd) { return ErrorCode::NOSYS; } 78 | orbis::SysResult orbis::sys_rename(Thread *thread, ptr from, ptr to) { return ErrorCode::NOSYS; } 79 | orbis::SysResult orbis::sys_renameat(Thread *thread, sint oldfd, ptr old, sint newfd, ptr new_) { return ErrorCode::NOSYS; } 80 | orbis::SysResult orbis::sys_mkdir(Thread *thread, ptr path, sint mode) { return ErrorCode::NOSYS; } 81 | orbis::SysResult orbis::sys_mkdirat(Thread *thread, sint fd, ptr path, mode_t mode) { return ErrorCode::NOSYS; } 82 | orbis::SysResult orbis::sys_rmdir(Thread *thread, ptr path) { return ErrorCode::NOSYS; } 83 | orbis::SysResult orbis::sys_getdirentries(Thread *thread, sint fd, ptr buf, uint count, ptr basep) { return ErrorCode::NOSYS; } 84 | orbis::SysResult orbis::sys_getdents(Thread *thread, sint fd, ptr buf, size_t count) { return ErrorCode::NOSYS; } 85 | orbis::SysResult orbis::sys_umask(Thread *thread, sint newmask) { return ErrorCode::NOSYS; } 86 | orbis::SysResult orbis::sys_revoke(Thread *thread, ptr path) { return ErrorCode::NOSYS; } 87 | orbis::SysResult orbis::sys_lgetfh(Thread *thread, ptr fname, ptr fhp) { return ErrorCode::NOSYS; } 88 | orbis::SysResult orbis::sys_getfh(Thread *thread, ptr fname, ptr fhp) { return ErrorCode::NOSYS; } 89 | orbis::SysResult orbis::sys_fhopen(Thread *thread, ptr u_fhp, sint flags) { return ErrorCode::NOSYS; } 90 | orbis::SysResult orbis::sys_fhstat(Thread *thread, ptr u_fhp, ptr sb) { return ErrorCode::NOSYS; } 91 | orbis::SysResult orbis::sys_fhstatfs(Thread *thread, ptr u_fhp, ptr buf) { return ErrorCode::NOSYS; } 92 | orbis::SysResult orbis::sys_posix_fallocate(Thread *thread, sint fd, off_t offset, off_t len) { return ErrorCode::NOSYS; } 93 | orbis::SysResult orbis::sys_posix_fadvise(Thread *thread, sint fd, off_t offset, off_t len, sint advice) { return ErrorCode::NOSYS; } 94 | -------------------------------------------------------------------------------- /src/sys/sys_vfs_acl.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys___acl_get_file(Thread *thread, ptr path, acl_type_t type, ptr aclp) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys___acl_get_link(Thread *thread, ptr path, acl_type_t type, ptr aclp) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys___acl_set_file(Thread *thread, ptr path, acl_type_t type, ptr aclp) { return ErrorCode::NOSYS; } 6 | orbis::SysResult orbis::sys___acl_set_link(Thread *thread, ptr path, acl_type_t type, ptr aclp) { return ErrorCode::NOSYS; } 7 | orbis::SysResult orbis::sys___acl_get_fd(Thread *thread, sint filedes, acl_type_t type, ptr aclp) { return ErrorCode::NOSYS; } 8 | orbis::SysResult orbis::sys___acl_set_fd(Thread *thread, sint filedes, acl_type_t type, ptr aclp) { return ErrorCode::NOSYS; } 9 | orbis::SysResult orbis::sys___acl_delete_link(Thread *thread, ptr path, acl_type_t type) { return ErrorCode::NOSYS; } 10 | orbis::SysResult orbis::sys___acl_delete_file(Thread *thread, ptr path, acl_type_t type) { return ErrorCode::NOSYS; } 11 | orbis::SysResult orbis::sys___acl_delete_fd(Thread *thread, sint filedes, acl_type_t type) { return ErrorCode::NOSYS; } 12 | orbis::SysResult orbis::sys___acl_aclcheck_file(Thread *thread, ptr path, acl_type_t type, ptr aclp) { return ErrorCode::NOSYS; } 13 | orbis::SysResult orbis::sys___acl_aclcheck_link(Thread *thread, ptr path, acl_type_t type, ptr aclp) { return ErrorCode::NOSYS; } 14 | orbis::SysResult orbis::sys___acl_aclcheck_fd(Thread *thread, sint filedes, acl_type_t type, ptr aclp) { return ErrorCode::NOSYS; } 15 | -------------------------------------------------------------------------------- /src/sys/sys_vfs_aio.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_aio_return(Thread *thread, ptr aiocbp) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_aio_suspend(Thread *thread, ptr aiocbp, sint nent, ptr timeout) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys_aio_cancel(Thread *thread, sint fd, ptr aiocbp) { return ErrorCode::NOSYS; } 6 | orbis::SysResult orbis::sys_aio_error(Thread *thread, ptr aiocbp) { return ErrorCode::NOSYS; } 7 | orbis::SysResult orbis::sys_oaio_read(Thread *thread, ptr aiocbp) { return ErrorCode::NOSYS; } 8 | orbis::SysResult orbis::sys_aio_read(Thread *thread, ptr aiocbp) { return ErrorCode::NOSYS; } 9 | orbis::SysResult orbis::sys_oaio_write(Thread *thread, ptr aiocbp) { return ErrorCode::NOSYS; } 10 | orbis::SysResult orbis::sys_aio_write(Thread *thread, ptr aiocbp) { return ErrorCode::NOSYS; } 11 | orbis::SysResult orbis::sys_olio_listio(Thread *thread, sint mode, ptr> acb_list, sint nent, ptr sig) { return ErrorCode::NOSYS; } 12 | orbis::SysResult orbis::sys_lio_listio(Thread *thread, sint mode, ptr> aiocbp, sint nent, ptr sig) { return ErrorCode::NOSYS; } 13 | orbis::SysResult orbis::sys_aio_waitcomplete(Thread *thread, ptr> aiocbp, ptr timeout) { return ErrorCode::NOSYS; } 14 | orbis::SysResult orbis::sys_aio_fsync(Thread *thread, sint op, ptr aiocbp) { return ErrorCode::NOSYS; } 15 | 16 | -------------------------------------------------------------------------------- /src/sys/sys_vfs_cache.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys___getcwd(Thread *thread, ptr buf, uint buflen) { return ErrorCode::NOSYS; } 4 | -------------------------------------------------------------------------------- /src/sys/sys_vfs_extattr.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_extattrctl(Thread *thread, ptr path, char cmd, ptr filename, sint attrnamespace, ptr attrname) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_extattr_set_fd(Thread *thread, sint fd, sint attrnamespace, ptr attrname, ptr data, size_t nbytes) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys_extattr_set_file(Thread *thread, ptr path, sint attrnamespace, ptr filename, ptr data, size_t nbytes) { return ErrorCode::NOSYS; } 6 | orbis::SysResult orbis::sys_extattr_set_link(Thread *thread, ptr path, sint attrnamespace, ptr attrname, ptr data, size_t nbytes) { return ErrorCode::NOSYS; } 7 | orbis::SysResult orbis::sys_extattr_get_fd(Thread *thread, sint fd, sint attrnamespace, ptr attrname, ptr data, size_t nbytes) { return ErrorCode::NOSYS; } 8 | orbis::SysResult orbis::sys_extattr_get_file(Thread *thread, ptr path, sint attrnamespace, ptr filename, ptr data, size_t nbytes) { return ErrorCode::NOSYS; } 9 | orbis::SysResult orbis::sys_extattr_get_link(Thread *thread, ptr path, sint attrnamespace, ptr attrname, ptr data, size_t nbytes) { return ErrorCode::NOSYS; } 10 | orbis::SysResult orbis::sys_extattr_delete_fd(Thread *thread, sint fd, sint attrnamespace, ptr attrname) { return ErrorCode::NOSYS; } 11 | orbis::SysResult orbis::sys_extattr_delete_file(Thread *thread, ptr path, sint attrnamespace, ptr attrname) { return ErrorCode::NOSYS; } 12 | orbis::SysResult orbis::sys_extattr_delete_link(Thread *thread, ptr path, sint attrnamespace, ptr attrname) { return ErrorCode::NOSYS; } 13 | orbis::SysResult orbis::sys_extattr_list_fd(Thread *thread, sint fd, sint attrnamespace, ptr data, size_t nbytes) { return ErrorCode::NOSYS; } 14 | orbis::SysResult orbis::sys_extattr_list_file(Thread *thread, ptr path, sint attrnamespace, ptr data, size_t nbytes) { return ErrorCode::NOSYS; } 15 | orbis::SysResult orbis::sys_extattr_list_link(Thread *thread, ptr path, sint attrnamespace, ptr data, size_t nbytes) { return ErrorCode::NOSYS; } 16 | -------------------------------------------------------------------------------- /src/sys/sys_vfs_mount.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_mount(Thread *thread, ptr type, ptr path, sint flags, caddr_t data) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_unmount(Thread *thread, ptr path, sint flags) { return ErrorCode::NOSYS; } 5 | orbis::SysResult orbis::sys_nmount(Thread *thread, ptr iovp, uint iovcnt, sint flags) { return ErrorCode::NOSYS; } 6 | -------------------------------------------------------------------------------- /src/sys/sys_vm_mmap.cpp: -------------------------------------------------------------------------------- 1 | #include "error.hpp" 2 | #include "sys/sysproto.hpp" 3 | 4 | orbis::SysResult orbis::sys_sbrk(Thread *, sint) { 5 | return ErrorCode::OPNOTSUPP; 6 | } 7 | orbis::SysResult orbis::sys_sstk(Thread *, sint) { 8 | return ErrorCode::OPNOTSUPP; 9 | } 10 | 11 | orbis::SysResult orbis::sys_mmap(Thread *thread, caddr_t addr, size_t len, 12 | sint prot, sint flags, sint fd, off_t pos) { 13 | if (auto impl = thread->tproc->ops->mmap) { 14 | return impl(thread, addr, len, prot, flags, fd, pos); 15 | } 16 | 17 | return ErrorCode::NOSYS; 18 | } 19 | 20 | orbis::SysResult orbis::sys_freebsd6_mmap(Thread *thread, caddr_t addr, 21 | size_t len, sint prot, sint flags, 22 | sint fd, sint, off_t pos) { 23 | return sys_mmap(thread, addr, len, prot, flags, fd, pos); 24 | } 25 | orbis::SysResult orbis::sys_msync(Thread *thread, ptr addr, size_t len, 26 | sint flags) { 27 | if (auto impl = thread->tproc->ops->msync) { 28 | return impl(thread, addr, len, flags); 29 | } 30 | 31 | return ErrorCode::NOSYS; 32 | } 33 | orbis::SysResult orbis::sys_munmap(Thread *thread, ptr addr, size_t len) { 34 | if (auto impl = thread->tproc->ops->munmap) { 35 | return impl(thread, addr, len); 36 | } 37 | 38 | return ErrorCode::NOSYS; 39 | } 40 | orbis::SysResult orbis::sys_mprotect(Thread *thread, ptr addr, 41 | size_t len, sint prot) { 42 | if (auto impl = thread->tproc->ops->mprotect) { 43 | return impl(thread, addr, len, prot); 44 | } 45 | 46 | return ErrorCode::NOSYS; 47 | } 48 | orbis::SysResult orbis::sys_minherit(Thread *thread, ptr addr, size_t len, 49 | sint inherit) { 50 | if (auto impl = thread->tproc->ops->minherit) { 51 | return impl(thread, addr, len, inherit); 52 | } 53 | 54 | return ErrorCode::NOSYS; 55 | } 56 | orbis::SysResult orbis::sys_madvise(Thread *thread, ptr addr, size_t len, 57 | sint behav) { 58 | if (auto impl = thread->tproc->ops->madvise) { 59 | return impl(thread, addr, len, behav); 60 | } 61 | 62 | return ErrorCode::NOSYS; 63 | } 64 | orbis::SysResult orbis::sys_mincore(Thread *thread, ptr addr, 65 | size_t len, ptr vec) { 66 | if (auto impl = thread->tproc->ops->mincore) { 67 | return impl(thread, addr, len, vec); 68 | } 69 | 70 | return ErrorCode::NOSYS; 71 | } 72 | orbis::SysResult orbis::sys_mlock(Thread *thread, ptr addr, 73 | size_t len) { 74 | if (auto impl = thread->tproc->ops->mlock) { 75 | return impl(thread, addr, len); 76 | } 77 | 78 | return ErrorCode::NOSYS; 79 | } 80 | orbis::SysResult orbis::sys_mlockall(Thread *thread, sint how) { 81 | if (auto impl = thread->tproc->ops->mlockall) { 82 | return impl(thread, how); 83 | } 84 | 85 | return ErrorCode::NOSYS; 86 | } 87 | orbis::SysResult orbis::sys_munlockall(Thread *thread) { 88 | if (auto impl = thread->tproc->ops->munlockall) { 89 | return impl(thread); 90 | } 91 | 92 | return ErrorCode::NOSYS; 93 | } 94 | orbis::SysResult orbis::sys_munlock(Thread *thread, ptr addr, 95 | size_t len) { 96 | if (auto impl = thread->tproc->ops->munlock) { 97 | return impl(thread, addr, len); 98 | } 99 | 100 | return ErrorCode::NOSYS; 101 | } 102 | -------------------------------------------------------------------------------- /src/sys/sys_vm_unix.cpp: -------------------------------------------------------------------------------- 1 | #include "sys/sysproto.hpp" 2 | 3 | orbis::SysResult orbis::sys_obreak(Thread *thread, ptr nsize) { return ErrorCode::NOSYS; } 4 | orbis::SysResult orbis::sys_ovadvise(Thread *thread, sint anom) { return ErrorCode::NOSYS; } 5 | -------------------------------------------------------------------------------- /src/utils/Logs.cpp: -------------------------------------------------------------------------------- 1 | #include "utils/Logs.hpp" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | static void append_hex(std::string &out, std::uintmax_t value) { 9 | std::ostringstream buf; 10 | buf << "0x" << std::hex << value; 11 | out += buf.str(); 12 | } 13 | 14 | namespace orbis::logs { 15 | void log_class_string::format(std::string &out, const void *arg) { 16 | const void *ptr = *reinterpret_cast(arg); 17 | append_hex(out, reinterpret_cast(ptr)); 18 | } 19 | 20 | void log_class_string::format(std::string &out, const void *arg) { 21 | out += *reinterpret_cast(arg); 22 | } 23 | 24 | template <> 25 | void log_class_string::format(std::string &out, const void *arg) { 26 | out += get_object(arg); 27 | } 28 | 29 | template <> 30 | void log_class_string::format(std::string &out, 31 | const void *arg) { 32 | out += get_object(arg); 33 | } 34 | 35 | template <> 36 | void log_class_string>::format(std::string &out, 37 | const void *arg) { 38 | const std::vector &obj = get_object(arg); 39 | out.append(obj.cbegin(), obj.cend()); 40 | } 41 | 42 | template <> 43 | void log_class_string::format(std::string &out, 44 | const void *arg) { 45 | const std::u8string &obj = get_object(arg); 46 | out.append(obj.cbegin(), obj.cend()); 47 | } 48 | 49 | template <> 50 | void log_class_string::format(std::string &out, 51 | const void *arg) { 52 | const std::u8string_view &obj = get_object(arg); 53 | out.append(obj.cbegin(), obj.cend()); 54 | } 55 | 56 | template <> 57 | void log_class_string>::format(std::string &out, 58 | const void *arg) { 59 | const std::vector &obj = get_object(arg); 60 | out.append(obj.cbegin(), obj.cend()); 61 | } 62 | 63 | template <> 64 | void log_class_string::format(std::string &out, const void *arg) { 65 | append_hex(out, static_cast(get_object(arg))); 66 | } 67 | 68 | template <> 69 | void log_class_string::format(std::string &out, 70 | const void *arg) { 71 | append_hex(out, get_object(arg)); 72 | } 73 | 74 | template <> 75 | void log_class_string::format(std::string &out, const void *arg) { 76 | append_hex(out, static_cast(get_object(arg))); 77 | } 78 | 79 | template <> 80 | void log_class_string::format(std::string &out, const void *arg) { 81 | append_hex(out, static_cast(get_object(arg))); 82 | } 83 | 84 | template <> 85 | void log_class_string::format(std::string &out, const void *arg) { 86 | append_hex(out, get_object(arg)); 87 | } 88 | 89 | template <> 90 | void log_class_string::format(std::string &out, const void *arg) { 91 | append_hex(out, static_cast(get_object(arg))); 92 | } 93 | 94 | template <> 95 | void log_class_string::format(std::string &out, const void *arg) { 96 | append_hex(out, get_object(arg)); 97 | } 98 | 99 | template <> 100 | void log_class_string::format(std::string &out, const void *arg) { 101 | append_hex(out, static_cast(get_object(arg))); 102 | } 103 | 104 | template <> 105 | void log_class_string::format(std::string &out, const void *arg) { 106 | append_hex(out, get_object(arg)); 107 | } 108 | 109 | template <> 110 | void log_class_string::format(std::string &out, const void *arg) { 111 | append_hex(out, static_cast(get_object(arg))); 112 | } 113 | 114 | template <> 115 | void log_class_string::format(std::string &out, 116 | const void *arg) { 117 | append_hex(out, get_object(arg)); 118 | } 119 | 120 | template <> 121 | void log_class_string::format(std::string &out, const void *arg) { 122 | std::ostringstream buf(out, std::ios_base::ate); 123 | buf << get_object(arg); 124 | } 125 | 126 | template <> 127 | void log_class_string::format(std::string &out, const void *arg) { 128 | std::ostringstream buf(out, std::ios_base::ate); 129 | buf << get_object(arg); 130 | } 131 | 132 | template <> 133 | void log_class_string::format(std::string &out, const void *arg) { 134 | out += get_object(arg) ? "1" : "0"; 135 | } 136 | 137 | void _orbis_log_print(LogLevel lvl, const char *msg, std::string_view names, 138 | const log_type_info *sup, ...) { 139 | 140 | /*constinit thread_local*/ std::string text; 141 | /*constinit thread_local*/ std::vector args; 142 | 143 | std::size_t args_count = 0; 144 | for (auto v = sup; v && v->log_string; v++) 145 | args_count++; 146 | 147 | text.reserve(50000); 148 | args.resize(args_count); 149 | 150 | va_list c_args; 151 | va_start(c_args, sup); 152 | for (const void *&arg : args) 153 | arg = va_arg(c_args, const void *); 154 | va_end(c_args); 155 | 156 | text += msg; 157 | text += "("; 158 | for (std::size_t i = 0; i < args_count; i++) { 159 | if (i) 160 | text += ", "; 161 | names.remove_prefix(names.find_first_not_of(" \t\n\r")); 162 | std::string_view name = names.substr(0, names.find_first_of(",")); 163 | names.remove_prefix(name.size() + 1); 164 | text += name; 165 | text += "="; 166 | sup[i].log_string(text, args[i]); 167 | } 168 | text += ")"; 169 | 170 | std::fprintf(stderr, "%s\n", text.c_str()); 171 | } 172 | } // namespace orbis::logs 173 | -------------------------------------------------------------------------------- /src/utils/SharedMutex.cpp: -------------------------------------------------------------------------------- 1 | #include "utils/SharedMutex.hpp" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | static void busy_wait(unsigned long long cycles = 3000) { 8 | const auto stop = __builtin_ia32_rdtsc() + cycles; 9 | do 10 | _mm_pause(); 11 | while (__builtin_ia32_rdtsc() < stop); 12 | } 13 | 14 | namespace orbis::utils { 15 | void shared_mutex::impl_lock_shared(unsigned val) { 16 | if (val >= c_err) 17 | std::abort(); // "shared_mutex underflow" 18 | 19 | // Try to steal the notification bit 20 | unsigned _old = val; 21 | if (val & c_sig && m_value.compare_exchange_strong(_old, val - c_sig + 1)) { 22 | return; 23 | } 24 | 25 | for (int i = 0; i < 10; i++) { 26 | if (try_lock_shared()) { 27 | return; 28 | } 29 | 30 | unsigned old = m_value; 31 | 32 | if (old & c_sig && m_value.compare_exchange_strong(old, old - c_sig + 1)) { 33 | return; 34 | } 35 | 36 | busy_wait(); 37 | } 38 | 39 | // Acquire writer lock and downgrade 40 | const unsigned old = m_value.fetch_add(c_one); 41 | 42 | if (old == 0) { 43 | lock_downgrade(); 44 | return; 45 | } 46 | 47 | if ((old % c_sig) + c_one >= c_sig) 48 | std::abort; // "shared_mutex overflow" 49 | impl_wait(); 50 | lock_downgrade(); 51 | } 52 | void shared_mutex::impl_unlock_shared(unsigned old) { 53 | if (old - 1 >= c_err) 54 | std::abort(); // "shared_mutex underflow" 55 | 56 | // Check reader count, notify the writer if necessary 57 | if ((old - 1) % c_one == 0) { 58 | impl_signal(); 59 | } 60 | } 61 | void shared_mutex::impl_wait() { 62 | while (true) { 63 | const auto [old, ok] = atomic_fetch_op(m_value, [](unsigned &value) { 64 | if (value >= c_sig) { 65 | value -= c_sig; 66 | return true; 67 | } 68 | 69 | return false; 70 | }); 71 | 72 | if (ok) { 73 | break; 74 | } 75 | 76 | syscall(SYS_futex, &m_value, FUTEX_WAIT, old, 0, 0, 0); 77 | } 78 | } 79 | void shared_mutex::impl_signal() { 80 | m_value += c_sig; 81 | syscall(SYS_futex, &m_value, FUTEX_WAKE, 1, 0, 0, 0); 82 | } 83 | void shared_mutex::impl_lock(unsigned val) { 84 | if (val >= c_err) 85 | std::abort(); // "shared_mutex underflow" 86 | 87 | // Try to steal the notification bit 88 | unsigned _old = val; 89 | if (val & c_sig && 90 | m_value.compare_exchange_strong(_old, val - c_sig + c_one)) { 91 | return; 92 | } 93 | 94 | for (int i = 0; i < 10; i++) { 95 | busy_wait(); 96 | 97 | unsigned old = m_value; 98 | 99 | if (!old && try_lock()) { 100 | return; 101 | } 102 | 103 | if (old & c_sig && 104 | m_value.compare_exchange_strong(old, old - c_sig + c_one)) { 105 | return; 106 | } 107 | } 108 | 109 | const unsigned old = m_value.fetch_add(c_one); 110 | 111 | if (old == 0) { 112 | return; 113 | } 114 | 115 | if ((old % c_sig) + c_one >= c_sig) 116 | std::abort(); // "shared_mutex overflow" 117 | impl_wait(); 118 | } 119 | void shared_mutex::impl_unlock(unsigned old) { 120 | if (old - c_one >= c_err) 121 | std::abort(); // "shared_mutex underflow" 122 | 123 | // 1) Notify the next writer if necessary 124 | // 2) Notify all readers otherwise if necessary (currently indistinguishable 125 | // from writers) 126 | if (old - c_one) { 127 | impl_signal(); 128 | } 129 | } 130 | void shared_mutex::impl_lock_upgrade() { 131 | for (int i = 0; i < 10; i++) { 132 | busy_wait(); 133 | 134 | if (try_lock_upgrade()) { 135 | return; 136 | } 137 | } 138 | 139 | // Convert to writer lock 140 | const unsigned old = m_value.fetch_add(c_one - 1); 141 | 142 | if ((old % c_sig) + c_one - 1 >= c_sig) 143 | std::abort(); // "shared_mutex overflow" 144 | 145 | if (old % c_one == 1) { 146 | return; 147 | } 148 | 149 | impl_wait(); 150 | } 151 | } // namespace orbis::utils 152 | --------------------------------------------------------------------------------