libclues
Linux C++ Tracing Library
Loading...
Searching...
No Matches
SystemCall.cxx
1// C++
2#include <cassert>
3
4// cosmos
5#include <cosmos/error/errno.hxx>
6#include <cosmos/io/ILogger.hxx>
7
8// clues
9#include <clues/logger.hxx>
10#include <clues/syscalls/fs.hxx>
11#include <clues/syscalls/io.hxx>
12#include <clues/syscalls/memory.hxx>
13#include <clues/syscalls/other.hxx>
14#include <clues/syscalls/process.hxx>
15#include <clues/syscalls/signals.hxx>
16#include <clues/syscalls/thread.hxx>
17#include <clues/syscalls/time.hxx>
18#include <clues/sysnrs/generic.hxx>
19#include <clues/SystemCallDB.hxx>
20#include <clues/SystemCall.hxx>
21#include <clues/SystemCallInfo.hxx>
22#include <clues/SystemCallItem.hxx>
23#include <clues/Tracee.hxx>
24#include <clues/types.hxx>
25
26namespace clues {
27
28const char* SystemCall::name(const SystemCallNr nr) {
29 return SYSTEM_CALL_NAMES[cosmos::to_integral(nr)].data();
30}
31
33 return cosmos::to_integral(nr) < SYSTEM_CALL_NAMES.size();
34}
35
39
40void SystemCall::fillParameters(const Tracee &proc, const SystemCallInfo &info) {
41 const auto args = info.entryInfo()->args();
42 std::vector<std::pair<SystemCallItem*, Word>> deferred;
43
44 for (size_t numpar = 0; numpar < m_pars.size(); numpar++) {
45 auto &par = *m_pars[numpar];
46 if (item::is_unused_par(par))
47 continue;
48
49 const auto word = Word{static_cast<Word>(args[numpar])};
50
51 if (par.deferFill()) {
52 deferred.push_back({&par, word});
53 continue;
54 }
55
56 par.fill(proc, word);
57 }
58
59 for (const auto &[item, word]: deferred) {
60 item->fill(proc, word);
61 }
62}
63
64void SystemCall::setEntryInfo(const Tracee &proc, const SystemCallInfo &info) {
65 m_abi = info.abi();
66 m_error.reset();
67 m_info = &info;
68
70
71 fillParameters(proc, info);
72
73 if (check2ndPass(proc)) {
74 fillParameters(proc, info);
75 }
76
77 m_info = nullptr;
78}
79
80bool SystemCall::hasOutParameter() const {
81 for (auto &par: m_pars) {
82 if (par->needsUpdate())
83 return true;
84 }
85
86 return false;
87}
88
89void SystemCall::setExitInfo(const Tracee &proc, const SystemCallInfo &info) {
90 m_info = &info;
91 const auto exit_info = *info.exitInfo();
92
93 if (exit_info.isValue()) {
94 m_return->fill(proc, Word{static_cast<Word>(*exit_info.retVal())});
95 } else {
96 m_error = ErrnoResult{*exit_info.errVal()};
97 }
98
99 for (auto &par: m_pars) {
100 if (par->needsUpdate()) {
101 par->updateData(proc);
102 }
103 }
104
105 if (exit_info.isValue()) {
106 updateFDTracking(proc);
107 }
108
109 m_info = nullptr;
110}
111
112// alias for creating SystemCall instances below
113template <typename T, typename... Args>
114std::shared_ptr<T> new_sys(Args&&... args)
115{
116 return std::make_shared<T>(std::forward<Args>(args)...);
117}
118
119SystemCallPtr create_syscall(const SystemCallNr nr) {
120 switch (nr) {
121 case SystemCallNr::ACCESS: return new_sys<AccessSystemCall>();
122 case SystemCallNr::FACCESSAT: return new_sys<FAccessAtSystemCall>();
123 case SystemCallNr::FACCESSAT2: return new_sys<FAccessAt2SystemCall>();
124 case SystemCallNr::ALARM: return new_sys<AlarmSystemCall>();
125#ifdef CLUES_HAVE_ARCH_PRCTL
126 case SystemCallNr::ARCH_PRCTL: return new_sys<ArchPrctlSystemCall>();
127#endif
128 case SystemCallNr::BRK: return new_sys<BreakSystemCall>();
129 case SystemCallNr::CLOCK_NANOSLEEP: return new_sys<ClockNanoSleepSystemCall>();
130 case SystemCallNr::CLONE: return new_sys<CloneSystemCall>();
131 case SystemCallNr::CLONE3: return new_sys<Clone3SystemCall>();
132 case SystemCallNr::CLOSE: return new_sys<CloseSystemCall>();
133 case SystemCallNr::EXECVE: return new_sys<ExecveSystemCall>();
134 case SystemCallNr::EXECVEAT: return new_sys<ExecveAtSystemCall>();
135 case SystemCallNr::EXIT_GROUP: return new_sys<ExitGroupSystemCall>();
136 case SystemCallNr::FCNTL: [[fallthrough]];
137 case SystemCallNr::FCNTL64: return new_sys<FcntlSystemCall>(nr);
138 case SystemCallNr::FORK: return new_sys<ForkSystemCall>();
139 case SystemCallNr::OLDFSTAT: [[fallthrough]];
140 case SystemCallNr::FSTAT: [[fallthrough]];
141 case SystemCallNr::FSTAT64: return new_sys<FstatSystemCall>(nr);
142 case SystemCallNr::FSTATAT64: [[fallthrough]];
143 case SystemCallNr::NEWFSTATAT: return new_sys<FstatAtSystemCall>(nr);
144 case SystemCallNr::FUTEX: return new_sys<FutexSystemCall>();
145 case SystemCallNr::GETDENTS: [[fallthrough]];
146 case SystemCallNr::GETDENTS64: return new_sys<GetDentsSystemCall>(nr);
147 case SystemCallNr::GETUID: [[fallthrough]];
148 case SystemCallNr::GETUID32: return new_sys<GetUidSystemCall>(nr);
149 case SystemCallNr::GETEGID32: [[fallthrough]];
150 case SystemCallNr::GETEGID: return new_sys<GetEgidSystemCall>(nr);
151 case SystemCallNr::GETEUID32: [[fallthrough]];
152 case SystemCallNr::GETEUID: return new_sys<GetEuidSystemCall>(nr);
153 case SystemCallNr::GETGID32: [[fallthrough]];
154 case SystemCallNr::GETGID: return new_sys<GetGidSystemCall>(nr);
155 case SystemCallNr::GETRLIMIT: return new_sys<GetRlimitSystemCall>();
156 case SystemCallNr::SETRLIMIT: return new_sys<SetRlimitSystemCall>();
157 case SystemCallNr::PRLIMIT64: return new_sys<Prlimit64SystemCall>();
158 case SystemCallNr::GET_ROBUST_LIST: return new_sys<GetRobustListSystemCall>();
159 case SystemCallNr::SET_ROBUST_LIST: return new_sys<SetRobustListSystemCall>();
160 case SystemCallNr::IOCTL: return new_sys<IoCtlSystemCall>();
161 case SystemCallNr::LSTAT: [[fallthrough]];
162 case SystemCallNr::LSTAT64: [[fallthrough]];
163 case SystemCallNr::OLDLSTAT: return new_sys<LstatSystemCall>(nr);
164 case SystemCallNr::MMAP: [[fallthrough]];
165 case SystemCallNr::MMAP2: return new_sys<MmapSystemCall>(nr);
166 case SystemCallNr::MPROTECT: return new_sys<MprotectSystemCall>();
167 case SystemCallNr::MUNMAP: return new_sys<MunmapSystemCall>();
168 case SystemCallNr::NANOSLEEP: return new_sys<NanoSleepSystemCall>();
169 case SystemCallNr::OPENAT: return new_sys<OpenAtSystemCall>();
170 case SystemCallNr::OPEN: return new_sys<OpenSystemCall>();
171 case SystemCallNr::READ: return new_sys<ReadSystemCall>();
172 case SystemCallNr::RESTART_SYSCALL: return new_sys<RestartSystemCall>();
173 case SystemCallNr::RT_SIGACTION: return new_sys<RtSigActionSystemCall>();
174 case SystemCallNr::SIGACTION: return new_sys<SigActionSystemCall>();
175 case SystemCallNr::RT_SIGPROCMASK: return new_sys<RtSigProcMaskSystemCall>();
176 case SystemCallNr::SIGPROCMASK: return new_sys<SigProcMaskSystemCall>();
177 case SystemCallNr::SET_TID_ADDRESS: return new_sys<SetTIDAddressSystemCall>();
178 case SystemCallNr::OLDSTAT: [[fallthrough]];
179 case SystemCallNr::STAT64: [[fallthrough]];
180 case SystemCallNr::STAT: return new_sys<StatSystemCall>(nr);
181 case SystemCallNr::TGKILL: return new_sys<TgKillSystemCall>();
182 case SystemCallNr::WAIT4: return new_sys<Wait4SystemCall>();
183 case SystemCallNr::WRITE: return new_sys<WriteSystemCall>();
184 case SystemCallNr::PIPE: return new_sys<PipeSystemCall>();
185 case SystemCallNr::PIPE2: return new_sys<Pipe2SystemCall>();
186 default: return new_sys<UnknownSystemCall>(nr);
187 }
188}
189
190void SystemCall::dropFD(const Tracee &proc, const cosmos::FileNum num) {
191 proc.dropFD(num);
192}
193
194void SystemCall::trackFD(const Tracee &proc, FDInfo &&info) {
195 proc.trackFD(std::move(info));
196}
197
198} // end ns
199
200std::ostream& operator<<(std::ostream &o, const clues::SystemCall &sc) {
201 o << sc.name() << " (" << cosmos::to_integral(sc.callNr()) << "): " << sc.numPars() << " parameters";
202
203 for (const auto &par: sc.m_pars) {
204 o << "\n\t" << *par;
205 }
206
207 o << "\n\tResult -> " << *(sc.m_return);
208
209 return o;
210}
An errno system call result.
Extended ptrace system call state information.
Access to System Call Data.
SystemCallItemPtr m_return
The return value of the system call.
std::string_view name() const
Returns the system call's human readable name.
const SystemCallInfo * m_info
Current system call info during entry/exit processing, nullptr otherwise.
size_t numPars() const
Returns the number of parameters for this system call.
virtual void prepareNewSystemCall()
Perform any necessary actions before processing a new system call entry event.
void setEntryInfo(const Tracee &proc, const SystemCallInfo &info)
Update the stored parameter values from the given tracee.
const std::string_view m_name
The basic name of the system call.
SystemCall(const SystemCallNr nr)
Instantiates a new SystemCall object with given properties.
SystemCallNr callNr() const
Returns the system call table number for this system call.
std::optional< ErrnoResult > m_error
If the system call fails, this is the error code.
ABI m_abi
The current system call ABI which is in effect.
ParameterVector m_pars
The array of system call parameters, if any.
static bool validNr(const SystemCallNr nr)
Returns whether the given system call number is in a valid range.
SystemCallNr m_nr
The raw system call number of the system call.
void setExitInfo(const Tracee &proc, const SystemCallInfo &info)
Update possible out and return parameter values from the given tracee.
virtual void updateFDTracking(const Tracee &proc)
Update file descriptor tracking.
virtual bool check2ndPass(const Tracee &)
Check whether a second pass needs to be made processing parameters.
Base class for traced processes.
Definition Tracee.hxx:39
SystemCallPtr create_syscall(const SystemCallNr nr)
Creates a dynamically allocated SystemCall instance for the given system call number.
SystemCallNr
Abstract system call number usable across architectures and ABIs.
Definition generic.hxx:29
Word
An integer that is able to hold a word for the current architecture.
Definition types.hxx:38
Contextual information about a file descriptor in a Tracee.
Definition types.hxx:75