From 1d2cf139a89f4c93fdd28454c9098931c2846ec8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Tue, 26 Apr 2022 14:50:17 +0200 Subject: [PATCH] strace: trace fcntl and wait_for_child syscalls parameters Change-Id: I774e8343139a2bdb3c2f60f37cab3a7207739c7c Reviewed-on: https://review.haiku-os.org/c/haiku/+/5251 Reviewed-by: waddlesplash Tested-by: Commit checker robot --- src/bin/debug/strace/Jamfile | 2 +- src/bin/debug/strace/NetworkTypes.cpp | 74 +++++++++++++++++++++++++++ src/bin/debug/strace/Syscall.h | 7 ++- src/bin/debug/strace/TypeHandler.h | 3 ++ src/bin/debug/strace/fcntl.cpp | 61 ++++++++++++++++++++++ src/bin/debug/strace/strace.cpp | 10 +++- 6 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 src/bin/debug/strace/fcntl.cpp diff --git a/src/bin/debug/strace/Jamfile b/src/bin/debug/strace/Jamfile index 527190e3e0..2de41d2435 100644 --- a/src/bin/debug/strace/Jamfile +++ b/src/bin/debug/strace/Jamfile @@ -13,7 +13,7 @@ SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ; SubDirHdrs $(TARGET_COMMON_DEBUG_LOCATE_TARGET) ; local straceSources = - Context.cpp ioctl.cpp MemoryReader.cpp NetworkTypes.cpp + Context.cpp fcntl.cpp ioctl.cpp MemoryReader.cpp NetworkTypes.cpp strace.cpp TypeHandler.cpp ; diff --git a/src/bin/debug/strace/NetworkTypes.cpp b/src/bin/debug/strace/NetworkTypes.cpp index 3a5d71c16f..bb1544a357 100644 --- a/src/bin/debug/strace/NetworkTypes.cpp +++ b/src/bin/debug/strace/NetworkTypes.cpp @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -111,6 +112,62 @@ TypeHandlerImpl::GetReturnValue(Context &context, uint64 value) } +static string +format_ltype(Context &context, int ltype) +{ + if (context.GetContents(Context::ENUMERATIONS)) { +#define LTYPE(type) \ + case type: \ + return #type + + switch (ltype) { + LTYPE(F_RDLCK); + LTYPE(F_UNLCK); + LTYPE(F_WRLCK); + } + } + + return context.FormatSigned(ltype); +} + + +static string +format_lwhence(Context &context, int lwhence) +{ + if (context.GetContents(Context::ENUMERATIONS)) { +#define LWHENCE(whence) \ + case whence: \ + return #whence + + switch (lwhence) { + LWHENCE(SEEK_SET); + LWHENCE(SEEK_CUR); + LWHENCE(SEEK_END); + LWHENCE(SEEK_DATA); + LWHENCE(SEEK_HOLE); + } + } + + return context.FormatSigned(lwhence); +} + + + +static string +format_pointer(Context &context, flock *lock) +{ + string r; + + r = "l_type=" + format_ltype(context, lock->l_type) + ", "; + r += "l_whence=" + format_lwhence(context, lock->l_whence) + ", "; + r += "l_start=" + context.FormatSigned(lock->l_start) + ", "; + r += "l_len=" + context.FormatSigned(lock->l_len); + + return r; +} + + + template static inline value_t get_value(const void *address) @@ -606,6 +663,21 @@ format_pointer(Context &context, ifconf *conf) } +static string +format_pointer(Context &context, siginfo_t *info) +{ + string r; + + switch (info->si_code) { + case CLD_EXITED: + r = "WIFEXITED(s) && WEXITSTATUS(s) == " + context.FormatUnsigned(info->si_status & 0xff); + break; + } + return r; +} + + + template class SpecializedPointerTypeHandler : public TypeHandler { string GetParameterValue(Context &context, Parameter *, @@ -633,9 +705,11 @@ class SpecializedPointerTypeHandler : public TypeHandler { } DEFINE_TYPE(fdset_ptr, fd_set *); +POINTER_TYPE(flock_ptr, flock); POINTER_TYPE(ifconf_ptr, ifconf); POINTER_TYPE(ifreq_ptr, ifreq); DEFINE_TYPE(pollfd_ptr, pollfd *); +POINTER_TYPE(siginfo_t_ptr, siginfo_t); #if 0 POINTER_TYPE(message_args_ptr, message_args); POINTER_TYPE(msghdr_ptr, msghdr); diff --git a/src/bin/debug/strace/Syscall.h b/src/bin/debug/strace/Syscall.h index 37aa6a547f..6b81b4e6fe 100644 --- a/src/bin/debug/strace/Syscall.h +++ b/src/bin/debug/strace/Syscall.h @@ -42,7 +42,9 @@ public: Parameter(string name, int32 offset, string typeName, TypeHandler *handler) : Type(typeName, handler), fName(name), - fOffset(offset) + fOffset(offset), + fInOut(false), + fOut(false) { } @@ -50,11 +52,14 @@ public: int32 Offset() const { return fOffset; } bool InOut() const { return fInOut; } void SetInOut(bool inout) { fInOut = inout; } + bool Out() const { return fOut; } + void SetOut(bool out) { fOut = out; } private: string fName; int32 fOffset; bool fInOut; + bool fOut; }; // Syscall diff --git a/src/bin/debug/strace/TypeHandler.h b/src/bin/debug/strace/TypeHandler.h index ce7367303d..d52866342e 100644 --- a/src/bin/debug/strace/TypeHandler.h +++ b/src/bin/debug/strace/TypeHandler.h @@ -98,6 +98,7 @@ struct TypeHandlerFactory { } \ struct fd_set; +struct flock; struct ifconf; struct ifreq; struct message_args; @@ -107,10 +108,12 @@ struct socket_args; struct sockopt_args; DEFINE_FACTORY(fdset_ptr, fd_set *); +DEFINE_FACTORY(flock_ptr, flock *); DEFINE_FACTORY(ifconf_ptr, ifconf *); DEFINE_FACTORY(ifreq_ptr, ifreq *); DEFINE_FACTORY(message_args_ptr, message_args *); DEFINE_FACTORY(pollfd_ptr, pollfd *); +DEFINE_FACTORY(siginfo_t_ptr, siginfo_t *); DEFINE_FACTORY(sockaddr_args_ptr, sockaddr_args *); DEFINE_FACTORY(socket_args_ptr, socket_args *); DEFINE_FACTORY(sockopt_args_ptr, sockopt_args *); diff --git a/src/bin/debug/strace/fcntl.cpp b/src/bin/debug/strace/fcntl.cpp new file mode 100644 index 0000000000..08bc8aa9cc --- /dev/null +++ b/src/bin/debug/strace/fcntl.cpp @@ -0,0 +1,61 @@ +/* + * Copyright 2022, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Copyright 2022, Jérôme Duval, jerome.duval@gmail.com + */ + + +#include + +#include "strace.h" +#include "Syscall.h" +#include "TypeHandler.h" + + +struct fcntl_info { + unsigned int index; + const char *name; + TypeHandler *handler; +}; + +#define FCNTL_INFO_ENTRY(name) \ + { name, #name, NULL } + +#define FCNTL_INFO_ENTRY_TYPE(name, type) \ + { name, #name, TypeHandlerFactory::Create() } + +static const fcntl_info kFcntls[] = { + FCNTL_INFO_ENTRY_TYPE(F_DUPFD, int), + FCNTL_INFO_ENTRY(F_GETFD), + FCNTL_INFO_ENTRY_TYPE(F_SETFD, int), + FCNTL_INFO_ENTRY(F_GETFL), + FCNTL_INFO_ENTRY_TYPE(F_SETFL, int), + FCNTL_INFO_ENTRY_TYPE(F_GETLK, struct flock*), + FCNTL_INFO_ENTRY_TYPE(F_SETLK, struct flock*), + FCNTL_INFO_ENTRY_TYPE(F_SETLKW, struct flock*), + { 0, NULL, NULL } +}; + +static EnumTypeHandler::EnumMap kFcntlNames; +static TypeHandlerSelector::SelectMap kFcntlTypeHandlers; + +void +patch_fcntl() +{ + for (int i = 0; kFcntls[i].name != NULL; i++) { + kFcntlNames[kFcntls[i].index] = kFcntls[i].name; + if (kFcntls[i].handler != NULL) + kFcntlTypeHandlers[kFcntls[i].index] = kFcntls[i].handler; + } + + Syscall *fcntl = get_syscall("_kern_fcntl"); + + fcntl->GetParameter("op")->SetHandler( + new EnumTypeHandler(kFcntlNames)); + fcntl->GetParameter("argument")->SetHandler( + new TypeHandlerSelector(kFcntlTypeHandlers, + 1, TypeHandlerFactory::Create())); +} + diff --git a/src/bin/debug/strace/strace.cpp b/src/bin/debug/strace/strace.cpp index f34688f6a3..431bd649a8 100644 --- a/src/bin/debug/strace/strace.cpp +++ b/src/bin/debug/strace/strace.cpp @@ -260,8 +260,10 @@ patch_syscalls() // instead of having this done here manually we should either add the // patching step to gensyscalls also manually or add metadata to // kernel/syscalls.h and have it parsed automatically + extern void patch_fcntl(); extern void patch_ioctl(); + patch_fcntl(); patch_ioctl(); Syscall *poll = get_syscall("_kern_poll"); @@ -271,6 +273,10 @@ patch_syscalls() select->ParameterAt(1)->SetInOut(true); select->ParameterAt(2)->SetInOut(true); select->ParameterAt(3)->SetInOut(true); + + Syscall *wait = get_syscall("_kern_wait_for_child"); + wait->ParameterAt(2)->SetOut(true); + wait->ParameterAt(3)->SetOut(true); } @@ -379,6 +385,8 @@ print_syscall(FILE *outputFile, Syscall* syscall, debug_pre_syscall &message, for (int32 i = 0; i < count; i++) { // get the value Parameter *parameter = syscall->ParameterAt(i); + if (parameter->Out()) + continue; TypeHandler *handler = parameter->Handler(); ::string value = handler->GetParameterValue(ctx, parameter, @@ -455,7 +463,7 @@ print_syscall(FILE *outputFile, Syscall* syscall, debug_post_syscall &message, for (int32 i = 0; i < count; i++) { // get the value Parameter *parameter = syscall->ParameterAt(i); - if (!parameter->InOut()) + if (!parameter->InOut() && !parameter->Out()) continue; TypeHandler *handler = parameter->Handler(); ::string value =