libclues
Linux C++ Tracing Library
Loading...
Searching...
No Matches
clues::item::FLockParameter Class Reference

Corresponds to struct flock Used with fcntl() F_*LK operations. More...

#include <fcntl.hxx>

+ Inheritance diagram for clues::item::FLockParameter:

Public Member Functions

std::string str () const override
 Returns a human readable string representation of the item.
 
const std::optional< cosmos::FileLock > & lock () const
 Access to the extracted FileLock data.
 
- Public Member Functions inherited from clues::item::PointerValue
 PointerValue (const ItemType type, const std::string_view short_name, const std::string_view long_name)
 
- Public Member Functions inherited from clues::SystemCallItem
 SystemCallItem (const ItemType type, const std::string_view short_name={}, const std::string_view long_name={})
 Constructs a new SystemCallItem.
 
auto type () const
 
bool isIn () const
 
bool isOut () const
 
bool isInOut () const
 
bool isReturnValue () const
 
void fill (const Tracee &proc, const Word word)
 Fills the item from the given register data.
 
bool needsUpdate () const
 Returns whether the item needs to be updated after the system call is finished.
 
std::string_view shortName () const
 Returns the friendly short name for this item.
 
std::string_view longName () const
 Returns the friendly long name for this item, if available, else the short name.
 
auto hasLongName () const
 
bool isZero () const
 Returns whether the parameter is set to 0 / NULL.
 
Word value () const
 Returns the currently stored raw value of the item.
 
template<typename OTHER>
OTHER valueAs () const
 Helper to cast the strongly typed Word m_val to other strong enum types.
 
ForeignPtr asPtr () const
 
Flags flags () const
 
bool deferFill () const
 

Protected Member Functions

void processValue (const Tracee &proc) override
 Processes the value stored in m_val acc. to the actual item type.
 
void updateData (const Tracee &proc) override
 Called upon exit of the system call to update possible out parameters.
 
- Protected Member Functions inherited from clues::SystemCallItem
void setSystemCall (const SystemCall &sc)
 Sets the system call context this item is a part of.
 

Protected Attributes

std::optional< cosmos::FileLock > m_lock
 
- Protected Attributes inherited from clues::SystemCallItem
const SystemCallm_call = nullptr
 The system call context this item part of.
 
const ItemType m_type
 The type of item.
 
std::string_view m_short_name
 A human readable short name for the item, should be one word only.
 
std::string_view m_long_name
 A human readable longer name for the item.
 
Word m_val
 The raw register value for the item.
 
Flags m_flags
 Flags influencing the processing of the item.
 

Additional Inherited Members

- Public Types inherited from clues::SystemCallItem
enum class  Flag { DEFER_FILL = 1 << 0 }
 
using Flags = cosmos::BitMask<Flag>
 

Detailed Description

Corresponds to struct flock Used with fcntl() F_*LK operations.

Definition at line 116 of file fcntl.hxx.

Constructor & Destructor Documentation

◆ FLockParameter()

clues::item::FLockParameter::FLockParameter ( )
inlineexplicit

Definition at line 119 of file fcntl.hxx.

119 :
120 // this can be PARAM_IN and PARAM_IN_OUT, but we
121 // simply claim it's always IN_OUT
122 PointerValue{ItemType::PARAM_IN_OUT, "flock", "struct flock"} {
123 }
@ PARAM_IN_OUT
Both an input and output parameter.

Member Function Documentation

◆ lock()

const std::optional< cosmos::FileLock > & clues::item::FLockParameter::lock ( ) const
inline

Access to the extracted FileLock data.

This can be unassigned in case no system call was yet executed, or if fetching the data from the Tracee failed for some reason.

Definition at line 132 of file fcntl.hxx.

132 {
133 return m_lock;
134 }

◆ processValue()

void clues::item::FLockParameter::processValue ( const Tracee & )
overrideprotectedvirtual

Processes the value stored in m_val acc. to the actual item type.

This function is called for all parameter types upon entry to a system call, and for ItemType::RETVAL upon exit from a system call.

For parameters of ItemType::PARAM_OUT this callback can be used to reset any stored data to be filled in later when updateData() is called.

Reimplemented from clues::SystemCallItem.

Definition at line 143 of file fcntl.cxx.

143 {
144 /* all flock related operations provide input, so unconditionally
145 * process it */
146
147 /*
148 * The situation with fcntl() and fcntl64() is quite messy. fcntl64()
149 * only exists on 32-bit platforms like I386. The difference is only
150 * in the data structure used with the GETLK and SETLK operations.
151 *
152 * On 64-bit targets, with the single `fcntl()` system call these
153 * operations always take `struct flock` with 64-bit wide `off_t`. On
154 * i386 `fcntl()` takes `struct flock` with 32-bit wide `off_t`
155 * fields. `fcntl64` on the other hand can support both, the 32-bit
156 * wide and 64-bit wide `off_t` fields. To differentiate this,
157 * additional operations GETLK64, SETLK64 and SETLKW64 have been
158 * introduced. These operations are _only_ supported in `fcntl64` on
159 * 32-bit targets.
160 *
161 * To make things worse, the definition of F_GETLK and F_GETLK64 we
162 * get from the userspace headers depends on the following factors:
163 *
164 * - in a 64-bit compilation environment they're both always
165 * set to 5,6,7, because `fcntl()` always uses struct
166 * flock64 with 64-bit wide `off_t.
167 * - in a 32-bit compilation environment with
168 * _FILE_OFFSET_BITS=64 they're always set to 12,13,14 so
169 * that fcntl64 with struct flock64 is always used transparently.
170 * - in a 32-bit compilation environment _without_
171 * _FILE_OFFSET_BITS=64 F_GETLK & friends are set to 5,6,7
172 * and F_GETLK64 & friends are set to 12,13,14 allowing to
173 * call regular fcntl() with 32-bit wide `off_t` and fcntl64() with
174 * 32-bit or 64-bit `off_t`.
175 *
176 * Thus these constants are a moving target depending on a lot
177 * of factors, which gets even more worse when a 64-bit tracer
178 * is looking at a 32-bit emulation binary. For this reason we are
179 * using our own literal values in FcntlOperation::Oper for the LK
180 * family of operations.
181 *
182 * The rule of thumb when looking at the raw system call is that on
183 * 64-bit targets either LK operation is always expecting a 64-bit
184 * `off_t` struct. On a 32-bit target like I386 the literal values
185 * 5,6,7 are always expecting a 32-bit `off_t` and the literal values
186 * 12,13,14 are always expecting a 64-bit `off_t` (and are only
187 * supported in `fcntl64()`).
188 *
189 * The OFD_ locks are not affected by this, they always use a 64-bit
190 * wide `off_t` in `struct flock`.
191 */
192
193 cosmos::DeferGuard reset_lock{[this]() { m_lock.reset(); }};
194
195 auto assign_data = [this, &reset_lock](const auto &lock) {
196 if (!m_lock) {
197 m_lock = std::make_optional<cosmos::FileLock>(cosmos::FileLock::Type::READ_LOCK);
198 }
199
200 m_lock->l_type = lock.l_type;
201 m_lock->l_whence = lock.l_whence;
202 m_lock->l_start = lock.l_start;
203 m_lock->l_len = lock.l_len;
204 m_lock->l_pid = lock.l_pid;
205 reset_lock.disarm();
206 };
207
208 auto fetch_lock = [this, assign_data, &proc]<typename FLOCK>() {
209 FLOCK lock;
210 if (proc.readStruct(asPtr(), lock)) {
211 assign_data(lock);
212 }
213 };
214
215 if (const auto abi = m_call->abi(); abi != ABI::I386) {
216 /*
217 * if the target ABI is 64-bit based then it's easy, simply
218 * use the only supported native 64-bit struct
219 */
220 fetch_lock.operator()<kernel::flock64>();
221 return;
222 }
223
224 // on i386 things get complicated
225
226 if (const auto sysnr = m_call->callNr(); sysnr != SystemCallNr::FCNTL64) {
227 /*
228 * for the old fcntl() call only the 32-bit `off_t` structure
229 * is supported. This one also has no alignment issues if the
230 * target is a 32-bit emulation binary.
231 */
232 fetch_lock.operator()<kernel::flock32>();
233 return;
234 }
235
236 /*
237 * for the fcntl64() call both 32-bit and 64-bit `off_t` are supported
238 * depending on the value found in the `op` parameter. Also we need to
239 * consider alignment for flock64 in case we're dealing with an
240 * emulation binary.
241 */
242 auto fcntl_sys = dynamic_cast<const FcntlSystemCall*>(m_call);
243 if (!fcntl_sys)
244 // alien system call?
245 return;
246
247 if (fcntl_sys->operation.isLock64()) {
248 // either native 32-bit tracing or the target is a 32-bit
249 // emulation binary, we need i386 alignment in both cases
250 fetch_lock.operator()<kernel::flock64_i386>();
251 } else {
252 /*
253 * with the 32-bit flock no alignment issues should occur when
254 * tracing emulation binaries
255 */
256 fetch_lock.operator()<kernel::flock32>();
257 }
258}
const SystemCall * m_call
The system call context this item part of.
const std::optional< cosmos::FileLock > & lock() const
Access to the extracted FileLock data.
Definition fcntl.hxx:132

◆ str()

std::string clues::item::FLockParameter::str ( ) const
overridevirtual

Returns a human readable string representation of the item.

This member function should be specialized in derived classes to output the item's data in a fashion suitable for the concrete item type.

Reimplemented from clues::SystemCallItem.

Definition at line 280 of file fcntl.cxx.

280 {
281 if (!m_lock) {
282 return "<invalid>";
283 }
284
285 auto whence_str = [](short whence) {
286 switch (whence) {
287 CASE_ENUM_TO_STR(SEEK_SET);
288 CASE_ENUM_TO_STR(SEEK_CUR);
289 CASE_ENUM_TO_STR(SEEK_END);
290 default: return "???";
291 }
292 };
293
294 return cosmos::sprintf("{l_type=%s, l_whence=%s, l_start=%jd, l_len=%jd, l_pid=%d}",
295 lock_type_to_str(cosmos::to_integral(m_lock->type())).data(),
296 whence_str(cosmos::to_integral(m_lock->whence())),
297 m_lock->start(),
298 m_lock->start(),
299 cosmos::to_integral(m_lock->pid())
300 );
301}

◆ updateData()

void clues::item::FLockParameter::updateData ( const Tracee & t)
overrideprotectedvirtual

Called upon exit of the system call to update possible out parameters.

This function is called for parameters of ItemType::PARAM_OUT and ItemType::PARAM_IN_OUT upon system call exit to update the data from the values returned from the system call.

The default implementation calls processValue() to allow to share the same data processing code for input and output for item types that support both.

This function is called regardless of system call success or error, so it can happen that there is no valid data returned by the kernel or pointers in userspace are broken. Implementations should take this into consideration when operating on the data.

Reimplemented from clues::SystemCallItem.

Definition at line 260 of file fcntl.cxx.

260 {
261 const auto fcntl_sc = dynamic_cast<const FcntlSystemCall*>(m_call);
262 if (!fcntl_sc || fcntl_sc->operation.operation() != item::FcntlOperation::Oper::GETLK) {
263 // only the F_GETLK operation causes changes on output
264 return;
265 }
266
267 processValue(proc);
268}
void processValue(const Tracee &proc) override
Processes the value stored in m_val acc. to the actual item type.
Definition fcntl.cxx:143

Member Data Documentation

◆ m_lock

std::optional<cosmos::FileLock> clues::item::FLockParameter::m_lock
protected

Definition at line 144 of file fcntl.hxx.


The documentation for this class was generated from the following files: