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 <[email protected]> Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
@@ -13,7 +13,7 @@ SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ;
|
|||||||
SubDirHdrs $(TARGET_COMMON_DEBUG_LOCATE_TARGET) ;
|
SubDirHdrs $(TARGET_COMMON_DEBUG_LOCATE_TARGET) ;
|
||||||
|
|
||||||
local straceSources =
|
local straceSources =
|
||||||
Context.cpp ioctl.cpp MemoryReader.cpp NetworkTypes.cpp
|
Context.cpp fcntl.cpp ioctl.cpp MemoryReader.cpp NetworkTypes.cpp
|
||||||
strace.cpp TypeHandler.cpp
|
strace.cpp TypeHandler.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
@@ -111,6 +112,62 @@ TypeHandlerImpl<fd_set *>::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<typename value_t>
|
template<typename value_t>
|
||||||
static inline value_t
|
static inline value_t
|
||||||
get_value(const void *address)
|
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<typename Type>
|
template<typename Type>
|
||||||
class SpecializedPointerTypeHandler : public TypeHandler {
|
class SpecializedPointerTypeHandler : public TypeHandler {
|
||||||
string GetParameterValue(Context &context, Parameter *,
|
string GetParameterValue(Context &context, Parameter *,
|
||||||
@@ -633,9 +705,11 @@ class SpecializedPointerTypeHandler : public TypeHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_TYPE(fdset_ptr, fd_set *);
|
DEFINE_TYPE(fdset_ptr, fd_set *);
|
||||||
|
POINTER_TYPE(flock_ptr, flock);
|
||||||
POINTER_TYPE(ifconf_ptr, ifconf);
|
POINTER_TYPE(ifconf_ptr, ifconf);
|
||||||
POINTER_TYPE(ifreq_ptr, ifreq);
|
POINTER_TYPE(ifreq_ptr, ifreq);
|
||||||
DEFINE_TYPE(pollfd_ptr, pollfd *);
|
DEFINE_TYPE(pollfd_ptr, pollfd *);
|
||||||
|
POINTER_TYPE(siginfo_t_ptr, siginfo_t);
|
||||||
#if 0
|
#if 0
|
||||||
POINTER_TYPE(message_args_ptr, message_args);
|
POINTER_TYPE(message_args_ptr, message_args);
|
||||||
POINTER_TYPE(msghdr_ptr, msghdr);
|
POINTER_TYPE(msghdr_ptr, msghdr);
|
||||||
|
|||||||
@@ -42,7 +42,9 @@ public:
|
|||||||
Parameter(string name, int32 offset, string typeName, TypeHandler *handler)
|
Parameter(string name, int32 offset, string typeName, TypeHandler *handler)
|
||||||
: Type(typeName, handler),
|
: Type(typeName, handler),
|
||||||
fName(name),
|
fName(name),
|
||||||
fOffset(offset)
|
fOffset(offset),
|
||||||
|
fInOut(false),
|
||||||
|
fOut(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,11 +52,14 @@ public:
|
|||||||
int32 Offset() const { return fOffset; }
|
int32 Offset() const { return fOffset; }
|
||||||
bool InOut() const { return fInOut; }
|
bool InOut() const { return fInOut; }
|
||||||
void SetInOut(bool inout) { fInOut = inout; }
|
void SetInOut(bool inout) { fInOut = inout; }
|
||||||
|
bool Out() const { return fOut; }
|
||||||
|
void SetOut(bool out) { fOut = out; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
string fName;
|
string fName;
|
||||||
int32 fOffset;
|
int32 fOffset;
|
||||||
bool fInOut;
|
bool fInOut;
|
||||||
|
bool fOut;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Syscall
|
// Syscall
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ struct TypeHandlerFactory<const char*> {
|
|||||||
} \
|
} \
|
||||||
|
|
||||||
struct fd_set;
|
struct fd_set;
|
||||||
|
struct flock;
|
||||||
struct ifconf;
|
struct ifconf;
|
||||||
struct ifreq;
|
struct ifreq;
|
||||||
struct message_args;
|
struct message_args;
|
||||||
@@ -107,10 +108,12 @@ struct socket_args;
|
|||||||
struct sockopt_args;
|
struct sockopt_args;
|
||||||
|
|
||||||
DEFINE_FACTORY(fdset_ptr, fd_set *);
|
DEFINE_FACTORY(fdset_ptr, fd_set *);
|
||||||
|
DEFINE_FACTORY(flock_ptr, flock *);
|
||||||
DEFINE_FACTORY(ifconf_ptr, ifconf *);
|
DEFINE_FACTORY(ifconf_ptr, ifconf *);
|
||||||
DEFINE_FACTORY(ifreq_ptr, ifreq *);
|
DEFINE_FACTORY(ifreq_ptr, ifreq *);
|
||||||
DEFINE_FACTORY(message_args_ptr, message_args *);
|
DEFINE_FACTORY(message_args_ptr, message_args *);
|
||||||
DEFINE_FACTORY(pollfd_ptr, pollfd *);
|
DEFINE_FACTORY(pollfd_ptr, pollfd *);
|
||||||
|
DEFINE_FACTORY(siginfo_t_ptr, siginfo_t *);
|
||||||
DEFINE_FACTORY(sockaddr_args_ptr, sockaddr_args *);
|
DEFINE_FACTORY(sockaddr_args_ptr, sockaddr_args *);
|
||||||
DEFINE_FACTORY(socket_args_ptr, socket_args *);
|
DEFINE_FACTORY(socket_args_ptr, socket_args *);
|
||||||
DEFINE_FACTORY(sockopt_args_ptr, sockopt_args *);
|
DEFINE_FACTORY(sockopt_args_ptr, sockopt_args *);
|
||||||
|
|||||||
@@ -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, [email protected]
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#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<type>::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<void *>::Create()));
|
||||||
|
}
|
||||||
|
|
||||||
@@ -260,8 +260,10 @@ patch_syscalls()
|
|||||||
// instead of having this done here manually we should either add the
|
// instead of having this done here manually we should either add the
|
||||||
// patching step to gensyscalls also manually or add metadata to
|
// patching step to gensyscalls also manually or add metadata to
|
||||||
// kernel/syscalls.h and have it parsed automatically
|
// kernel/syscalls.h and have it parsed automatically
|
||||||
|
extern void patch_fcntl();
|
||||||
extern void patch_ioctl();
|
extern void patch_ioctl();
|
||||||
|
|
||||||
|
patch_fcntl();
|
||||||
patch_ioctl();
|
patch_ioctl();
|
||||||
|
|
||||||
Syscall *poll = get_syscall("_kern_poll");
|
Syscall *poll = get_syscall("_kern_poll");
|
||||||
@@ -271,6 +273,10 @@ patch_syscalls()
|
|||||||
select->ParameterAt(1)->SetInOut(true);
|
select->ParameterAt(1)->SetInOut(true);
|
||||||
select->ParameterAt(2)->SetInOut(true);
|
select->ParameterAt(2)->SetInOut(true);
|
||||||
select->ParameterAt(3)->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++) {
|
for (int32 i = 0; i < count; i++) {
|
||||||
// get the value
|
// get the value
|
||||||
Parameter *parameter = syscall->ParameterAt(i);
|
Parameter *parameter = syscall->ParameterAt(i);
|
||||||
|
if (parameter->Out())
|
||||||
|
continue;
|
||||||
TypeHandler *handler = parameter->Handler();
|
TypeHandler *handler = parameter->Handler();
|
||||||
::string value =
|
::string value =
|
||||||
handler->GetParameterValue(ctx, parameter,
|
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++) {
|
for (int32 i = 0; i < count; i++) {
|
||||||
// get the value
|
// get the value
|
||||||
Parameter *parameter = syscall->ParameterAt(i);
|
Parameter *parameter = syscall->ParameterAt(i);
|
||||||
if (!parameter->InOut())
|
if (!parameter->InOut() && !parameter->Out())
|
||||||
continue;
|
continue;
|
||||||
TypeHandler *handler = parameter->Handler();
|
TypeHandler *handler = parameter->Handler();
|
||||||
::string value =
|
::string value =
|
||||||
|
|||||||
Reference in New Issue
Block a user