2#include "pedigree/kernel/LockGuard.h"
3#include "pedigree/kernel/process/Thread.h"
4#include "pedigree/kernel/processor/state.h"
5#include "pedigree/kernel/utilities/lib.h"
9#include "PosixSubsystem.h"
10#include "queued-signal.h"
11#include "trace-state.h"
14void ignoreTraceSignal(
int) {}
15bool stopping(
int signal) {
16 return signal == 19 || signal == 20 || signal == 21 || signal == 22;
20 record.number =
event.getNumber();
21 record.code =
event.getSignalCode();
22 record.pid =
event.getSenderProcess();
23 record.uid =
event.getSenderUser();
24 record.value =
event.getSignalValue();
25 record.status =
event.childStatus();
26 record.userTime =
event.childUserTime();
27 record.systemTime =
event.childSystemTime();
28 event.timerInfo(record.timerId, record.overrun);
30 posix_signal_record_siginfo(record, encoded);
32 MemoryCopy(&info, &encoded,
sizeof(info));
35void releaseRelation(
void* value) {
39 int32_t timer = 0, overrun = 0;
40 event.timerInfo(timer, overrun);
41 event.completeSignalDelivery(overrun);
45TraceStatus PosixSubsystem::prepareTraceSignal(
Thread& thread,
int signal, int32_t pid,
46 uint32_t uid,
bool inheritReservation,
51 auto* handler = m_SignalHandlers.lookup(signal);
53 return TraceStatus::Missing;
56 static_cast<SignalEvent*
>(handler->pEvent->cloneForDelivery()));
57 else if (handler->type == 2)
59 reinterpret_cast<uintptr_t
>(ignoreTraceSignal), signal, ~0UL, uint64_t(0),
true,
true,
60 Event::HandlerPrivilege::Kernel, SignalEvent::DeliveryDisposition::DefaultAction);
63 return TraceStatus::NoMemory;
64 if (signal >= 35 && !inheritReservation) {
65 auto reservation = posix_signal_reserve_queue(thread.
getParent());
67 return TraceStatus::Full;
68 prepared.get()->setDeliveryState(reservation);
70 prepared.get()->setSignalOrigin(0, pid, uid);
71 prepared.get()->setProcessDirected(
false);
72 result = pedigree_std::move(prepared);
73 return TraceStatus::Success;
83 const int signal = replacement->
getNumber();
84 if (source && source->hasDeliveryState())
85 source->transferDeliveryStateTo(*replacement);
87 constexpr int stops[] = {19, 20, 21, 22};
88 for (
int stop : stops)
89 thread.cullSignalEvent(stop);
91 }
else if (stopping(signal)) {
95 replacement->setTraceBypass(!(thread.
getSignalMask() & (uint64_t(1) << (signal - 1))));
99 m_PendingSignals->recordChange(signal, &thread,
false);
103Subsystem::UserReturnEventResult PosixSubsystem::userReturnEvent(
Thread& thread,
Event& event,
106 return UserReturnEventResult::Deliver;
108 if (signal.consumeTraceBypass())
109 return UserReturnEventResult::Deliver;
113 return UserReturnEventResult::Deliver;
114 if (!signal.deliveryActive())
115 return UserReturnEventResult::Consumed;
116 const int number = signal.getNumber();
117 auto decision = relation->stop(thread, frame, PosixTraceRelation::StopKind::Signal, number,
118 signalInfo(signal), 0, signal.hasDeliveryState());
122 if (decision.terminal) {
125 return UserReturnEventResult::Terminal;
127 if (!decision.signal) {
129 return UserReturnEventResult::Consumed;
131 SignalDisposition disposition;
132 if (decision.signal == number && stopping(number) &&
getSignalDisposition(number, disposition) &&
133 disposition.type == 1) {
134 const size_t epoch = signal.getContinuationEpoch();
136 decision = relation->stop(thread, frame, PosixTraceRelation::StopKind::Group, number,
138 if (decision.terminal) {
141 return UserReturnEventResult::Terminal;
143 }
else if (decision.detached) {
147 return UserReturnEventResult::Consumed;
149 if (decision.signal == number)
150 return UserReturnEventResult::Deliver;
151 if (!publishTraceSignal(thread, decision.prepared, &signal))
152 return UserReturnEventResult::Terminal;
153 return UserReturnEventResult::Consumed;
156Subsystem::UserReturnResult PosixSubsystem::userReturnCheckpoint(
Thread& thread,
160 if (!
m_TraceContext.acquireIncoming(relation) || !relation->takeExecTrap())
161 return UserReturnResult::Continue;
163 int32_t number = 5, code = 0;
164 MemoryCopy(
reinterpret_cast<uint8_t*
>(&info), &number, 4);
165 MemoryCopy(
reinterpret_cast<uint8_t*
>(&info) + 8, &code, 4);
166 auto decision = relation->stop(thread, frame, PosixTraceRelation::StopKind::Exec, 5, info);
170 if (decision.terminal) {
173 return UserReturnResult::Terminal;
175 if (decision.signal && !publishTraceSignal(thread, decision.prepared,
nullptr))
176 return UserReturnResult::Terminal;
177 return UserReturnResult::Continue;
180bool PosixSubsystem::traceException(
Thread& thread,
int& signal, InterruptState& state,
181 ExceptionType exception, uintptr_t address,
182 uintptr_t errorCode) {
183 auto* frame = thread.currentUserReturnFrame();
192 code = errorCode & 1 ? 2 : 1;
197 case GeneralProtectionFault:
198 case FileMappingFault:
205 case SpecialFpuError:
212 auto info = signalInfo(source);
213 const uintptr_t fault = exception == PageFault || exception == FileMappingFault
215 : state.getInstructionPointer();
216 ByteSet(
reinterpret_cast<uint8_t*
>(&info) + 16, 0,
sizeof(info) - 16);
217 MemoryCopy(
reinterpret_cast<uint8_t*
>(&info) + 16, &fault,
sizeof(fault));
219 relation->stop(thread, *frame, PosixTraceRelation::StopKind::Signal, signal, info);
223 if (decision.terminal) {
228 if (!decision.signal)
230 if (decision.signal != signal) {
231 if (!publishTraceSignal(thread, decision.prepared,
nullptr) &&
236 SignalDisposition disposition;
241 if (disposition.type == 1)
virtual bool isSignalEvent() const
virtual size_t getNumber()=0
UnlikelyLock m_SignalHandlersLock
PosixTraceContext m_TraceContext
bool getSignalDisposition(size_t sig, SignalDisposition &disposition, bool beginDelivery=false)
void suspendIfContinuationEpoch(int stopSignal, size_t continuationEpoch)
size_t getContinuationEpoch()
virtual size_t getNumber()
void setSignalOrigin(int32_t signalCode, int32_t senderProcess, uint32_t senderUser)
void setContinuationEpoch(size_t continuationEpoch)
@ Continue
No unwind necessary, carry on as normal.
void deferSignalExit(int signal)
UnwindType getUnwindState()
Process * getParent() const
void cullSignalEvent(size_t signalNumber)
bool sendEvent(Event *pEvent)
T * releaseOwnership() noexcept
static UniquePointer< T > adopt(T *pointer)