libclues
Linux C++ Tracing Library
Loading...
Searching...
No Matches
TermTracer.hxx
1#pragma once
2
3// C++
4#include <map>
5#include <memory>
6#include <set>
7#include <tuple>
8
9// cosmos
10#include <cosmos/BitMask.hxx>
11#include <cosmos/io/StdLogger.hxx>
12#include <cosmos/main.hxx>
13#include <cosmos/types.hxx>
14
15// clues
16#include <clues/Engine.hxx>
17#include <clues/EventConsumer.hxx>
18#include <clues/SystemCall.hxx>
19
20// termtracer
21#include "Args.hxx"
22
23namespace clues {
24
25class TermTracer :
27 public cosmos::MainPlainArgs {
28public: // functions
29
30 TermTracer();
31
32 TermTracer(const TermTracer&) = delete;
33 TermTracer& operator=(const TermTracer&) = delete;
34
35protected: // types
36
38 enum class FollowExecContext {
39 YES,
40 NO,
41 ASK,
42 CHECK_PATH,
43 CHECK_GLOB
44 };
45
46 enum class FollowChildMode {
47 YES,
48 NO,
49 ASK,
50 THREADS
51 };
52
53 enum class Flag {
56 };
57
58 using Flags = cosmos::BitMask<Flag>;
59
60protected: // functions
61
62 bool processPars();
63
64 void printSyscalls();
65
66 void printABISyscalls(const std::string &abi);
67
68 void printABIs();
69
70 cosmos::ExitStatus main(const int argc, const char **argv) override;
71
72 bool configureTracee(const cosmos::ProcessID pid);
73
74 void runTrace();
75
76 void configureLogger();
77
78 std::string formatTraceeInvocation(const Tracee &tracee);
79 std::string formatTraceeInvocation(const std::string &exe, const cosmos::StringVector &cmdline) const;
80 void printPar(std::ostream &trace, const SystemCallItem &value) const;
81 void printParsOnEntry(std::ostream &trace, const SystemCall::ParameterVector &pars) const;
82 void printParsOnExit(std::ostream &trace, const SystemCall::ParameterVector &pars) const;
83
84 bool followExecutionContext(Tracee &tracee);
85
87 std::ostream& traceStream(const Tracee &tracee, const bool new_line = true);
88
90
98 void startNewLine(std::ostream &trace, const Tracee &tracee);
99
101
110
112
117 void checkResumedSyscall(const Tracee &tracee);
118
119 bool hasActiveSyscall(const Tracee &tracee) const {
120 return hasActiveSyscall(tracee.pid());
121 }
122
123 bool hasActiveSyscall(const cosmos::ProcessID pid) const {
124 return activeSyscall(pid) != nullptr;
125 }
126
127 const SystemCall* activeSyscall(const cosmos::ProcessID pid) const {
128 if (!m_active_syscall)
129 return nullptr;
130
131 const auto info = *m_active_syscall;
132
133 if (std::get<cosmos::ProcessID>(info) != pid) {
134 return nullptr;
135 }
136
137 return std::get<const SystemCall*>(info);
138 }
139
140 const SystemCall* activeSyscall(const Tracee &tracee) const {
141 return activeSyscall(tracee.pid());
142 }
143
144 const SystemCall* activeSyscall() const {
145 if (!m_active_syscall)
146 return nullptr;
147
148 return std::get<const SystemCall*>(*m_active_syscall);
149 }
150
152
160 const SystemCall* findSyscall(const Tracee &tracee) const;
161
162 bool isExecSyscall(const SystemCall &sc) const;
163
165 bool isEnabled(const SystemCall *sc) const;
166
168
172 const SystemCall* currentSyscall(const Tracee &tracee) const;
173
174 void cleanupTracee(const Tracee &tracee);
175
177 void updateTracee(const Tracee &tracee, const cosmos::ProcessID old_pid);
178
179 bool seenInitialExec() const {
181 }
182
184
189 void abortSyscall(const Tracee &tracee);
190
192 void checkABI(const Tracee &tracee, const SystemCallInfo &info);
193
194protected: // EventConsumer interface
195
196 void syscallEntry(Tracee &tracee, const SystemCall &sc, const StatusFlags flags) override;
197
198 void syscallExit(Tracee &tracee, const SystemCall &sc, const StatusFlags flags) override;
199
200 void signaled(Tracee &tracee, const cosmos::SigInfo &info) override;
201
202 void attached(Tracee &tracee) override;
203
204 void exited(Tracee &tracee, const cosmos::WaitStatus status, const StatusFlags flags) override;
205
206 void newExecutionContext(Tracee &tracee,
207 const std::string &old_exe,
208 const cosmos::StringVector &old_cmdline,
209 const std::optional<cosmos::ProcessID> old_pid) override;
210
211 void newChildProcess(
212 Tracee &parent,
213 Tracee &child,
214 const cosmos::ptrace::Event event,
215 const StatusFlags flags) override;
216
217 void stopped(Tracee &tracee) override;
218
219 void disappeared(Tracee &tracee, const cosmos::ChildState &data) override;
220
221protected: // data
222
225
227 cosmos::StdLogger m_logger;
228 cosmos::Init m_cosmos;
229
231 Engine m_engine;
232
234 bool m_print_pars = true;
240 std::set<SystemCallNr> m_syscall_filter;
242 FollowExecContext m_follow_exec = FollowExecContext::YES;
244 FollowChildMode m_follow_children = FollowChildMode::NO;
245
247 size_t m_num_tracees = 0;
249 Flags m_flags;
251 cosmos::ProcessID m_main_tracee_pid;
253 std::optional<cosmos::WaitStatus> m_main_status;
254
256
261 std::optional<std::tuple<cosmos::ProcessID, const SystemCall*>> m_active_syscall;
263
268 std::map<cosmos::ProcessID, const SystemCall*> m_unfinished_syscalls;
270
274 std::map<cosmos::ProcessID, std::pair<cosmos::ProcessID, cosmos::ptrace::Event>> m_new_tracees;
276 clues::ABI m_last_abi = clues::ABI::UNKNOWN;
277
278};
279
280} // end ns
Callback interface for consumers of tracing events.
Base class for any kind of system call parameter or return value.
std::vector< SystemCallItemPtr > ParameterVector
Vector of the parameters required for a system call.
const SystemCall * findSyscall(const Tracee &tracee) const
Find any active or unfinished system call for pid.
void newChildProcess(Tracee &parent, Tracee &child, const cosmos::ptrace::Event event, const StatusFlags flags) override
A new child process has been created.
std::optional< std::tuple< cosmos::ProcessID, const SystemCall * > > m_active_syscall
The currently active system call, if any.
void syscallExit(Tracee &tracee, const SystemCall &sc, const StatusFlags flags) override
A system call has been finished.
const SystemCall * currentSyscall(const Tracee &tracee) const
Returns the system call last seen for tracee, or nullptr if there's none.
Flags m_flags
State flags with global context or carried between different callbacks.
void checkABI(const Tracee &tracee, const SystemCallInfo &info)
Checks the current system call's ABI and reports ABI changes.
std::string m_exec_context_arg
optional argument to m_follow_exec (e.g. path, glob, script)
bool storeUnfinishedSyscallCtx()
Store an active system call in m_unfinished_syscalls.
Args m_args
Command line arguments and parser.
void syscallEntry(Tracee &tracee, const SystemCall &sc, const StatusFlags flags) override
A system call is about to be executed in the Tracee.
void abortSyscall(const Tracee &tracee)
Abort syscall if one was active for tracee.
std::ostream & traceStream(const Tracee &tracee, const bool new_line=true)
Returns the currently active trace output stream, starting a new output line.
std::map< cosmos::ProcessID, std::pair< cosmos::ProcessID, cosmos::ptrace::Event > > m_new_tracees
Newly created tracees that haven't seen any ptrace stop yet.
void signaled(Tracee &tracee, const cosmos::SigInfo &info) override
The tracee has received a signal.
void updateTracee(const Tracee &tracee, const cosmos::ProcessID old_pid)
Update internal data structures in case a tracee changed PID.
clues::ABI m_last_abi
The ABI of the last system call we've seen.
FollowChildMode m_follow_children
Behaviour upon newChildProcess()
FollowExecContext
What to do upon execve.
void exited(Tracee &tracee, const cosmos::WaitStatus status, const StatusFlags flags) override
The tracee is about to end execution.
@ DROPPED_TO_LAST_TRACEE
whether we've returned to tracing only a single PID anymore.
@ SEEN_INITIAL_EXEC
whether we've seen a ChildTracee's initial newExecutionContext().
std::map< cosmos::ProcessID, const SystemCall * > m_unfinished_syscalls
Unfinished / preempted system calls.
FollowExecContext m_follow_exec
Behaviour upon newExecutionContext()
size_t m_par_truncation_len
Maximum length of of system call parameter values to print before truncating the output.
void checkResumedSyscall(const Tracee &tracee)
Check whether tracee has an unfinished system call pending.
void stopped(Tracee &tracee) override
The tracee entered group-stop due to a stopping signal.
size_t m_num_tracees
The number of tracees we're currently dealing with.
cosmos::StdLogger m_logger
cosmos ILogger instance for clues library logging.
void disappeared(Tracee &tracee, const cosmos::ChildState &data) override
The tracee disappeared for unclear reasons.
std::set< SystemCallNr > m_syscall_filter
Whitelist of system calls to trace, if any.
void attached(Tracee &tracee) override
The tracee is now properly attached to.
void startNewLine(std::ostream &trace, const Tracee &tracee)
Start a new output line concerning `tracee.
bool isEnabled(const SystemCall *sc) const
Returns true if sc is set and supposed to the printed.
Engine m_engine
libclues main object.
void newExecutionContext(Tracee &tracee, const std::string &old_exe, const cosmos::StringVector &old_cmdline, const std::optional< cosmos::ProcessID > old_pid) override
A new program is executed in the tracee.
cosmos::ProcessID m_main_tracee_pid
The PID of the main process we're tracing (the one we created or attached to).
std::optional< cosmos::WaitStatus > m_main_status
The WaitStatus of the main process we've seen upon it exiting.
bool m_print_pars
Whether to print system call parameters at all (-s 0 disables it).
Base class for traced processes.
Definition Tracee.hxx:39
ABI
System Call ABI.
Definition types.hxx:62