libclues
Linux C++ Tracing Library
Loading...
Searching...
No Matches
Tracee.hxx
1#pragma once
2
3// C++
4#include <array>
5#include <iosfwd>
6
7// Linux
8#include <unistd.h>
9
10// cosmos
11#include <cosmos/BitMask.hxx>
12#include <cosmos/proc/process.hxx>
13#include <cosmos/proc/ptrace.hxx>
14#include <cosmos/proc/signal.hxx>
15#include <cosmos/proc/Tracee.hxx>
16
17// clues
18#include <clues/ProcessData.hxx>
19#include <clues/RegisterSet.hxx>
20#include <clues/SystemCallInfo.hxx>
21#include <clues/SystemCallDB.hxx>
22#include <clues/types.hxx>
23
24namespace cosmos {
25 class ApiError;
26}
27
28namespace clues {
29
30class SystemCall;
31class EventConsumer;
32class Engine;
33
35
39class CLUES_API Tracee {
40 friend class Engine;
41 friend class SystemCall;
42public: // types
43
45
59
71
72 using Flags = cosmos::BitMask<Flag>;
73
74public: // functions
75
76 virtual ~Tracee();
77
78 const std::string& executable() const {
79 return m_process_data->executable;
80 }
81
82 const cosmos::StringVector& cmdLine() const {
83 return m_process_data->cmdline;
84 }
85
87 const FDInfoMap& fdInfoMap() const {
88 return m_process_data->fd_info_map;
89 }
90
91 cosmos::ProcessID pid() const {
92 return m_ptrace.pid();
93 }
94
95 bool alive() const {
96 return pid() != cosmos::ProcessID::INVALID;
97 }
98
99 size_t maxBufferPrefetch() const {
100 return m_max_buffer_prefetch;
101 }
102
104
123 void setMaxBufferPrefetch(const size_t bytes) {
124 m_max_buffer_prefetch = bytes;
125 }
126
128
132 size_t syscallCtr() const {
133 return m_syscall_ctr;
134 }
135
137 std::optional<cosmos::Signal> stopSignal() const {
138 return m_stop_signal;
139 }
140
141 static const char* getStateLabel(const State state);
142
143 State state() const {
144 return m_state;
145 }
146
147 State prevState() const {
148 return m_prev_state;
149 }
150
151 bool isEnterStop() const {
152 return state() == State::SYSCALL_ENTER_STOP;
153 }
154
155 bool isExitStop() const {
156 return state() == State::SYSCALL_EXIT_STOP;
157 }
158
159 Flags flags() const {
160 return m_flags;
161 }
162
164
169 std::optional<cosmos::ChildState> exitData() const {
170 return m_exit_data;
171 }
172
174
181 virtual void attach(const FollowChildren follow_children,
182 const AttachThreads attach_threads = AttachThreads{false});
183
185
196 bool detach();
197
199
203 long getData(const ForeignPtr addr) const;
204
206
210 void readString(const ForeignPtr addr, std::string &out) const;
211
213 void readBlob(const ForeignPtr addr, char *buffer, const size_t bytes) const;
214
216
220 template <typename T, bool CHECK_TRIVIAL=true>
221 bool readStruct(const ForeignPtr addr, T &out) const {
222 // the address of the struct in the tracee's address space
223 if (addr == ForeignPtr::NO_POINTER)
224 // null address specification
225 return false;
226
227 if constexpr (CHECK_TRIVIAL) {
228 static_assert(std::is_trivial_v<T> == true);
229 }
230
231 readBlob(addr, reinterpret_cast<char*>(&out), sizeof(T));
232 return true;
233 }
234
236 template <typename VECTOR>
237 void readVector(const ForeignPtr pointer, VECTOR &out) const;
238
240
245 virtual bool isChildProcess() const {
246 return false;
247 }
248
250
262 bool isThreadGroupLeader() const;
263
265
270 return m_initial_attacher != std::nullopt;
271 }
272
274 std::optional<SystemCallNr> currentSystemCallNr() const;
275
276 const std::optional<SystemCallInfo>& currentSystemCallInfo() const {
277 return m_syscall_info;
278 }
279
280 const Engine& engine() const {
281 return m_engine;
282 }
283
284protected: // constants
285
287
292 static constexpr std::array<cosmos::Signal, 4> STOPPING_SIGNALS = {
293 cosmos::signal::STOP, cosmos::signal::TERM_STOP,
294 cosmos::signal::TERM_INPUT, cosmos::signal::TERM_OUTPUT
295 };
296
297protected: // functions
298
304 explicit Tracee(Engine &engine, EventConsumer &consumer,
305 TraceePtr sibling = nullptr);
306
308
312 void processEvent(const cosmos::ChildState &data);
313
314 void updateExecutable();
315
316 void updateCmdLine();
317
318 void updateExecInfo() {
319 updateExecutable();
320 updateCmdLine();
321 }
322
323 void syncFDsAfterExec();
324
325 void changeState(const State new_state);
326
328 void interrupt() {
329 m_ptrace.interrupt();
330 }
331
333 void restart(const cosmos::Tracee::RestartMode mode = cosmos::Tracee::RestartMode::CONT,
334 const std::optional<cosmos::Signal> signal = {}) {
335 m_ptrace.restart(mode, signal);
336 }
337
339 void setOptions(const cosmos::ptrace::Opts opts) {
340 m_ptrace.setOptions(opts);
341 }
342
344 void seize(const cosmos::ptrace::Opts opts) {
345 m_ptrace.seize(opts);
346 }
347
349 void setPID(const cosmos::ProcessID tracee);
350
352
355 template <ABI abi>
356 void getRegisters(RegisterSet<abi> &rs);
357
358 void handleSystemCall();
359
360 void handleSystemCallEntry();
361
362 void handleSystemCallExit();
363
364 void handleStateMismatch();
365
366 void handleSignal(const cosmos::SigInfo &info);
367
368 void handleEvent(const cosmos::ChildState &data,
369 const cosmos::ptrace::Event event,
370 const cosmos::Signal signal);
371
372 void handleStopEvent(const cosmos::Signal signal);
373
374 void handleExitEvent();
375
376 void handleExecEvent(const cosmos::ProcessID main_pid);
377
378 void handleNewChildEvent(const cosmos::ptrace::Event event);
379
380 void handleAttached();
381
382 void syncState(Tracee &other);
383
387 void attachThreads();
388
390 template <typename FILLER>
391 void fillData(ForeignPtr addr, FILLER &filler) const;
392
393 virtual void cleanupChild() {}
394
396 void verifyArch();
397
399 std::optional<SystemCallNr> getInitialSyscallNr(const ABI abi) const;
400
401 void getInitialRegisters();
402
403 void unshareProcessData();
404
406
409 void doDetach();
410
412
416 void handleError(const cosmos::ApiError &error);
417
419 bool hasClonedThread() const;
420
422
426 void trackFD(FDInfo &&info) const;
427
429 void dropFD(const cosmos::FileNum fd) const;
430
431protected: // data
432
434 Engine &m_engine;
442 Flags m_flags;
444 cosmos::Tracee m_ptrace;
446 cosmos::ptrace::Opts m_ptrace_opts;
448 std::optional<SystemCallInfo> m_syscall_info;
452 SystemCall *m_current_syscall = nullptr;
454 SystemCall *m_interrupted_syscall = nullptr;
456 cosmos::Tracee::RestartMode m_restart_mode = cosmos::Tracee::RestartMode::CONT;
458 std::optional<cosmos::Signal> m_inject_sig;
460 std::optional<cosmos::ChildState> m_exit_data;
462 std::optional<cosmos::ProcessID> m_initial_attacher;
464 size_t m_syscall_ctr = 0;
468 std::optional<cosmos::Signal> m_stop_signal;
470 ProcessDataPtr m_process_data;
473};
474
475} // end ns
476
477std::ostream& operator<<(std::ostream &o, const clues::Tracee::State &state);
Main class for configuring and running libclues.
Definition Engine.hxx:45
Callback interface for consumers of tracing events.
Holds a set of registers for the given ABI.
Stores information about each system call number in form of SystemCall objects.
Access to System Call Data.
Base class for traced processes.
Definition Tracee.hxx:39
bool isInitiallyAttachedThread() const
Indicates whether this Tracee is an automatically attached thread.
Definition Tracee.hxx:269
cosmos::ptrace::Opts m_ptrace_opts
The options we've set for ptrace().
Definition Tracee.hxx:446
ProcessDataPtr m_process_data
Shared process data.
Definition Tracee.hxx:470
Flag
Different flags reflecting the tracer status.
Definition Tracee.hxx:61
@ INJECTED_SIGSTOP
whether we've injected a SIGSTOP that needs to be undone.
Definition Tracee.hxx:64
@ SYSCALL_ENTERED
we've seen a syscall-enter-stop and are waiting for the corresponding exit-stop.
Definition Tracee.hxx:66
@ SEEN_SIGRETURN
a sigreturn with a pending interrupted system call has been observed.
Definition Tracee.hxx:69
@ INJECTED_SIGCONT
whether we've injected a SIGCONT that needs to be ignored.
Definition Tracee.hxx:65
@ DETACH_AT_NEXT_STOP
as soon as the tracee reaches a stop stace, detach from it.
Definition Tracee.hxx:63
@ WAIT_FOR_ATTACH_STOP
we're still waiting for the PTRACE_INTERRUPT event stop.
Definition Tracee.hxx:62
@ WAIT_FOR_EXITED
we've already seen PTHREAD_EVENT_EXIT but are still waiting for CLD_EXITED.
Definition Tracee.hxx:67
@ ATTACH_THREADS_PENDING
attach all threads of the process as soon as the initial event stop happens.
Definition Tracee.hxx:68
void setMaxBufferPrefetch(const size_t bytes)
Sets an upper limit for the retrieval of variable-length buffer parameters in system calls.
Definition Tracee.hxx:123
size_t m_max_buffer_prefetch
Number of bytes system calls will fetch for variable-length data buffers.
Definition Tracee.hxx:472
std::optional< cosmos::Signal > m_stop_signal
For State::GROUP_STOP this contains the signal that caused it.
Definition Tracee.hxx:468
Tracee(Engine &engine, EventConsumer &consumer, TraceePtr sibling=nullptr)
Definition Tracee.cxx:100
void seize(const cosmos::ptrace::Opts opts)
Makes the tracee a tracee.
Definition Tracee.hxx:344
size_t m_syscall_ctr
Number of system calls observed.
Definition Tracee.hxx:464
SystemCall * m_current_syscall
Holds state for the currently executing system call.
Definition Tracee.hxx:452
Engine & m_engine
The engine that manages this tracee.
Definition Tracee.hxx:434
void setOptions(const cosmos::ptrace::Opts opts)
Applies the given trace flags.
Definition Tracee.hxx:339
std::optional< cosmos::ChildState > m_exit_data
If tracee exit was observed then this contains the final exit data.
Definition Tracee.hxx:460
Flags m_flags
These keep track of various state on the tracer side.
Definition Tracee.hxx:442
size_t syscallCtr() const
Returns the number of system calls observed so far.
Definition Tracee.hxx:132
cosmos::Tracee m_ptrace
libcosmos API for the Tracee.
Definition Tracee.hxx:444
bool readStruct(const ForeignPtr addr, T &out) const
Reads a system call struct from the tracee's address space into out.
Definition Tracee.hxx:221
const FDInfoMap & fdInfoMap() const
Provides access to the current knowledge about file descriptors in the tracee.
Definition Tracee.hxx:87
std::optional< SystemCallInfo > m_syscall_info
The current system call information, if any.
Definition Tracee.hxx:448
static constexpr std::array< cosmos::Signal, 4 > STOPPING_SIGNALS
Array of signals that cause tracee stop.
Definition Tracee.hxx:292
State
Current tracing state for a single tracee.
Definition Tracee.hxx:48
@ DETACHED
we already detached from the tracee
Definition Tracee.hxx:57
@ SYSCALL_ENTER_STOP
system call started.
Definition Tracee.hxx:51
@ SYSCALL_EXIT_STOP
system call finished.
Definition Tracee.hxx:52
@ RUNNING
tracee is running normally / not in a special trace state.
Definition Tracee.hxx:50
@ SIGNAL_DELIVERY_STOP
signal was delivered.
Definition Tracee.hxx:53
@ UNKNOWN
initial PTRACE_SIZE / PTRACE_INTERRUPT.
Definition Tracee.hxx:49
@ EVENT_STOP
special ptrace event occurred.
Definition Tracee.hxx:55
@ DEAD
the tracee no longer exists.
Definition Tracee.hxx:56
@ GROUP_STOP
SIGSTOP executed, the tracee is stopped.
Definition Tracee.hxx:54
void readBlob(const ForeignPtr addr, char *buffer, const size_t bytes) const
Reads an arbitrary binary blob of fixed length from the tracee.
Definition Tracee.cxx:981
std::optional< cosmos::ChildState > exitData() const
Returns possible tracee exit data.
Definition Tracee.hxx:169
SystemCall * m_interrupted_syscall
Previous system call, if it has been interrupted.
Definition Tracee.hxx:454
State m_state
The current state the tracee is in.
Definition Tracee.hxx:438
std::optional< cosmos::Signal > m_inject_sig
signal to inject upon next restart of the tracee.
Definition Tracee.hxx:458
std::optional< cosmos::ProcessID > m_initial_attacher
If this Tracee was automatically attached due to AttachThreads{true} then this contains the ProcessID...
Definition Tracee.hxx:462
virtual bool isChildProcess() const
Returns whether the tracee is a child process created by us.
Definition Tracee.hxx:245
cosmos::Tracee::RestartMode m_restart_mode
current RestartMode to use.
Definition Tracee.hxx:456
EventConsumer & m_consumer
Callback interface receiving our information.
Definition Tracee.hxx:436
std::optional< cosmos::Signal > stopSignal() const
For state() == State::GROUP_STOP this returns the stopping signal that caused it.
Definition Tracee.hxx:137
void interrupt()
Forces the traced process to stop.
Definition Tracee.hxx:328
void restart(const cosmos::Tracee::RestartMode mode=cosmos::Tracee::RestartMode::CONT, const std::optional< cosmos::Signal > signal={})
Restarts the traced process, optionally delivering signal.
Definition Tracee.hxx:333
AnyRegisterSet m_initial_regset
Register set observed during initial attach event stop.
Definition Tracee.hxx:466
State m_prev_state
The previous Tracee state we've seen (except RUNNING).
Definition Tracee.hxx:440
SystemCallDB m_syscall_db
Reusable database object for tracing system calls.
Definition Tracee.hxx:450
cosmos::NamedBool< struct attach_threads_t, true > AttachThreads
A strong boolean type denoting whether to automatically all other threads of a process.
Definition types.hxx:27
std::variant< RegisterSet< ABI::I386 >, RegisterSet< ABI::X86_64 >, RegisterSet< ABI::X32 >, RegisterSet< ABI::AARCH64 > > AnyRegisterSet
A variant to hold any of the ABI-specific RegisterSet types.
std::map< cosmos::FileNum, FDInfo > FDInfoMap
A mapping of file descriptor numbers to their file system paths or other human readable description o...
Definition types.hxx:126
cosmos::NamedBool< struct follow_children_t, true > FollowChildren
A strong boolean type denoting whether to automatically attach to newly created child processes.
Definition types.hxx:24
ForeignPtr
Strongly typed opaque pointer to tracee memory.
Definition types.hxx:140