Add a set_tracer call (and implement get_tracer)

This commit is contained in:
Ariel Abreu 2022-03-24 13:47:32 -04:00
parent 2b0ae0e30b
commit 8bb81313a0
No known key found for this signature in database
GPG Key ID: D67AE16CCEA85B70
4 changed files with 81 additions and 3 deletions

View File

@ -79,6 +79,7 @@ namespace DarlingServer {
std::unordered_map<uintptr_t, std::weak_ptr<Kqchan::Process>> _listeningKqchannels;
dtape_semaphore_t* _dtapeForkWaitSemaphore;
Architecture _architecture;
std::weak_ptr<Process> _tracerProcess;
#if DSERVER_EXTENDED_DEBUG
std::unordered_map<uint32_t, uintptr_t> _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<Process> tracerProcess() const;
bool setTracerProcess(std::shared_ptr<Process> tracerProcess);
static std::shared_ptr<Process> currentProcess();
static std::shared_ptr<Process> kernelProcess();

View File

@ -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
#

View File

@ -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<Process> targetProcess = nullptr;
std::shared_ptr<Process> 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;

View File

@ -530,3 +530,17 @@ void DarlingServer::Process::_clearPortSet(dtape_port_set_id_t portSetID) {
};
#endif
std::shared_ptr<DarlingServer::Process> DarlingServer::Process::tracerProcess() const {
std::shared_lock lock(_rwlock);
return _tracerProcess.lock();
};
bool DarlingServer::Process::setTracerProcess(std::shared_ptr<Process> tracerProcess) {
std::unique_lock lock(_rwlock);
if (!_tracerProcess.expired()) {
return false;
}
_tracerProcess = tracerProcess;
return true;
};