From 8bb81313a0055125de19cf40e9e76db296a937d7 Mon Sep 17 00:00:00 2001 From: Ariel Abreu Date: Thu, 24 Mar 2022 13:47:32 -0400 Subject: [PATCH] Add a `set_tracer` call (and implement `get_tracer`) --- internal-include/darlingserver/process.hpp | 4 ++ scripts/generate-rpc-wrappers.py | 7 ++- src/call.cpp | 59 +++++++++++++++++++++- src/process.cpp | 14 +++++ 4 files changed, 81 insertions(+), 3 deletions(-) diff --git a/internal-include/darlingserver/process.hpp b/internal-include/darlingserver/process.hpp index ea00a58..1377421 100644 --- a/internal-include/darlingserver/process.hpp +++ b/internal-include/darlingserver/process.hpp @@ -79,6 +79,7 @@ namespace DarlingServer { std::unordered_map> _listeningKqchannels; dtape_semaphore_t* _dtapeForkWaitSemaphore; Architecture _architecture; + std::weak_ptr _tracerProcess; #if DSERVER_EXTENDED_DEBUG std::unordered_map _registeredNames; @@ -156,6 +157,9 @@ namespace DarlingServer { MemoryInfo memoryInfo() const; void memoryRegionInfo(uintptr_t address, uintptr_t& startAddress, uint64_t& pageCount, int& protection, uint64_t& mapOffset, bool& shared) const; + std::shared_ptr tracerProcess() const; + bool setTracerProcess(std::shared_ptr tracerProcess); + static std::shared_ptr currentProcess(); static std::shared_ptr kernelProcess(); diff --git a/scripts/generate-rpc-wrappers.py b/scripts/generate-rpc-wrappers.py index 0bc0d6c..8887ce0 100755 --- a/scripts/generate-rpc-wrappers.py +++ b/scripts/generate-rpc-wrappers.py @@ -131,7 +131,7 @@ calls = [ ]), ('get_tracer', [], [ - ('tracer', 'uint32_t'), + ('tracer', 'int32_t'), ]), ('uidgid', [ @@ -188,6 +188,11 @@ calls = [ ('console', '@fd'), ]), + ('set_tracer', [ + ('target', 'int32_t'), + ('tracer', 'int32_t'), + ], []), + # # kqueue channels # diff --git a/src/call.cpp b/src/call.cpp index 40fa939..e2bb9a2 100644 --- a/src/call.cpp +++ b/src/call.cpp @@ -417,9 +417,21 @@ void DarlingServer::Call::StartedSuspended::processCall() { void DarlingServer::Call::GetTracer::processCall() { int code = 0; - uint32_t tracer = 0; + int32_t tracer = 0; - callLog.warning() << "GetTracer: TODO" << callLog.endLog; + if (auto thread = _thread.lock()) { + if (auto process = thread->process()) { + if (auto tracerProcess = process->tracerProcess()) { + tracer = tracerProcess->nsid(); + } else { + // leave `tracer` as 0 + } + } else { + code = -ESRCH; + } + } else { + code = -ESRCH; + } _sendReply(code, tracer); }; @@ -769,4 +781,47 @@ void DarlingServer::Call::ConsoleOpen::processCall() { _sendReply(code, sockets[1]); }; +void DarlingServer::Call::SetTracer::processCall() { + int code = 0; + std::shared_ptr targetProcess = nullptr; + std::shared_ptr tracerProcess = nullptr; + + if (_body.target == 0) { + if (auto thread = _thread.lock()) { + targetProcess = thread->process(); + } + } else { + if (auto maybeTargetProcess = processRegistry().lookupEntryByNSID(_body.target)) { + targetProcess = *maybeTargetProcess; + } + } + + if (targetProcess) { + if (_body.tracer == 0) { + // leave tracer process as nullptr + } else { + if (auto maybeTracerProcess = processRegistry().lookupEntryByNSID(_body.tracer)) { + tracerProcess = *maybeTracerProcess; + } else { + // intentionally not negated because this is not an internal error; + // this is a perfectly valid case + code = ESRCH; + } + } + + if (code == 0) { + if (!targetProcess->setTracerProcess(tracerProcess)) { + // again, not negated because this isn't an internal error; + // simply indicates there was already a tracer set for the target + code = EPERM; + } + } + } else { + // ditto from before + code = ESRCH; + } + + _sendReply(code); +}; + DSERVER_CLASS_SOURCE_DEFS; diff --git a/src/process.cpp b/src/process.cpp index f94c79e..a86ee62 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -530,3 +530,17 @@ void DarlingServer::Process::_clearPortSet(dtape_port_set_id_t portSetID) { }; #endif + +std::shared_ptr DarlingServer::Process::tracerProcess() const { + std::shared_lock lock(_rwlock); + return _tracerProcess.lock(); +}; + +bool DarlingServer::Process::setTracerProcess(std::shared_ptr tracerProcess) { + std::unique_lock lock(_rwlock); + if (!_tracerProcess.expired()) { + return false; + } + _tracerProcess = tracerProcess; + return true; +};