2023-06-23 02:28:14 +02:00
|
|
|
#include "ops.hpp"
|
2023-07-13 16:50:36 +02:00
|
|
|
#include "align.hpp"
|
2023-07-20 17:18:12 +02:00
|
|
|
#include "backtrace.hpp"
|
2023-06-23 02:28:14 +02:00
|
|
|
#include "io-device.hpp"
|
2023-07-30 13:56:25 +02:00
|
|
|
#include "iodev/blockpool.hpp"
|
2023-07-30 00:30:36 +02:00
|
|
|
#include "iodev/dmem.hpp"
|
2023-06-23 02:28:14 +02:00
|
|
|
#include "linker.hpp"
|
2023-07-29 21:46:28 +02:00
|
|
|
#include "orbis/KernelContext.hpp"
|
2023-06-23 02:28:14 +02:00
|
|
|
#include "orbis/module/ModuleHandle.hpp"
|
|
|
|
|
#include "orbis/thread/Process.hpp"
|
|
|
|
|
#include "orbis/thread/Thread.hpp"
|
2023-07-13 13:44:57 +02:00
|
|
|
#include "orbis/umtx.hpp"
|
2023-07-13 21:34:49 +02:00
|
|
|
#include "orbis/utils/Logs.hpp"
|
2023-06-23 02:28:14 +02:00
|
|
|
#include "orbis/utils/Rc.hpp"
|
2023-08-01 14:40:35 +02:00
|
|
|
#include "orbis/vm.hpp"
|
2023-07-06 15:55:25 +02:00
|
|
|
#include "thread.hpp"
|
2023-06-23 02:28:14 +02:00
|
|
|
#include "vfs.hpp"
|
|
|
|
|
#include "vm.hpp"
|
2023-07-06 15:55:25 +02:00
|
|
|
#include <chrono>
|
2023-07-13 15:18:38 +02:00
|
|
|
#include <csignal>
|
2023-06-23 02:28:14 +02:00
|
|
|
#include <cstdio>
|
|
|
|
|
#include <map>
|
|
|
|
|
#include <optional>
|
|
|
|
|
#include <set>
|
2023-07-06 15:55:25 +02:00
|
|
|
#include <thread>
|
2023-06-23 02:28:14 +02:00
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
|
|
using namespace orbis;
|
|
|
|
|
|
|
|
|
|
extern "C" void __register_frame(const void *);
|
|
|
|
|
|
|
|
|
|
namespace {
|
2023-07-19 00:42:23 +02:00
|
|
|
static std::pair<SysResult, Ref<Module>>
|
|
|
|
|
loadPrx(orbis::Thread *thread, std::string_view name, bool relocate,
|
|
|
|
|
std::map<std::string, Module *, std::less<>> &loadedObjects,
|
|
|
|
|
std::map<std::string, Module *, std::less<>> &loadedModules,
|
|
|
|
|
std::string_view expectedName) {
|
2023-07-20 20:04:12 +02:00
|
|
|
if (auto it = loadedObjects.find(expectedName); it != loadedObjects.end()) {
|
|
|
|
|
return {{}, it->second};
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-19 00:42:23 +02:00
|
|
|
if (auto it = loadedObjects.find(name); it != loadedObjects.end()) {
|
|
|
|
|
return {{}, it->second};
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-29 18:53:34 +02:00
|
|
|
auto module = rx::linker::loadModuleFile(name, thread);
|
2023-07-19 00:42:23 +02:00
|
|
|
|
|
|
|
|
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();
|
2023-07-19 22:28:23 +02:00
|
|
|
if (loadedModules.try_emplace(module->moduleName, module.get()).second) {
|
|
|
|
|
std::printf("Setting '%s' as '%s' module\n", module->soName,
|
|
|
|
|
module->moduleName);
|
|
|
|
|
}
|
2023-07-19 00:42:23 +02:00
|
|
|
|
|
|
|
|
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.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);
|
2023-07-19 22:28:23 +02:00
|
|
|
std::fprintf(stderr, "'%s' ('%s') was loaded with id '%u'\n",
|
|
|
|
|
module->moduleName, module->soName, (unsigned)module->id);
|
2023-07-19 00:42:23 +02:00
|
|
|
return {{}, module};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static std::pair<SysResult, Ref<Module>>
|
2023-07-20 20:04:12 +02:00
|
|
|
loadPrx(orbis::Thread *thread, std::string_view path, bool relocate) {
|
2023-07-19 00:42:23 +02:00
|
|
|
std::map<std::string, Module *, std::less<>> loadedObjects;
|
|
|
|
|
std::map<std::string, Module *, std::less<>> loadedModules;
|
|
|
|
|
|
|
|
|
|
for (auto [id, module] : thread->tproc->modulesMap) {
|
|
|
|
|
loadedObjects[module->soName] = module;
|
|
|
|
|
loadedModules[module->moduleName] = module;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-20 20:04:12 +02:00
|
|
|
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;
|
|
|
|
|
expectedName += ".prx";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return loadPrx(thread, path, relocate, loadedObjects, loadedModules,
|
|
|
|
|
expectedName);
|
|
|
|
|
}
|
2023-07-19 00:42:23 +02:00
|
|
|
|
2023-06-23 02:28:14 +02:00
|
|
|
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) {
|
2023-07-29 18:53:34 +02:00
|
|
|
auto result = rx::vm::map(addr, len, prot, flags);
|
|
|
|
|
if (result == (void *)-1) {
|
|
|
|
|
return ErrorCode::NOMEM;
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
|
|
|
|
|
2023-07-29 18:53:34 +02:00
|
|
|
thread->retval[0] = reinterpret_cast<std::uint64_t>(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);
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
|
|
|
|
|
2023-07-29 18:53:34 +02:00
|
|
|
void *maddr = addr;
|
|
|
|
|
auto result = file->ops->mmap(file, &maddr, len, prot, flags, pos, thread);
|
|
|
|
|
|
|
|
|
|
if (result != ErrorCode{}) {
|
|
|
|
|
return result;
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
|
|
|
|
|
2023-07-29 18:53:34 +02:00
|
|
|
thread->retval[0] = reinterpret_cast<std::uint64_t>(maddr);
|
2023-06-30 16:14:05 +02:00
|
|
|
return {};
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
|
|
|
|
|
2023-07-30 00:30:36 +02:00
|
|
|
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<DmemDevice *>(orbis::g_context.dmemDevice.get());
|
|
|
|
|
void *address = addr;
|
|
|
|
|
auto result =
|
|
|
|
|
dmem->mmap(&address, len, memoryType, prot, flags, directMemoryStart);
|
|
|
|
|
if (result != ErrorCode{}) {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
thread->retval[0] = reinterpret_cast<std::uint64_t>(address);
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-13 12:30:37 +02:00
|
|
|
orbis::SysResult munmap(orbis::Thread *, orbis::ptr<void> addr,
|
2023-06-23 02:28:14 +02:00
|
|
|
orbis::size_t len) {
|
2023-07-13 12:30:37 +02:00
|
|
|
if (rx::vm::unmap(addr, len)) {
|
|
|
|
|
return {};
|
|
|
|
|
}
|
2023-06-23 02:28:14 +02:00
|
|
|
return ErrorCode::INVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
orbis::SysResult msync(orbis::Thread *thread, orbis::ptr<void> addr,
|
|
|
|
|
orbis::size_t len, orbis::sint flags) {
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
orbis::SysResult mprotect(orbis::Thread *thread, orbis::ptr<const void> addr,
|
|
|
|
|
orbis::size_t len, orbis::sint prot) {
|
2023-07-18 17:54:05 +02:00
|
|
|
if (!rx::vm::protect((void *)addr, len, prot)) {
|
|
|
|
|
return ErrorCode::INVAL;
|
|
|
|
|
}
|
2023-06-23 02:28:14 +02:00
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
orbis::SysResult minherit(orbis::Thread *thread, orbis::ptr<void> addr,
|
|
|
|
|
orbis::size_t len, orbis::sint inherit) {
|
|
|
|
|
return ErrorCode::INVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
orbis::SysResult madvise(orbis::Thread *thread, orbis::ptr<void> addr,
|
|
|
|
|
orbis::size_t len, orbis::sint behav) {
|
|
|
|
|
return ErrorCode::INVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
orbis::SysResult mincore(orbis::Thread *thread, orbis::ptr<const void> addr,
|
|
|
|
|
orbis::size_t len, orbis::ptr<char> vec) {
|
|
|
|
|
return ErrorCode::INVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
orbis::SysResult mlock(orbis::Thread *thread, orbis::ptr<const void> 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<const void> addr,
|
|
|
|
|
orbis::size_t len) {
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
orbis::SysResult virtual_query(orbis::Thread *thread,
|
|
|
|
|
orbis::ptr<const void> addr, orbis::sint flags,
|
|
|
|
|
orbis::ptr<void> 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 {};
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-01 14:40:35 +02:00
|
|
|
orbis::SysResult
|
|
|
|
|
query_memory_protection(orbis::Thread *thread, orbis::ptr<void> address,
|
|
|
|
|
orbis::ptr<MemoryProtection> protection) {
|
|
|
|
|
if (rx::vm::queryProtection(address, &protection->startAddress,
|
|
|
|
|
&protection->endAddress, &protection->prot)) {
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
return ErrorCode::INVAL;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-23 02:28:14 +02:00
|
|
|
orbis::SysResult open(orbis::Thread *thread, orbis::ptr<const char> path,
|
2023-07-29 18:53:34 +02:00
|
|
|
orbis::sint flags, orbis::sint mode,
|
|
|
|
|
orbis::Ref<orbis::File> *file) {
|
2023-07-29 21:46:28 +02:00
|
|
|
return rx::vfs::open(path, flags, mode, file, thread);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
orbis::SysResult shm_open(orbis::Thread *thread, const char *path,
|
|
|
|
|
orbis::sint flags, orbis::sint mode,
|
|
|
|
|
orbis::Ref<orbis::File> *file) {
|
|
|
|
|
auto dev = static_cast<IoDevice *>(orbis::g_context.shmDevice.get());
|
|
|
|
|
return dev->open(file, path, flags, mode, thread);
|
2023-07-19 17:04:26 +02:00
|
|
|
}
|
|
|
|
|
|
2023-07-30 13:56:25 +02:00
|
|
|
orbis::SysResult blockpool_open(orbis::Thread *thread,
|
|
|
|
|
orbis::Ref<orbis::File> *file) {
|
|
|
|
|
auto dev = static_cast<IoDevice *>(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<BlockPoolDevice *>(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<std::uint64_t>(address);
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
orbis::SysResult blockpool_unmap(orbis::Thread *thread, orbis::caddr_t addr,
|
|
|
|
|
orbis::size_t len) {
|
|
|
|
|
auto blockpool =
|
|
|
|
|
static_cast<BlockPoolDevice *>(orbis::g_context.blockpoolDevice.get());
|
|
|
|
|
return blockpool->unmap(addr, len, thread);
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-19 17:04:26 +02:00
|
|
|
orbis::SysResult socket(orbis::Thread *thread, orbis::ptr<const char> name,
|
|
|
|
|
orbis::sint domain, orbis::sint type,
|
2023-07-29 18:53:34 +02:00
|
|
|
orbis::sint protocol, Ref<File> *file) {
|
|
|
|
|
return createSocket(file, name, domain, type, protocol);
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
|
|
|
|
|
2023-07-29 21:46:28 +02:00
|
|
|
orbis::SysResult shm_unlink(orbis::Thread *thread, const char *path) {
|
|
|
|
|
auto dev = static_cast<IoDevice *>(orbis::g_context.shmDevice.get());
|
|
|
|
|
return dev->unlink(path, thread);
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-23 02:28:14 +02:00
|
|
|
orbis::SysResult dynlib_get_obj_member(orbis::Thread *thread,
|
|
|
|
|
orbis::ModuleHandle handle,
|
|
|
|
|
orbis::uint64_t index,
|
|
|
|
|
orbis::ptr<orbis::ptr<void>> addrp) {
|
2023-07-19 00:42:23 +02:00
|
|
|
std::lock_guard lock(thread->tproc->mtx);
|
2023-06-23 02:28:14 +02:00
|
|
|
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 {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ErrorCode::INVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ptr<char> findSymbolById(orbis::Module *module, std::uint64_t id) {
|
|
|
|
|
for (auto sym : module->symbols) {
|
|
|
|
|
if (sym.id == id && sym.bind != orbis::SymbolBind::Local) {
|
2023-07-18 17:54:05 +02:00
|
|
|
return sym.address != 0 ? (ptr<char>)module->base + sym.address : 0;
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
orbis::SysResult dynlib_dlsym(orbis::Thread *thread, orbis::ModuleHandle handle,
|
|
|
|
|
orbis::ptr<const char> symbol,
|
|
|
|
|
orbis::ptr<orbis::ptr<void>> addrp) {
|
|
|
|
|
std::printf("sys_dynlib_dlsym(%u, '%s')\n", (unsigned)handle, symbol);
|
2023-07-19 00:42:23 +02:00
|
|
|
std::lock_guard lock(thread->tproc->mtx);
|
2023-06-23 02:28:14 +02:00
|
|
|
auto module = thread->tproc->modulesMap.get(handle);
|
|
|
|
|
|
|
|
|
|
if (module == nullptr) {
|
|
|
|
|
return ErrorCode::INVAL;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-06 18:16:25 +02:00
|
|
|
std::printf("sys_dynlib_dlsym(%s (%s), '%s')\n", module->soName,
|
|
|
|
|
module->moduleName, symbol);
|
2023-06-30 16:14:05 +02:00
|
|
|
|
2023-06-23 02:28:14 +02:00
|
|
|
std::string_view symView(symbol);
|
|
|
|
|
|
2023-06-30 16:14:05 +02:00
|
|
|
if (auto nid = rx::linker::decodeNid(symView)) {
|
|
|
|
|
if (auto addr = findSymbolById(module, *nid)) {
|
2023-06-23 02:28:14 +02:00
|
|
|
*addrp = addr;
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-06 18:16:25 +02:00
|
|
|
std::printf("sys_dynlib_dlsym(%s (%s), '%s')\n", module->soName,
|
|
|
|
|
module->moduleName,
|
|
|
|
|
rx::linker::encodeNid(rx::linker::encodeFid(symView)).string);
|
2023-06-30 16:14:05 +02:00
|
|
|
|
2023-06-23 02:28:14 +02:00
|
|
|
if (auto addr = findSymbolById(module, rx::linker::encodeFid(symView))) {
|
|
|
|
|
*addrp = addr;
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ErrorCode::NOENT;
|
|
|
|
|
}
|
|
|
|
|
orbis::SysResult dynlib_do_copy_relocations(orbis::Thread *thread) {
|
|
|
|
|
// TODO
|
|
|
|
|
return {};
|
|
|
|
|
}
|
2023-07-19 00:42:23 +02:00
|
|
|
|
2023-06-23 02:28:14 +02:00
|
|
|
orbis::SysResult dynlib_load_prx(orbis::Thread *thread,
|
|
|
|
|
orbis::ptr<const char> name,
|
|
|
|
|
orbis::uint64_t arg1,
|
|
|
|
|
orbis::ptr<ModuleHandle> pHandle,
|
|
|
|
|
orbis::uint64_t arg3) {
|
|
|
|
|
std::printf("sys_dynlib_load_prx: %s\n", name);
|
2023-07-19 00:42:23 +02:00
|
|
|
|
|
|
|
|
std::lock_guard lock(thread->tproc->mtx);
|
|
|
|
|
|
|
|
|
|
char _name[256];
|
|
|
|
|
auto errorCode = ureadString(_name, sizeof(_name), name);
|
|
|
|
|
if (errorCode != ErrorCode{}) {
|
|
|
|
|
return errorCode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto [result, module] = loadPrx(thread, _name, true);
|
2023-06-23 02:28:14 +02:00
|
|
|
if (result.isError()) {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*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<struct ucontext> ctxt,
|
|
|
|
|
ptr<orbis::slong> arg, orbis::sint flags) {
|
|
|
|
|
return ErrorCode::NOTSUP;
|
|
|
|
|
}
|
2023-07-06 15:55:25 +02:00
|
|
|
SysResult thr_new(orbis::Thread *thread, orbis::ptr<thr_param> param,
|
2023-06-23 02:28:14 +02:00
|
|
|
orbis::sint param_size) {
|
2023-07-12 02:13:39 +02:00
|
|
|
thr_param _param;
|
|
|
|
|
auto result = uread(_param, param);
|
|
|
|
|
if (result != ErrorCode{}) {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2023-07-06 15:55:25 +02:00
|
|
|
|
|
|
|
|
auto proc = thread->tproc;
|
2023-07-17 06:33:25 +02:00
|
|
|
std::lock_guard lock(proc->mtx);
|
2023-07-06 15:55:25 +02:00
|
|
|
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<std::uintptr_t>(_param.tls_base);
|
|
|
|
|
|
2023-07-12 02:13:39 +02:00
|
|
|
result = uwrite(_param.parent_tid, slong(childThread->tid));
|
|
|
|
|
|
|
|
|
|
if (result != ErrorCode{}) {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2023-07-06 15:55:25 +02:00
|
|
|
|
|
|
|
|
// FIXME: implement scheduler
|
|
|
|
|
|
2023-07-17 06:33:25 +02:00
|
|
|
ORBIS_LOG_NOTICE("Starting child thread", childThread->tid,
|
|
|
|
|
childThread->stackStart);
|
2023-07-06 15:55:25 +02:00
|
|
|
|
2023-07-17 06:33:25 +02:00
|
|
|
auto stdthr = std::thread{[=, childThread = Ref<Thread>(childThread)] {
|
2023-07-13 15:18:38 +02:00
|
|
|
stack_t ss;
|
|
|
|
|
|
2023-07-13 16:50:36 +02:00
|
|
|
auto sigStackSize = std::max<std::size_t>(
|
|
|
|
|
SIGSTKSZ, ::utils::alignUp(8 * 1024 * 1024, sysconf(_SC_PAGE_SIZE)));
|
|
|
|
|
|
|
|
|
|
ss.ss_sp = malloc(sigStackSize);
|
2023-07-13 15:18:38 +02:00
|
|
|
if (ss.ss_sp == NULL) {
|
|
|
|
|
perror("malloc");
|
2023-07-17 06:33:25 +02:00
|
|
|
::exit(EXIT_FAILURE);
|
2023-07-13 15:18:38 +02:00
|
|
|
}
|
|
|
|
|
|
2023-07-13 16:50:36 +02:00
|
|
|
ss.ss_size = sigStackSize;
|
2023-07-13 15:18:38 +02:00
|
|
|
ss.ss_flags = 0;
|
|
|
|
|
|
|
|
|
|
if (sigaltstack(&ss, NULL) == -1) {
|
|
|
|
|
perror("sigaltstack");
|
2023-07-17 06:33:25 +02:00
|
|
|
::exit(EXIT_FAILURE);
|
2023-07-13 15:18:38 +02:00
|
|
|
}
|
|
|
|
|
|
2023-07-12 02:13:39 +02:00
|
|
|
static_cast<void>(
|
|
|
|
|
uwrite(_param.child_tid, slong(childThread->tid))); // TODO: verify
|
2023-07-06 18:16:25 +02:00
|
|
|
auto context = new ucontext_t{};
|
2023-07-06 15:55:25 +02:00
|
|
|
|
2023-07-06 18:16:25 +02:00
|
|
|
context->uc_mcontext.gregs[REG_RDI] =
|
|
|
|
|
reinterpret_cast<std::uintptr_t>(_param.arg);
|
|
|
|
|
context->uc_mcontext.gregs[REG_RSI] =
|
|
|
|
|
reinterpret_cast<std::uintptr_t>(_param.arg);
|
|
|
|
|
context->uc_mcontext.gregs[REG_RSP] =
|
|
|
|
|
reinterpret_cast<std::uintptr_t>(childThread->stackEnd);
|
|
|
|
|
context->uc_mcontext.gregs[REG_RIP] =
|
|
|
|
|
reinterpret_cast<std::uintptr_t>(_param.start_func);
|
2023-07-06 15:55:25 +02:00
|
|
|
|
2023-07-06 18:16:25 +02:00
|
|
|
childThread->context = context;
|
|
|
|
|
childThread->state = orbis::ThreadState::RUNNING;
|
|
|
|
|
rx::thread::invoke(childThread.get());
|
2023-07-17 06:33:25 +02:00
|
|
|
}};
|
2023-07-06 15:55:25 +02:00
|
|
|
|
2023-07-17 06:33:25 +02:00
|
|
|
if (pthread_setname_np(stdthr.native_handle(),
|
|
|
|
|
std::to_string(childThread->tid).c_str())) {
|
|
|
|
|
perror("pthread_setname_np");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
childThread->handle = std::move(stdthr);
|
2023-06-23 02:28:14 +02:00
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
SysResult thr_exit(orbis::Thread *thread, orbis::ptr<orbis::slong> state) {
|
2023-07-06 18:16:25 +02:00
|
|
|
std::printf("Requested exit of thread %u, state %p\n", (unsigned)thread->tid,
|
|
|
|
|
state);
|
2023-07-13 13:44:57 +02:00
|
|
|
if (state != nullptr) {
|
|
|
|
|
static_cast<void>(uwrite(state, (orbis::slong)1));
|
|
|
|
|
umtx_wake(thread, state, INT_MAX);
|
|
|
|
|
}
|
2023-07-06 15:55:25 +02:00
|
|
|
|
|
|
|
|
// FIXME: implement exit
|
|
|
|
|
while (true) {
|
|
|
|
|
std::this_thread::sleep_for(std::chrono::seconds(60));
|
|
|
|
|
}
|
2023-06-23 02:28:14 +02:00
|
|
|
return ErrorCode::NOTSUP;
|
|
|
|
|
}
|
|
|
|
|
SysResult thr_kill(orbis::Thread *thread, orbis::slong id, orbis::sint sig) {
|
|
|
|
|
return ErrorCode::NOTSUP;
|
|
|
|
|
}
|
|
|
|
|
SysResult thr_kill2(orbis::Thread *thread, orbis::pid_t pid, orbis::slong id,
|
|
|
|
|
orbis::sint sig) {
|
|
|
|
|
return ErrorCode::NOTSUP;
|
|
|
|
|
}
|
|
|
|
|
SysResult thr_suspend(orbis::Thread *thread,
|
2023-07-12 04:22:44 +02:00
|
|
|
orbis::ptr<const orbis::timespec> timeout) {
|
2023-06-23 02:28:14 +02:00
|
|
|
return ErrorCode::NOTSUP;
|
|
|
|
|
}
|
|
|
|
|
SysResult thr_wake(orbis::Thread *thread, orbis::slong id) {
|
|
|
|
|
return ErrorCode::NOTSUP;
|
|
|
|
|
}
|
|
|
|
|
SysResult thr_set_name(orbis::Thread *thread, orbis::slong id,
|
|
|
|
|
orbis::ptr<const char> name) {
|
|
|
|
|
return ErrorCode::NOTSUP;
|
|
|
|
|
}
|
|
|
|
|
orbis::SysResult exit(orbis::Thread *thread, orbis::sint status) {
|
|
|
|
|
std::printf("Requested exit with status %d\n", status);
|
|
|
|
|
std::exit(status);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SysResult processNeeded(Thread *thread) {
|
2023-07-19 00:42:23 +02:00
|
|
|
std::map<std::string, Module *, std::less<>> loadedObjects;
|
|
|
|
|
std::map<std::string, Module *, std::less<>> loadedModules;
|
|
|
|
|
std::set<std::string> allNeeded;
|
2023-06-23 02:28:14 +02:00
|
|
|
|
2023-07-19 00:42:23 +02:00
|
|
|
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));
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
2023-07-19 00:42:23 +02:00
|
|
|
}
|
2023-06-23 02:28:14 +02:00
|
|
|
|
2023-07-19 00:42:23 +02:00
|
|
|
for (auto needed : allNeeded) {
|
|
|
|
|
auto [result, neededModule] =
|
|
|
|
|
loadPrx(thread, needed, false, loadedObjects, loadedModules, needed);
|
2023-06-23 02:28:14 +02:00
|
|
|
|
2023-07-19 00:42:23 +02:00
|
|
|
if (result.isError() || neededModule == nullptr) {
|
|
|
|
|
std::fprintf(stderr, "Needed '%s' not found\n", needed.c_str());
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-06-23 02:28:14 +02:00
|
|
|
|
2023-07-19 00:42:23 +02:00
|
|
|
for (auto [id, module] : thread->tproc->modulesMap) {
|
|
|
|
|
module->importedModules.reserve(module->neededModules.size());
|
2023-06-23 02:28:14 +02:00
|
|
|
|
2023-07-19 00:42:23 +02:00
|
|
|
for (auto mod : module->neededModules) {
|
|
|
|
|
if (auto it = loadedModules.find(std::string_view(mod.name));
|
|
|
|
|
it != loadedModules.end()) {
|
|
|
|
|
module->importedModules.emplace_back(it->second);
|
2023-06-29 22:01:47 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-19 00:42:23 +02:00
|
|
|
std::fprintf(stderr, "Not found needed module '%s' for object '%s'\n",
|
|
|
|
|
mod.name.c_str(), module->soName);
|
|
|
|
|
module->importedModules.push_back({});
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
|
|
|
|
|
2023-07-19 00:42:23 +02:00
|
|
|
module->relocate(thread->tproc);
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SysResult registerEhFrames(Thread *thread) {
|
|
|
|
|
for (auto [id, module] : thread->tproc->modulesMap) {
|
2023-07-05 12:08:13 +02:00
|
|
|
if (module->ehFrame != nullptr) {
|
2023-06-30 16:14:05 +02:00
|
|
|
__register_frame(module->ehFrame);
|
|
|
|
|
}
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {};
|
|
|
|
|
}
|
2023-07-20 17:18:12 +02:00
|
|
|
|
|
|
|
|
void where(Thread *thread) {
|
|
|
|
|
rx::printStackTrace((ucontext_t *)thread->context, thread, 2);
|
|
|
|
|
}
|
2023-06-23 02:28:14 +02:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
ProcessOps rx::procOpsTable = {
|
|
|
|
|
.mmap = mmap,
|
2023-07-30 00:30:36 +02:00
|
|
|
.dmem_mmap = dmem_mmap,
|
2023-06-23 02:28:14 +02:00
|
|
|
.munmap = munmap,
|
|
|
|
|
.msync = msync,
|
|
|
|
|
.mprotect = mprotect,
|
|
|
|
|
.minherit = minherit,
|
|
|
|
|
.madvise = madvise,
|
|
|
|
|
.mincore = mincore,
|
|
|
|
|
.mlock = mlock,
|
|
|
|
|
.mlockall = mlockall,
|
|
|
|
|
.munlockall = munlockall,
|
|
|
|
|
.munlock = munlock,
|
|
|
|
|
.virtual_query = virtual_query,
|
2023-08-01 14:40:35 +02:00
|
|
|
.query_memory_protection = query_memory_protection,
|
2023-06-23 02:28:14 +02:00
|
|
|
.open = open,
|
2023-07-29 21:46:28 +02:00
|
|
|
.shm_open = shm_open,
|
2023-07-30 13:56:25 +02:00
|
|
|
.blockpool_open = blockpool_open,
|
|
|
|
|
.blockpool_map = blockpool_map,
|
|
|
|
|
.blockpool_unmap = blockpool_unmap,
|
2023-07-19 17:04:26 +02:00
|
|
|
.socket = socket,
|
2023-07-29 21:46:28 +02:00
|
|
|
.shm_unlink = shm_unlink,
|
2023-06-23 02:28:14 +02:00
|
|
|
.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,
|
|
|
|
|
.exit = exit,
|
|
|
|
|
.processNeeded = processNeeded,
|
|
|
|
|
.registerEhFrames = registerEhFrames,
|
2023-07-20 17:18:12 +02:00
|
|
|
.where = where,
|
2023-06-23 02:28:14 +02:00
|
|
|
};
|