#include "ops.hpp" #include "backtrace.hpp" #include "io-device.hpp" #include "io-devices.hpp" #include "iodev/blockpool.hpp" #include "iodev/dmem.hpp" #include "linker.hpp" #include "orbis-config.hpp" #include "orbis/KernelContext.hpp" #include "orbis/file.hpp" #include "orbis/module/ModuleHandle.hpp" #include "orbis/thread/Process.hpp" #include "orbis/thread/Thread.hpp" #include "orbis/uio.hpp" #include "orbis/umtx.hpp" #include "orbis/utils/Logs.hpp" #include "orbis/utils/Rc.hpp" #include "orbis/vm.hpp" #include "thread.hpp" #include "vfs.hpp" #include "vm.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace orbis; extern bool allowMonoDebug; extern "C" void __register_frame(const void *); void setupSigHandlers(); int ps4Exec(orbis::Thread *mainThread, orbis::utils::Ref executableModule, std::span argv, std::span envp); namespace { static std::pair> loadPrx(orbis::Thread *thread, std::string_view name, bool relocate, std::map> &loadedObjects, std::map> &loadedModules, std::string_view expectedName) { if (auto it = loadedObjects.find(expectedName); it != loadedObjects.end()) { return {{}, it->second}; } if (auto it = loadedObjects.find(name); it != loadedObjects.end()) { return {{}, it->second}; } auto module = rx::linker::loadModuleFile(name, thread); if (module == nullptr) { if (!expectedName.empty()) { loadedObjects[std::string(expectedName)] = nullptr; } return {ErrorCode::NOENT, {}}; } if (!expectedName.empty() && expectedName != module->soName) { if (module->soName[0] != '\0') { std::fprintf(stderr, "Module name mismatch, expected '%s', loaded '%s' (%s)\n", std::string(expectedName).c_str(), module->soName, module->moduleName); // std::abort(); } std::strncpy(module->soName, std::string(expectedName).c_str(), sizeof(module->soName)); if (module->soName[sizeof(module->soName) - 1] != '\0') { std::fprintf(stderr, "Too big needed name\n"); std::abort(); } } loadedObjects[module->soName] = module.get(); if (loadedModules.try_emplace(module->moduleName, module.get()).second) { std::printf("Setting '%s' as '%s' module\n", module->soName, module->moduleName); } for (auto &needed : module->needed) { auto [result, neededModule] = loadPrx(thread, needed, relocate, loadedObjects, loadedModules, needed); if (result.isError() || neededModule == nullptr) { std::fprintf(stderr, "Needed '%s' not found\n", needed.c_str()); } } module->importedModules.clear(); module->importedModules.reserve(module->neededModules.size()); for (auto mod : module->neededModules) { if (auto it = loadedModules.find(std::string_view(mod.name)); it != loadedModules.end()) { module->importedModules.emplace_back(it->second); continue; } std::fprintf(stderr, "Not found needed module '%s' for object '%s'\n", mod.name.c_str(), module->soName); module->importedModules.push_back({}); } if (relocate) { auto result = module->relocate(thread->tproc); if (result.isError()) { return {result, module}; } } module->id = thread->tproc->modulesMap.insert(module); std::fprintf(stderr, "'%s' ('%s') was loaded with id '%u'\n", module->moduleName, module->soName, (unsigned)module->id); return {{}, module}; } static std::pair> loadPrx(orbis::Thread *thread, std::string_view path, bool relocate) { std::map> loadedObjects; std::map> loadedModules; for (auto [id, module] : thread->tproc->modulesMap) { loadedObjects[module->soName] = module; loadedModules[module->moduleName] = module; } std::string expectedName; if (auto sep = path.rfind('/'); sep != std::string_view::npos) { auto tmpExpectedName = path.substr(sep + 1); if (tmpExpectedName.ends_with(".sprx")) { tmpExpectedName.remove_suffix(5); } expectedName += tmpExpectedName; if (!expectedName.ends_with(".prx")) { expectedName += ".prx"; } } return loadPrx(thread, path, relocate, loadedObjects, loadedModules, expectedName); } std::string getAbsolutePath(std::string path, Thread *thread) { if (!path.starts_with('/')) { path = "/" + std::string(thread->tproc->cwd) + "/" + path; } path = std::filesystem::path(path).lexically_normal().string(); if (!path.starts_with("/dev") && !path.starts_with("/system")) { // fixme: implement devfs mount path = std::string(thread->tproc->root) + "/" + path; } return std::filesystem::path(path).lexically_normal().string(); } orbis::SysResult mmap(orbis::Thread *thread, orbis::caddr_t addr, orbis::size_t len, orbis::sint prot, orbis::sint flags, orbis::sint fd, orbis::off_t pos) { if (fd == -1) { auto result = rx::vm::map(addr, len, prot, flags); if (result == (void *)-1) { return ErrorCode::NOMEM; } thread->retval[0] = reinterpret_cast(result); return {}; } auto file = thread->tproc->fileDescriptors.get(fd); if (file == nullptr) { return ErrorCode::BADF; } if (file->ops->mmap == nullptr) { ORBIS_LOG_FATAL("unimplemented mmap", fd, (void *)addr, len, prot, flags, pos); return mmap(thread, addr, len, prot, flags, -1, 0); } void *maddr = addr; auto result = file->ops->mmap(file.get(), &maddr, len, prot, flags, pos, thread); if (result != ErrorCode{}) { return result; } thread->retval[0] = reinterpret_cast(maddr); return {}; } orbis::SysResult dmem_mmap(orbis::Thread *thread, orbis::caddr_t addr, orbis::size_t len, orbis::sint memoryType, orbis::sint prot, sint flags, orbis::off_t directMemoryStart) { auto dmem = static_cast(orbis::g_context.dmemDevice.get()); void *address = addr; auto result = dmem->mmap(&address, len, prot, flags, directMemoryStart); if (result != ErrorCode{}) { return result; } thread->retval[0] = reinterpret_cast(address); return {}; } orbis::SysResult munmap(orbis::Thread *, orbis::ptr addr, orbis::size_t len) { if (rx::vm::unmap(addr, len)) { return {}; } return ErrorCode::INVAL; } orbis::SysResult msync(orbis::Thread *thread, orbis::ptr addr, orbis::size_t len, orbis::sint flags) { return {}; } orbis::SysResult mprotect(orbis::Thread *thread, orbis::ptr addr, orbis::size_t len, orbis::sint prot) { if (!rx::vm::protect((void *)addr, len, prot)) { return ErrorCode::INVAL; } return {}; } orbis::SysResult minherit(orbis::Thread *thread, orbis::ptr addr, orbis::size_t len, orbis::sint inherit) { return ErrorCode::INVAL; } orbis::SysResult madvise(orbis::Thread *thread, orbis::ptr addr, orbis::size_t len, orbis::sint behav) { return {}; } orbis::SysResult mincore(orbis::Thread *thread, orbis::ptr addr, orbis::size_t len, orbis::ptr vec) { return ErrorCode::INVAL; } orbis::SysResult mlock(orbis::Thread *thread, orbis::ptr addr, orbis::size_t len) { return {}; } orbis::SysResult mlockall(orbis::Thread *thread, orbis::sint how) { return {}; } orbis::SysResult munlockall(orbis::Thread *thread) { return {}; } orbis::SysResult munlock(orbis::Thread *thread, orbis::ptr addr, orbis::size_t len) { return {}; } orbis::SysResult virtual_query(orbis::Thread *thread, orbis::ptr addr, orbis::sint flags, orbis::ptr info, orbis::ulong infoSize) { if (infoSize != sizeof(rx::vm::VirtualQueryInfo)) { return ErrorCode::INVAL; } if (!rx::vm::virtualQuery(addr, flags, (rx::vm::VirtualQueryInfo *)info)) { return ErrorCode::FAULT; } return {}; } orbis::SysResult query_memory_protection(orbis::Thread *thread, orbis::ptr address, orbis::ptr protection) { if (rx::vm::queryProtection(address, &protection->startAddress, &protection->endAddress, &protection->prot)) { return {}; } return ErrorCode::INVAL; } orbis::SysResult open(orbis::Thread *thread, orbis::ptr path, orbis::sint flags, orbis::sint mode, orbis::Ref *file) { return rx::vfs::open(getAbsolutePath(path, thread), flags, mode, file, thread); } orbis::SysResult shm_open(orbis::Thread *thread, const char *path, orbis::sint flags, orbis::sint mode, orbis::Ref *file) { auto dev = static_cast(orbis::g_context.shmDevice.get()); return dev->open(file, path, flags, mode, thread); } orbis::SysResult unlink(orbis::Thread *thread, orbis::ptr path) { return rx::vfs::unlink(getAbsolutePath(path, thread), thread); } orbis::SysResult mkdir(Thread *thread, ptr path, sint mode) { ORBIS_LOG_TODO(__FUNCTION__, path, mode); return rx::vfs::mkdir(getAbsolutePath(path, thread), mode, thread); } orbis::SysResult rmdir(Thread *thread, ptr path) { ORBIS_LOG_TODO(__FUNCTION__, path); return rx::vfs::rmdir(getAbsolutePath(path, thread), thread); } orbis::SysResult rename(Thread *thread, ptr from, ptr to) { ORBIS_LOG_TODO(__FUNCTION__, from, to); return rx::vfs::rename(getAbsolutePath(from, thread), getAbsolutePath(to, thread), thread); } orbis::SysResult blockpool_open(orbis::Thread *thread, orbis::Ref *file) { auto dev = static_cast(orbis::g_context.blockpoolDevice.get()); return dev->open(file, nullptr, 0, 0, thread); } orbis::SysResult blockpool_map(orbis::Thread *thread, orbis::caddr_t addr, orbis::size_t len, orbis::sint prot, orbis::sint flags) { auto blockpool = static_cast(orbis::g_context.blockpoolDevice.get()); void *address = addr; auto result = blockpool->map(&address, len, prot, flags, thread); if (result != ErrorCode{}) { return result; } thread->retval[0] = reinterpret_cast(address); return {}; } orbis::SysResult blockpool_unmap(orbis::Thread *thread, orbis::caddr_t addr, orbis::size_t len) { auto blockpool = static_cast(orbis::g_context.blockpoolDevice.get()); return blockpool->unmap(addr, len, thread); } orbis::SysResult socket(orbis::Thread *thread, orbis::ptr name, orbis::sint domain, orbis::sint type, orbis::sint protocol, Ref *file) { return createSocket(file, name ? name : "", domain, type, protocol); } orbis::SysResult socketPair(orbis::Thread *thread, orbis::sint domain, orbis::sint type, orbis::sint protocol, Ref *a, Ref *b) { if (domain == 1 && type == 1 && protocol == 0) { int fds[2]; if (::socketpair(domain, type, protocol, fds)) { return convertErrno(); } *a = wrapSocket(fds[0], "", domain, type, protocol); *b = wrapSocket(fds[1], "", domain, type, protocol); return {}; } auto result = wrapSocket(-1, "", domain, type, protocol); *a = result; *b = result; return {}; } orbis::SysResult shm_unlink(orbis::Thread *thread, const char *path) { auto dev = static_cast(orbis::g_context.shmDevice.get()); return dev->unlink(path, false, thread); } orbis::SysResult dynlib_get_obj_member(orbis::Thread *thread, orbis::ModuleHandle handle, orbis::uint64_t index, orbis::ptr> addrp) { std::lock_guard lock(thread->tproc->mtx); auto module = thread->tproc->modulesMap.get(handle); if (module == nullptr) { return ErrorCode::INVAL; } switch (index) { case 1: *addrp = module->initProc; return {}; case 8: *addrp = module->moduleParam; return {}; default: ORBIS_LOG_ERROR(__FUNCTION__, index); thread->where(); } return ErrorCode::INVAL; } ptr findSymbolById(orbis::Module *module, std::uint64_t id) { for (auto sym : module->symbols) { if (sym.id == id && sym.bind != orbis::SymbolBind::Local) { return sym.address != 0 ? (ptr)module->base + sym.address : 0; } } return nullptr; } orbis::SysResult dynlib_dlsym(orbis::Thread *thread, orbis::ModuleHandle handle, orbis::ptr symbol, orbis::ptr> addrp) { std::printf("sys_dynlib_dlsym(%u, '%s')\n", (unsigned)handle, symbol); std::lock_guard lock(thread->tproc->mtx); auto module = thread->tproc->modulesMap.get(handle); if (module == nullptr) { return ErrorCode::INVAL; } std::printf("sys_dynlib_dlsym(%s (%s), '%s')\n", module->soName, module->moduleName, symbol); std::string_view symView(symbol); if (auto nid = rx::linker::decodeNid(symView)) { if (auto addr = findSymbolById(module.get(), *nid)) { *addrp = addr; return {}; } } std::printf("sys_dynlib_dlsym(%s (%s), '%s')\n", module->soName, module->moduleName, rx::linker::encodeNid(rx::linker::encodeFid(symView)).string); if (auto addr = findSymbolById(module.get(), rx::linker::encodeFid(symView))) { *addrp = addr; return {}; } return ErrorCode::NOENT; } orbis::SysResult dynlib_do_copy_relocations(orbis::Thread *thread) { // TODO return {}; } orbis::SysResult dynlib_load_prx(orbis::Thread *thread, orbis::ptr name, orbis::uint64_t arg1, orbis::ptr pHandle, orbis::uint64_t arg3) { std::printf("sys_dynlib_load_prx: %s\n", name); std::lock_guard lock(thread->tproc->mtx); char _name[256]; auto errorCode = ureadString(_name, sizeof(_name), name); if (errorCode != ErrorCode{}) { return errorCode; } auto path = getAbsolutePath(_name, thread); { orbis::Ref file; if (auto result = rx::vfs::open(path, 0, 0, &file, thread); result.isError()) { return result; } } auto [result, module] = loadPrx(thread, path, true); if (result.isError()) { return result; } { std::map> loadedModules; for (auto [id, module] : thread->tproc->modulesMap) { // std::fprintf(stderr, "%u: %s\n", (unsigned)id, module->moduleName); loadedModules[module->moduleName] = module; } for (auto [id, module] : thread->tproc->modulesMap) { module->importedModules.clear(); module->importedModules.reserve(module->neededModules.size()); for (auto mod : module->neededModules) { if (auto it = loadedModules.find(std::string_view(mod.name)); it != loadedModules.end()) { module->importedModules.emplace_back(it->second); continue; } module->importedModules.push_back({}); } module->relocate(thread->tproc); } } *pHandle = module->id; return {}; } orbis::SysResult dynlib_unload_prx(orbis::Thread *thread, orbis::ModuleHandle handle) { return ErrorCode::NOTSUP; } SysResult thr_create(orbis::Thread *thread, orbis::ptr ctxt, ptr arg, orbis::sint flags) { ORBIS_LOG_FATAL(__FUNCTION__, ctxt, arg, flags); return ErrorCode::NOTSUP; } SysResult thr_new(orbis::Thread *thread, orbis::ptr param, orbis::sint param_size) { thr_param _param; auto result = uread(_param, param); if (result != ErrorCode{}) { return result; } auto proc = thread->tproc; std::lock_guard lock(proc->mtx); auto [baseId, childThread] = proc->threadsMap.emplace(); childThread->tproc = proc; childThread->tid = proc->pid + baseId; childThread->state = orbis::ThreadState::RUNQ; childThread->stackStart = _param.stack_base; childThread->stackEnd = _param.stack_base + _param.stack_size; childThread->fsBase = reinterpret_cast(_param.tls_base); result = uwrite(_param.parent_tid, slong(childThread->tid)); if (result != ErrorCode{}) { return result; } // FIXME: implement scheduler ORBIS_LOG_NOTICE("Starting child thread", thread->tid, childThread->tid, childThread->stackStart, _param.rtp, _param.name, _param.spare[0], _param.spare[1]); if (_param.name != 0) { ORBIS_RET_ON_ERROR( ureadString(childThread->name, sizeof(childThread->name), _param.name)); } if (_param.rtp != 0) { rtprio _rtp; ORBIS_RET_ON_ERROR(uread(_rtp, _param.rtp)); ORBIS_LOG_NOTICE(" rtp: ", _rtp.type, _rtp.prio); } auto stdthr = std::thread{[=, childThread = Ref(childThread)] { static_cast( uwrite(_param.child_tid, slong(childThread->tid))); // TODO: verify auto context = new ucontext_t{}; context->uc_mcontext.gregs[REG_RDI] = reinterpret_cast(_param.arg); context->uc_mcontext.gregs[REG_RSI] = reinterpret_cast(_param.arg); context->uc_mcontext.gregs[REG_RSP] = reinterpret_cast(childThread->stackEnd); context->uc_mcontext.gregs[REG_RIP] = reinterpret_cast(_param.start_func); childThread->hostTid = ::gettid(); childThread->context = context; childThread->state = orbis::ThreadState::RUNNING; rx::thread::setupSignalStack(); rx::thread::setupThisThread(); rx::thread::invoke(childThread.get()); }}; if (pthread_setname_np(stdthr.native_handle(), std::to_string(childThread->tid).c_str())) { perror("pthread_setname_np"); } childThread->handle = std::move(stdthr); return {}; } SysResult thr_exit(orbis::Thread *thread, orbis::ptr state) { std::printf("Requested exit of thread %u, state %p\n", (unsigned)thread->tid, state); if (state != nullptr) { static_cast(uwrite(state, (orbis::slong)1)); umtx_wake(thread, state, INT_MAX); } // FIXME: implement exit pthread_setname_np(pthread_self(), "dead"); while (true) { std::this_thread::sleep_for(std::chrono::seconds(60)); } return ErrorCode::NOTSUP; } SysResult thr_kill(orbis::Thread *thread, orbis::slong id, orbis::sint sig) { auto t = (std::lock_guard(thread->tproc->mtx), thread->tproc->threadsMap.get(id - thread->tproc->pid)); if (t == nullptr) { return ErrorCode::SRCH; } ORBIS_LOG_FATAL(__FUNCTION__, id, sig, t->hostTid); std::lock_guard lock(t->tproc->mtx); t->signalQueue.push_back(sig); ::tgkill(t->tproc->hostPid, t->hostTid, SIGUSR1); return {}; } SysResult thr_kill2(orbis::Thread *thread, orbis::pid_t pid, orbis::slong id, orbis::sint sig) { ORBIS_LOG_FATAL(__FUNCTION__, pid, id, sig); return ErrorCode::NOTSUP; } SysResult thr_suspend(orbis::Thread *thread, orbis::ptr timeout) { ORBIS_LOG_FATAL(__FUNCTION__, timeout); return ErrorCode::NOTSUP; } SysResult thr_wake(orbis::Thread *thread, orbis::slong id) { ORBIS_LOG_FATAL(__FUNCTION__, id); return ErrorCode::NOTSUP; } SysResult thr_set_name(orbis::Thread *thread, orbis::slong id, orbis::ptr name) { ORBIS_LOG_WARNING(__FUNCTION__, name, id, thread->tid); return {}; } orbis::SysResult unmount(orbis::Thread *thread, orbis::ptr path, orbis::sint flags) { // TODO: support other that nullfs ORBIS_LOG_WARNING(__FUNCTION__, path); thread->where(); rx::vfs::unlink(getAbsolutePath(path, thread), thread); return {}; } orbis::SysResult nmount(orbis::Thread *thread, orbis::ptr iovp, orbis::uint iovcnt, orbis::sint flags) { ORBIS_LOG_ERROR(__FUNCTION__, iovp, iovcnt, flags); std::string_view fstype; std::string fspath; std::string target; for (auto it = iovp; it < iovp + iovcnt; it += 2) { IoVec a; IoVec b; ORBIS_RET_ON_ERROR(uread(a, it)); ORBIS_RET_ON_ERROR(uread(b, it + 1)); std::string_view key((char *)a.base, a.len - 1); std::string_view value((char *)b.base, b.len - 1); if (key == "fstype") { fstype = value; } else if (key == "fspath") { fspath = getAbsolutePath(std::string(value), thread); } else if (key == "target") { target = getAbsolutePath(std::string(value), thread); } std::fprintf(stderr, "%s: '%s':'%s'\n", __FUNCTION__, key.data(), value.data()); } if (fstype == "nullfs") { rx::vfs::unlinkAll(fspath, thread); return rx::vfs::createSymlink(target, fspath, thread); } // TODO return {}; } orbis::SysResult exit(orbis::Thread *thread, orbis::sint status) { std::printf("Requested exit with status %d\n", status); thread->tproc->exitStatus = status; thread->tproc->event.emit(orbis::kEvFiltProc, orbis::kNoteExit, status); std::exit(status); } SysResult processNeeded(Thread *thread) { std::map> loadedObjects; std::map> loadedModules; std::set allNeeded; for (auto [id, module] : thread->tproc->modulesMap) { loadedObjects[module->soName] = module; loadedModules[module->moduleName] = module; for (auto &needed : module->needed) { allNeeded.insert(std::string(needed)); } } for (auto needed : allNeeded) { auto [result, neededModule] = loadPrx(thread, needed, false, loadedObjects, loadedModules, needed); if (result.isError() || neededModule == nullptr) { std::fprintf(stderr, "Needed '%s' not found\n", needed.c_str()); continue; } } for (auto [id, module] : thread->tproc->modulesMap) { module->importedModules.clear(); module->importedModules.reserve(module->neededModules.size()); for (auto mod : module->neededModules) { if (auto it = loadedModules.find(std::string_view(mod.name)); it != loadedModules.end()) { module->importedModules.emplace_back(it->second); continue; } std::fprintf(stderr, "Not found needed module '%s' for object '%s'\n", mod.name.c_str(), module->soName); module->importedModules.push_back({}); } module->relocate(thread->tproc); } return {}; } SysResult fork(Thread *thread, slong flags) { auto childPid = g_context.allocatePid() * 10000 + 1; ORBIS_LOG_TODO(__FUNCTION__, flags, childPid, thread->tid); thread->where(); auto flag = knew>(); *flag = false; int hostPid = ::fork(); if (hostPid) { while (*flag == false) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); } kfree(flag, sizeof(*flag)); thread->tproc->event.emit(orbis::kEvFiltProc, orbis::kNoteFork, childPid); thread->retval[0] = childPid; thread->retval[1] = 0; return {}; } auto process = g_context.createProcess(childPid); process->hostPid = ::getpid(); process->sysent = thread->tproc->sysent; process->onSysEnter = thread->tproc->onSysEnter; process->onSysExit = thread->tproc->onSysExit; process->ops = thread->tproc->ops; process->parentProcess = thread->tproc; process->authInfo = thread->tproc->authInfo; process->sdkVersion = thread->tproc->sdkVersion; for (auto [id, mod] : thread->tproc->modulesMap) { if (!process->modulesMap.insert(id, mod)) { std::abort(); } } if (flags & RFFDG) { std::lock_guard lock(thread->tproc->fileDescriptors.mutex); for (auto [id, mod] : thread->tproc->fileDescriptors) { if (!process->fileDescriptors.insert(id, mod)) { std::abort(); } } } rx::vm::fork(childPid); rx::vfs::fork(); *flag = true; auto [baseId, newThread] = process->threadsMap.emplace(); newThread->tproc = process; newThread->hostTid = ::gettid(); newThread->tid = process->pid + baseId; newThread->state = orbis::ThreadState::RUNNING; newThread->context = thread->context; newThread->fsBase = thread->fsBase; orbis::g_currentThread = newThread; newThread->retval[0] = 0; newThread->retval[1] = 1; thread = orbis::g_currentThread; setupSigHandlers(); rx::thread::initialize(); rx::thread::setupThisThread(); auto logFd = ::open(("log-" + std::to_string(thread->tproc->pid) + ".txt").c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0666); dup2(logFd, 1); dup2(logFd, 2); ::close(logFd); return {}; } volatile bool debuggerPresent = false; SysResult execve(Thread *thread, ptr fname, ptr> argv, ptr> envv) { ORBIS_LOG_ERROR(__FUNCTION__, fname); thread->where(); std::vector _argv; std::vector _envv; if (auto ptr = argv) { char *p; while (uread(p, ptr) == ErrorCode{} && p != nullptr) { ORBIS_LOG_ERROR(" argv ", p); _argv.push_back(p); ++ptr; } } if (auto ptr = envv) { char *p; while (uread(p, ptr) == ErrorCode{} && p != nullptr) { ORBIS_LOG_ERROR(" envv ", p); _envv.push_back(p); ++ptr; } } std::string path = getAbsolutePath(fname, thread); ORBIS_LOG_ERROR(__FUNCTION__, path); { auto name = path; if (auto slashP = name.rfind('/'); slashP != std::string::npos) { name = name.substr(slashP + 1); } if (name.size() > 15) { name.resize(15); } pthread_setname_np(pthread_self(), name.c_str()); } std::printf("pid: %u\n", ::getpid()); // if (thread->tid == 60001) { // while (debuggerPresent == false) { // std::this_thread::sleep_for(std::chrono::seconds(1)); // } // } { orbis::Ref file; auto result = rx::vfs::open(path, kOpenFlagReadOnly, 0, &file, thread); if (result.isError()) { return result; } } rx::vm::reset(); thread->tproc->nextTlsSlot = 1; for (auto [id, mod] : thread->tproc->modulesMap) { thread->tproc->modulesMap.close(id); } auto executableModule = rx::linker::loadModuleFile(path, thread); executableModule->id = thread->tproc->modulesMap.insert(executableModule); thread->tproc->processParam = executableModule->processParam; thread->tproc->processParamSize = executableModule->processParamSize; thread->tproc->event.emit(orbis::kEvFiltProc, orbis::kNoteExec); ORBIS_LOG_ERROR(__FUNCTION__, "done"); std::thread([&] { rx::thread::setupSignalStack(); rx::thread::setupThisThread(); ps4Exec(thread, executableModule, _argv, _envv); }).join(); std::abort(); } SysResult registerEhFrames(Thread *thread) { for (auto [id, module] : thread->tproc->modulesMap) { if (module->ehFrame != nullptr) { __register_frame(module->ehFrame); } } return {}; } void where(Thread *thread) { rx::printStackTrace((ucontext_t *)thread->context, thread, 2); } } // namespace ProcessOps rx::procOpsTable = { .mmap = mmap, .dmem_mmap = dmem_mmap, .munmap = munmap, .msync = msync, .mprotect = mprotect, .minherit = minherit, .madvise = madvise, .mincore = mincore, .mlock = mlock, .mlockall = mlockall, .munlockall = munlockall, .munlock = munlock, .virtual_query = virtual_query, .query_memory_protection = query_memory_protection, .open = open, .shm_open = shm_open, .unlink = unlink, .mkdir = mkdir, .rmdir = rmdir, .rename = rename, .blockpool_open = blockpool_open, .blockpool_map = blockpool_map, .blockpool_unmap = blockpool_unmap, .socket = socket, .socketpair = socketPair, .shm_unlink = shm_unlink, .dynlib_get_obj_member = dynlib_get_obj_member, .dynlib_dlsym = dynlib_dlsym, .dynlib_do_copy_relocations = dynlib_do_copy_relocations, .dynlib_load_prx = dynlib_load_prx, .dynlib_unload_prx = dynlib_unload_prx, .thr_create = thr_create, .thr_new = thr_new, .thr_exit = thr_exit, .thr_kill = thr_kill, .thr_kill2 = thr_kill2, .thr_suspend = thr_suspend, .thr_wake = thr_wake, .thr_set_name = thr_set_name, .unmount = unmount, .nmount = nmount, .fork = fork, .execve = execve, .exit = exit, .processNeeded = processNeeded, .registerEhFrames = registerEhFrames, .where = where, };