diff --git a/src/bin/strace/Jamfile b/src/bin/strace/Jamfile index 4638383a7d..6ee19c6888 100644 --- a/src/bin/strace/Jamfile +++ b/src/bin/strace/Jamfile @@ -3,11 +3,12 @@ SubDir HAIKU_TOP src bin strace ; UseArchHeaders $(TARGET_ARCH) ; UsePrivateHeaders kernel ; UsePrivateHeaders shared ; +UsePrivateHeaders net ; # find headers generated by gensyscalls SubDirHdrs $(TARGET_COMMON_DEBUG_LOCATE_TARGET) ; -local straceSources = strace.cpp MemoryReader.cpp TypeHandler.cpp ; +local straceSources = strace.cpp MemoryReader.cpp TypeHandler.cpp ioctl.cpp ; # Our compiler badly chokes when compiling the generated file. So will # split up the job into 20 pieces. diff --git a/src/bin/strace/Syscall.h b/src/bin/strace/Syscall.h index a59904ea76..b7b00207b9 100644 --- a/src/bin/strace/Syscall.h +++ b/src/bin/strace/Syscall.h @@ -106,10 +106,50 @@ public: return NULL; } + static Syscall *GetSyscall(const char *); + private: string fName; Type *fReturnType; vector fParameters; }; +class Context { +public: + enum { + STRINGS = 1 << 0, + ENUMERATIONS = 1 << 1, + SIMPLE_STRUCTS = 1 << 2, + COMPLEX_STRUCTS = 1 << 3, + ALL = 0xffffffff + }; + + Context(Syscall *sc, char *data, MemoryReader &reader, + uint32 flags, bool decimal) + : fSyscall(sc), fData(data), fReader(reader), + fFlags(flags), fDecimal(decimal) {} + + Parameter *GetSibling(int32 index) const { + return fSyscall->ParameterAt(index); + } + + const void *GetValue(Parameter *param) const { + return fData + param->Offset(); + } + + MemoryReader &Reader() { return fReader; } + bool GetContents(uint32 what) const { return fFlags & what; } + + string FormatSigned(int64 value, const char *modifier = "ll") const; + string FormatUnsigned(uint64 value) const; + string FormatFlags(uint64 value) const; + +private: + Syscall *fSyscall; + char *fData; + MemoryReader &fReader; + uint32 fFlags; + bool fDecimal; +}; + #endif // STRACE_SYSCALL_H diff --git a/src/bin/strace/TypeHandler.cpp b/src/bin/strace/TypeHandler.cpp index c6d1d97e9e..2a9e57c896 100644 --- a/src/bin/strace/TypeHandler.cpp +++ b/src/bin/strace/TypeHandler.cpp @@ -7,47 +7,38 @@ * Hugo Santos */ -#include "MemoryReader.h" #include "TypeHandler.h" +// headers required for network structures +#include +#include +#include + +#include + +#include "MemoryReader.h" +#include "Syscall.h" // TypeHandlerImpl template class TypeHandlerImpl : public TypeHandler { public: - virtual string GetParameterValue(const void *address, bool getContents, - MemoryReader &reader); - - virtual string GetReturnValue(uint64 value, bool getContents, - MemoryReader &reader); + virtual string GetParameterValue(Context &, Parameter *, const void *); + virtual string GetReturnValue(Context &, uint64 value); }; - -// #pragma mark - - -// get_number_value template -static inline -string -get_number_value(value_t value, const char *format) -{ - char buffer[32]; - sprintf(buffer, format, value); - return buffer; -} - -// get_number_value -template -static inline -string -get_number_value(const void *address, const char *format) +static inline value_t +get_value(const void *address) { if (sizeof(align_t) > sizeof(value_t)) - return get_number_value(value_t(*(align_t*)address), format); + return value_t(*(align_t*)address); else - return get_number_value(*(value_t*)address, format); + return *(value_t*)address; } +// #pragma mark - + // get_pointer_value static inline string @@ -82,13 +73,6 @@ create_string_type_handler() return new TypeHandlerImpl(); } -TypeHandler * -create_fdset_type_handler() -{ - return new TypeHandlerImpl(); -} - - // #pragma mark - // complete specializations @@ -96,16 +80,14 @@ create_fdset_type_handler() // void template<> string -TypeHandlerImpl::GetParameterValue(const void *address, bool getContents, - MemoryReader &reader) +TypeHandlerImpl::GetParameterValue(Context &, Parameter *, const void *) { return "void"; } template<> string -TypeHandlerImpl::GetReturnValue(uint64 value, bool getContents, - MemoryReader &reader) +TypeHandlerImpl::GetReturnValue(Context &, uint64 value) { return ""; } @@ -120,16 +102,15 @@ TypeHandlerFactory::Create() // bool template<> string -TypeHandlerImpl::GetParameterValue(const void *address, bool getContents, - MemoryReader &reader) +TypeHandlerImpl::GetParameterValue(Context &, Parameter *, + const void *address) { - return (*(align_t*)address ? "true" : "false"); + return (*(const align_t*)address ? "true" : "false"); } template<> string -TypeHandlerImpl::GetReturnValue(uint64 value, bool getContents, - MemoryReader &reader) +TypeHandlerImpl::GetReturnValue(Context &, uint64 value) { return (value ? "true" : "false"); } @@ -141,223 +122,6 @@ TypeHandlerFactory::Create() return new TypeHandlerImpl(); } -// char -template<> -string -TypeHandlerImpl::GetParameterValue(const void *address, bool getContents, - MemoryReader &reader) -{ - return get_number_value(address, "0x%x"); -} - -template<> -string -TypeHandlerImpl::GetReturnValue(uint64 value, bool getContents, - MemoryReader &reader) -{ - return get_number_value(value, "0x%x"); -} - -template<> -TypeHandler * -TypeHandlerFactory::Create() -{ - return new TypeHandlerImpl(); -} - -// short -template<> -string -TypeHandlerImpl::GetParameterValue(const void *address, bool getContents, - MemoryReader &reader) -{ - return get_number_value(address, "0x%x"); -} - -template<> -string -TypeHandlerImpl::GetReturnValue(uint64 value, bool getContents, - MemoryReader &reader) -{ - return get_number_value(value, "0x%x"); -} - -template<> -TypeHandler * -TypeHandlerFactory::Create() -{ - return new TypeHandlerImpl(); -} - - -// unsigned short -template<> -string -TypeHandlerImpl::GetParameterValue(const void *address, - bool getContents, MemoryReader &reader) -{ - return get_number_value(address, "0x%x"); -} - -template<> -string -TypeHandlerImpl::GetReturnValue(uint64 value, bool getContents, - MemoryReader &reader) -{ - return get_number_value(value, "0x%x"); -} - -template<> -TypeHandler * -TypeHandlerFactory::Create() -{ - return new TypeHandlerImpl(); -} - -// int -template<> -string -TypeHandlerImpl::GetParameterValue(const void *address, bool getContents, - MemoryReader &reader) -{ - return get_number_value(address, "0x%x"); -} - -template<> -string -TypeHandlerImpl::GetReturnValue(uint64 value, bool getContents, - MemoryReader &reader) -{ - return get_number_value(value, "0x%x"); -} - -template<> -TypeHandler * -TypeHandlerFactory::Create() -{ - return new TypeHandlerImpl(); -} - -// unsigned int -template<> -string -TypeHandlerImpl::GetParameterValue(const void *address, - bool getContents, MemoryReader &reader) -{ - return get_number_value(address, "0x%x"); -} - -template<> -string -TypeHandlerImpl::GetReturnValue(uint64 value, bool getContents, - MemoryReader &reader) -{ - return get_number_value(value, "0x%x"); -} - -template<> -TypeHandler * -TypeHandlerFactory::Create() -{ - return new TypeHandlerImpl(); -} - -// long -template<> -string -TypeHandlerImpl::GetParameterValue(const void *address, bool getContents, - MemoryReader &reader) -{ - return get_number_value(address, "0x%lx"); -} - -template<> -string -TypeHandlerImpl::GetReturnValue(uint64 value, bool getContents, - MemoryReader &reader) -{ - return get_number_value(value, "0x%lx"); -} - -template<> -TypeHandler * -TypeHandlerFactory::Create() -{ - return new TypeHandlerImpl(); -} - -// unsigned long -template<> -string -TypeHandlerImpl::GetParameterValue(const void *address, - bool getContents, MemoryReader &reader) -{ - return get_number_value(address, "0x%lx"); -} - -template<> -string -TypeHandlerImpl::GetReturnValue(uint64 value, bool getContents, - MemoryReader &reader) -{ - return get_number_value(value, "0x%lx"); -} - -template<> -TypeHandler * -TypeHandlerFactory::Create() -{ - return new TypeHandlerImpl(); -} - -// long long -template<> -string -TypeHandlerImpl::GetParameterValue(const void *address, - bool getContents, MemoryReader &reader) -{ - return get_number_value(address, "0x%llx"); -} - -template<> -string -TypeHandlerImpl::GetReturnValue(uint64 value, bool getContents, - MemoryReader &reader) -{ - return get_number_value(value, "0x%llx"); -} - -template<> -TypeHandler * -TypeHandlerFactory::Create() -{ - return new TypeHandlerImpl(); -} - -// unsigned long -template<> -string -TypeHandlerImpl::GetParameterValue(const void *address, - bool getContents, MemoryReader &reader) -{ - return get_number_value(address, "0x%llx"); -} - -template<> -string -TypeHandlerImpl::GetReturnValue(uint64 value, - bool getContents, MemoryReader &reader) -{ - return get_number_value(value, "0x%llx"); -} - -template<> -TypeHandler * -TypeHandlerFactory::Create() -{ - return new TypeHandlerImpl(); -} - // read_string static string @@ -388,13 +152,21 @@ read_string(MemoryReader &reader, void *data) } static string -read_fdset(MemoryReader &reader, void *data) +format_number(uint32 value) { - /* default FD_SETSIZE is 1024 */ + char tmp[32]; + snprintf(tmp, sizeof(tmp), "%u", (unsigned int)value); + return tmp; +} + +static string +read_fdset(Context &context, void *data) +{ + // default FD_SETSIZE is 1024 unsigned long tmp[1024 / (sizeof(unsigned long) * 8)]; int32 bytesRead; - status_t err = reader.Read(data, &tmp, sizeof(tmp), bytesRead); + status_t err = context.Reader().Read(data, &tmp, sizeof(tmp), bytesRead); if (err != B_OK) return get_pointer_value(&data); @@ -402,17 +174,19 @@ read_fdset(MemoryReader &reader, void *data) int count = bytesRead / sizeof(unsigned long); int added = 0; - string r = "["; + string r; + r.reserve(16); + + r = "["; for (int i = 0; i < count && added < 8; i++) { for (int j = 0; j < (int)(sizeof(unsigned long) * 8) && added < 8; j++) { if (tmp[i] & (1 << j)) { if (added > 0) - r += ", "; - r += get_number_value( - i * (sizeof(unsigned long) * 8) + j, - "%u"); + r += " "; + unsigned int fd = i * sizeof(unsigned long) * 8 + j; + r += format_number(fd); added++; } } @@ -421,22 +195,23 @@ read_fdset(MemoryReader &reader, void *data) if (added >= 8) r += " ..."; - return r + "]"; + r += "]"; + + return r; } // const void* template<> string -TypeHandlerImpl::GetParameterValue(const void *address, - bool getContents, MemoryReader &reader) +TypeHandlerImpl::GetParameterValue(Context &, Parameter *, + const void *address) { return get_pointer_value(address); } template<> string -TypeHandlerImpl::GetReturnValue(uint64 value, bool getContents, - MemoryReader &reader) +TypeHandlerImpl::GetReturnValue(Context &, uint64 value) { return get_pointer_value(value); } @@ -444,48 +219,317 @@ TypeHandlerImpl::GetReturnValue(uint64 value, bool getContents, // const char* template<> string -TypeHandlerImpl::GetParameterValue(const void *address, - bool getContents, MemoryReader &reader) +TypeHandlerImpl::GetParameterValue(Context &context, Parameter *, + const void *address) { - void *data = *(void**)address; - if (getContents && data) - return read_string(reader, data); + void *data = *(void **)address; + if (data != NULL && context.GetContents(Context::STRINGS)) + return read_string(context.Reader(), data); return get_pointer_value(&data); } template<> string -TypeHandlerImpl::GetReturnValue(uint64 value, - bool getContents, MemoryReader &reader) +TypeHandlerImpl::GetReturnValue(Context &context, uint64 value) { - void *data = (void*)value; - if (getContents && data) - return read_string(reader, data); - - return get_pointer_value(&data); + void *ptr = (void *)value; + return GetParameterValue(context, NULL, (const void *)&ptr); } // struct fd_set * template<> string -TypeHandlerImpl::GetParameterValue(const void *address, - bool getContents, MemoryReader &reader) +TypeHandlerImpl::GetParameterValue(Context &context, Parameter *, + const void *address) { void *data = *(void **)address; - if (getContents && data) - return read_fdset(reader, data); + if (data != NULL && context.GetContents(Context::SIMPLE_STRUCTS)) + return read_fdset(context, data); return get_pointer_value(&data); } template<> string -TypeHandlerImpl::GetReturnValue(uint64 value, - bool getContents, MemoryReader &reader) +TypeHandlerImpl::GetReturnValue(Context &, uint64 value) { - void *data = (void *)value; - if (getContents && data) - return read_fdset(reader, data); - - return get_pointer_value(&data); + return get_pointer_value(value); } + +EnumTypeHandler::EnumTypeHandler(const EnumMap &m) : fMap(m) {} + +string +EnumTypeHandler::GetParameterValue(Context &context, Parameter *, + const void *address) +{ + return RenderValue(context, get_value(address)); +} + +string +EnumTypeHandler::GetReturnValue(Context &context, uint64 value) +{ + return RenderValue(context, value); +} + +string +EnumTypeHandler::RenderValue(Context &context, unsigned int value) const +{ + if (context.GetContents(Context::ENUMERATIONS)) { + EnumMap::const_iterator i = fMap.find(value); + if (i != fMap.end() && i->second != NULL) + return i->second; + } + + return context.FormatUnsigned(value); +} + +TypeHandlerSelector::TypeHandlerSelector(const SelectMap &m, int sibling, + TypeHandler *def) + : fMap(m), fSibling(sibling), fDefault(def) {} + +string +TypeHandlerSelector::GetParameterValue(Context &context, Parameter *param, + const void *address) +{ + TypeHandler *target = fDefault; + + int index = get_value(context.GetValue(context.GetSibling(fSibling))); + + SelectMap::const_iterator i = fMap.find(index); + if (i != fMap.end()) + target = i->second; + + return target->GetParameterValue(context, param, address); +} + +string +TypeHandlerSelector::GetReturnValue(Context &context, uint64 value) +{ + return fDefault->GetReturnValue(context, value); +} + +template +static string +format_pointer_deep(Context &context, void *address) +{ + if (address == NULL || !context.GetContents(Context::COMPLEX_STRUCTS)) + return get_pointer_value(&address); + + Base data; + int32 bytesRead; + + status_t err = context.Reader().Read(address, &data, sizeof(Base), bytesRead); + if (err != B_OK || bytesRead < (int32)sizeof(Base)) + return get_pointer_value(&address); + + return format_pointer(context, &data); +} + +template +static string +format_pointer_value(Context &context, const void *pointer) +{ + return format_pointer_deep(context, *(void **)pointer); +} + +template +static string +format_pointer_value(Context &context, uint64 value) +{ + return format_pointer_deep(context, (void *)value); +} + +static string +get_ipv4_address(struct in_addr *addr) +{ + char tmp[32]; + snprintf(tmp, sizeof(tmp), "%u.%u.%u.%u", + (unsigned int)(htonl(addr->s_addr) >> 24) & 0xff, + (unsigned int)(htonl(addr->s_addr) >> 16) & 0xff, + (unsigned int)(htonl(addr->s_addr) >> 8) & 0xff, + (unsigned int)(htonl(addr->s_addr) >> 0) & 0xff); + return tmp; +} + +static string +format_pointer(Context &context, sockaddr *saddr) +{ + string r = "{"; + + struct sockaddr_in *sin = (struct sockaddr_in *)saddr; + + switch (saddr->sa_family) { + case AF_INET: + r += "AF_INET, "; + r += get_ipv4_address(&sin->sin_addr); + r += "/"; + r += format_number(ntohs(sin->sin_port)); + break; + + default: + r += "family = "; + r += context.FormatUnsigned(saddr->sa_family); + r += ", ..."; + break; + } + + return r + "}"; +} + +static string +format_pointer(Context &context, sockaddr_args *args) +{ + string r = "{"; + + r += "addr = " + format_pointer_deep(context, args->address); + r += ", len = " + context.FormatUnsigned(args->address_length); + + return r + "}"; +} + +static string +format_pointer(Context &context, transfer_args *args) +{ + string r = "{"; + + r += "data = " + get_pointer_value(&args->data); + r += ", len = " + context.FormatUnsigned(args->data_length); + r += ", flags = " + context.FormatFlags(args->flags); + r += ", addr = " + format_pointer_deep(context, args->address); + + return r + "}"; +} + +static string +format_pointer(Context &context, sockopt_args *args) +{ + string r = "{"; + + r += "level = " + context.FormatSigned(args->level); + r += ", option = " + context.FormatSigned(args->option); + r += ", value = " + get_pointer_value(args->value); + r += ", len = " + context.FormatSigned(args->length); + + return r + "}"; +} + +static string +get_iovec(Context &context, struct iovec *iov, int iovlen) +{ + string r = "{"; + r += get_pointer_value(&iov); + r += ", " + context.FormatSigned(iovlen); + return r + "}"; +} + +static string +format_pointer(Context &context, msghdr *h) +{ + string r = "{"; + + r += "name = " + format_pointer_deep(context, h->msg_name); + r += ", name_len = " + context.FormatUnsigned(h->msg_namelen); + r += ", iov = " + get_iovec(context, h->msg_iov, h->msg_iovlen); + r += ", control = " + get_pointer_value(&h->msg_control); + r += ", control_len = " + context.FormatUnsigned(h->msg_controllen); + r += ", flags = " + context.FormatFlags(h->msg_flags); + + return r + "}"; +} + +template +class SignedIntegerTypeHandler : public TypeHandler { +public: + SignedIntegerTypeHandler(const char *modifier) + : fModifier(modifier) {} + + string GetParameterValue(Context &context, Parameter *, + const void *address) + { + return context.FormatSigned(get_value(address), fModifier); + } + + string GetReturnValue(Context &context, uint64 value) + { + return context.FormatSigned(value, fModifier); + } + +private: + const char *fModifier; +}; + +template +class UnsignedIntegerTypeHandler : public TypeHandler { +public: + string GetParameterValue(Context &context, Parameter *, + const void *address) + { + return context.FormatUnsigned(get_value(address)); + } + + string GetReturnValue(Context &context, uint64 value) + { + return context.FormatUnsigned(value); + } +}; + +template +class SpecializedPointerTypeHandler : public TypeHandler { + string GetParameterValue(Context &context, Parameter *, + const void *address) + { + return format_pointer_value(context, address); + } + + string GetReturnValue(Context &context, uint64 value) + { + return format_pointer_value(context, value); + } +}; + +#define DEFINE_TYPE(name, type) \ + TypeHandler *create_##name##_type_handler() \ + { \ + return new TypeHandlerImpl(); \ + } + +#define SIGNED_INTEGER_TYPE(type, modifier) \ + template<> \ + TypeHandler * \ + TypeHandlerFactory::Create() \ + { \ + return new SignedIntegerTypeHandler(modifier); \ + } + +#define UNSIGNED_INTEGER_TYPE(type) \ + template<> \ + TypeHandler * \ + TypeHandlerFactory::Create() \ + { \ + return new UnsignedIntegerTypeHandler(); \ + } + +#define POINTER_TYPE(name, type) \ + TypeHandler *create_##name##_type_handler() \ + { \ + return new SpecializedPointerTypeHandler(); \ + } + +SIGNED_INTEGER_TYPE(char, "hh"); +SIGNED_INTEGER_TYPE(short, "h"); +SIGNED_INTEGER_TYPE(int, ""); +SIGNED_INTEGER_TYPE(long, "l"); +SIGNED_INTEGER_TYPE(long long, "ll"); + +UNSIGNED_INTEGER_TYPE(unsigned char); +UNSIGNED_INTEGER_TYPE(unsigned short); +UNSIGNED_INTEGER_TYPE(unsigned int); +UNSIGNED_INTEGER_TYPE(unsigned long); +UNSIGNED_INTEGER_TYPE(unsigned long long); + +DEFINE_TYPE(fdset_ptr, struct fd_set *); +POINTER_TYPE(sockaddr_args_ptr, struct sockaddr_args); +POINTER_TYPE(transfer_args_ptr, struct transfer_args); +POINTER_TYPE(sockopt_args_ptr, struct sockopt_args); +POINTER_TYPE(msghdr_ptr, struct msghdr); + diff --git a/src/bin/strace/TypeHandler.h b/src/bin/strace/TypeHandler.h index e9b64ad4a0..7f7a54cc19 100644 --- a/src/bin/strace/TypeHandler.h +++ b/src/bin/strace/TypeHandler.h @@ -10,12 +10,15 @@ #define STRACE_TYPE_HANDLER_H #include +#include #include #include using std::string; +class Context; +class Parameter; class MemoryReader; typedef FUNCTION_CALL_PARAMETER_ALIGNMENT_TYPE align_t; @@ -26,11 +29,41 @@ public: TypeHandler() {} virtual ~TypeHandler() {} - virtual string GetParameterValue(const void *address, bool getContents, - MemoryReader &reader) = 0; + virtual string GetParameterValue(Context &, Parameter *, + const void *value) = 0; + virtual string GetReturnValue(Context &, uint64 value) = 0; +}; - virtual string GetReturnValue(uint64 value, bool getContents, - MemoryReader &reader) = 0; +class EnumTypeHandler : public TypeHandler { +public: + typedef std::map EnumMap; + + EnumTypeHandler(const EnumMap &); + + string GetParameterValue(Context &c, Parameter *, const void *); + string GetReturnValue(Context &, uint64 value); + +private: + string RenderValue(Context &, unsigned int value) const; + + const EnumMap &fMap; +}; + +// currently limited to select ints +class TypeHandlerSelector : public TypeHandler { +public: + typedef std::map SelectMap; + + TypeHandlerSelector(const SelectMap &, int sibling, + TypeHandler *def); + + string GetParameterValue(Context &, Parameter *, const void *); + string GetReturnValue(Context &, uint64 value); + +private: + const SelectMap &fMap; + int fSibling; + TypeHandler *fDefault; }; // templatized TypeHandler factory class @@ -44,7 +77,6 @@ struct TypeHandlerFactory { extern TypeHandler *create_pointer_type_handler(); extern TypeHandler *create_string_type_handler(); -extern TypeHandler *create_fdset_type_handler(); // specialization for "const char*" template<> @@ -55,14 +87,20 @@ struct TypeHandlerFactory { } }; -// specialization for 'struct fdset *' -template<> -struct TypeHandlerFactory { - static inline TypeHandler *Create() - { - return create_fdset_type_handler(); - } -}; +#define DEFINE_FACTORY(name, type) \ + template<> \ + struct TypeHandlerFactory { \ + static inline TypeHandler *Create() \ + { \ + extern TypeHandler *create_##name##_type_handler(); \ + return create_##name##_type_handler(); \ + } \ + } \ + +DEFINE_FACTORY(fdset_ptr, struct fd_set *); +DEFINE_FACTORY(sockaddr_args_ptr, struct sockaddr_args *); +DEFINE_FACTORY(transfer_args_ptr, struct transfer_args *); +DEFINE_FACTORY(sockopt_args_ptr, struct sockopt_args *); // partial specialization for generic pointers template diff --git a/src/bin/strace/ioctl.cpp b/src/bin/strace/ioctl.cpp new file mode 100644 index 0000000000..36abb1a11b --- /dev/null +++ b/src/bin/strace/ioctl.cpp @@ -0,0 +1,91 @@ +/* + * Copyright 2007, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Hugo Santos + */ + +#include +#include + +#include "Syscall.h" +#include "TypeHandler.h" + +struct ioctl_info { + int index; + const char *name; + TypeHandler *handler; +}; + +#define IOCTL_INFO_ENTRY(name) \ + { name, #name, NULL } + +#define IOCTL_INFO_ENTRY_TYPE(name, type) \ + { name, #name, TypeHandlerFactory::Create() } + +static const ioctl_info kIOCtls[] = { + // network stack ioctls + IOCTL_INFO_ENTRY(NET_STACK_SOCKET), + IOCTL_INFO_ENTRY(NET_STACK_GET_COOKIE), + IOCTL_INFO_ENTRY(NET_STACK_CONTROL_NET_MODULE), + IOCTL_INFO_ENTRY(NET_STACK_GET_NEXT_STAT), + IOCTL_INFO_ENTRY_TYPE(NET_STACK_BIND, struct sockaddr_args *), + IOCTL_INFO_ENTRY_TYPE(NET_STACK_RECVFROM, struct transfer_args *), + IOCTL_INFO_ENTRY_TYPE(NET_STACK_RECV, struct transfer_args *), + IOCTL_INFO_ENTRY_TYPE(NET_STACK_SENDTO, struct transfer_args *), + IOCTL_INFO_ENTRY_TYPE(NET_STACK_SEND, struct transfer_args *), + IOCTL_INFO_ENTRY(NET_STACK_LISTEN), + IOCTL_INFO_ENTRY(NET_STACK_ACCEPT), + IOCTL_INFO_ENTRY_TYPE(NET_STACK_CONNECT, struct sockaddr_args *), + IOCTL_INFO_ENTRY(NET_STACK_SHUTDOWN), + IOCTL_INFO_ENTRY_TYPE(NET_STACK_GETSOCKOPT, struct sockopt_args *), + IOCTL_INFO_ENTRY_TYPE(NET_STACK_SETSOCKOPT, struct sockopt_args *), + IOCTL_INFO_ENTRY_TYPE(NET_STACK_GETSOCKNAME, struct sockaddr_args *), + IOCTL_INFO_ENTRY_TYPE(NET_STACK_GETPEERNAME, struct sockaddr_args *), + IOCTL_INFO_ENTRY(NET_STACK_SOCKETPAIR), + IOCTL_INFO_ENTRY(NET_STACK_NOTIFY_SOCKET_EVENT), + + // termios ioctls + IOCTL_INFO_ENTRY(TCGETA), + IOCTL_INFO_ENTRY(TCSETA), + IOCTL_INFO_ENTRY(TCSETAF), + IOCTL_INFO_ENTRY(TCSETAW), + IOCTL_INFO_ENTRY(TCWAITEVENT), + IOCTL_INFO_ENTRY(TCSBRK), + IOCTL_INFO_ENTRY(TCFLSH), + IOCTL_INFO_ENTRY(TCXONC), + IOCTL_INFO_ENTRY(TCQUERYCONNECTED), + IOCTL_INFO_ENTRY(TCGETBITS), + IOCTL_INFO_ENTRY(TCSETDTR), + IOCTL_INFO_ENTRY(TCSETRTS), + IOCTL_INFO_ENTRY(TIOCGWINSZ), + IOCTL_INFO_ENTRY(TIOCSWINSZ), + IOCTL_INFO_ENTRY(TCVTIME), + IOCTL_INFO_ENTRY(TIOCGPGRP), + IOCTL_INFO_ENTRY(TIOCSPGRP), + + { -1, NULL, NULL } +}; + +static EnumTypeHandler::EnumMap kIoctlNames; +static TypeHandlerSelector::SelectMap kIoctlTypeHandlers; + +void +patch_ioctl() +{ + for (int i = 0; kIOCtls[i].name != NULL; i++) { + kIoctlNames[kIOCtls[i].index] = kIOCtls[i].name; + if (kIOCtls[i].handler != NULL) + kIoctlTypeHandlers[kIOCtls[i].index] = kIOCtls[i].handler; + } + + Syscall *ioctl = Syscall::GetSyscall("_kern_ioctl"); + + ioctl->GetParameter("cmd")->SetHandler( + new EnumTypeHandler(kIoctlNames)); + ioctl->GetParameter("data")->SetHandler( + new TypeHandlerSelector(kIoctlTypeHandlers, + 1, TypeHandlerFactory::Create())); +} + diff --git a/src/bin/strace/strace.cpp b/src/bin/strace/strace.cpp index 7007a92f7c..daa8b7e1a0 100644 --- a/src/bin/strace/strace.cpp +++ b/src/bin/strace/strace.cpp @@ -59,8 +59,11 @@ static const char *kUsage = "Options:\n" " -a - Don't print syscall arguments.\n" " -c - Don't colorize output.\n" +" -d - Filter the types that have their contents retrieved.\n" +" is one of: strings, enums, simple or complex\n" " -f - Fast mode. Syscall arguments contents aren't retrieved.\n" " -h, --help - Print this text.\n" +" -i - Print integers in decimal format instead of hexadecimal.\n" " -l - Also trace loading the excecutable. Only considered when\n" " an executable is provided.\n" " -r - Don't print syscall return values.\n" @@ -88,7 +91,6 @@ static const char *const *sArgv; static vector sSyscallVector; static map sSyscallMap; - // print_usage void print_usage(bool error) @@ -266,6 +268,17 @@ continue_thread(port_id nubPort, thread_id thread) } } +static void +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_ioctl(); + + patch_ioctl(); +} + // init_syscalls static void @@ -299,6 +312,8 @@ init_syscalls() Syscall *syscall = sSyscallVector[i]; sSyscallMap[syscall->Name()] = syscall; } + + patch_syscalls(); } // print_to_string @@ -319,14 +334,17 @@ print_to_string(char **_buffer, int32 *_length, const char *format, ...) static void print_syscall(FILE *outputFile, debug_post_syscall &message, - MemoryReader &memoryReader, bool printArguments, bool getContents, - bool printReturnValue, bool colorize) + MemoryReader &memoryReader, bool printArguments, uint32 contentsFlags, + bool printReturnValue, bool colorize, bool decimal) { char buffer[4096], *string = buffer; int32 length = (int32)sizeof(buffer); int32 syscallNumber = message.syscall; Syscall *syscall = sSyscallVector[syscallNumber]; + Context ctx(syscall, (char *)message.args, memoryReader, + contentsFlags, decimal); + // print syscall name if (colorize) { print_to_string(&string, &length, "[%6ld] %s%s%s(", @@ -344,9 +362,9 @@ print_syscall(FILE *outputFile, debug_post_syscall &message, // get the value Parameter *parameter = syscall->ParameterAt(i); TypeHandler *handler = parameter->Handler(); - ::string value = handler->GetParameterValue( - (char*)message.args + parameter->Offset(), getContents, - memoryReader); + ::string value = + handler->GetParameterValue(ctx, parameter, + ctx.GetValue(parameter)); print_to_string(&string, &length, (i > 0 ? ", %s" : "%s"), value.c_str()); @@ -359,8 +377,7 @@ print_syscall(FILE *outputFile, debug_post_syscall &message, if (printReturnValue) { Type *returnType = syscall->ReturnType(); TypeHandler *handler = returnType->Handler(); - ::string value = handler->GetReturnValue(message.return_value, - getContents, memoryReader); + ::string value = handler->GetReturnValue(ctx, message.return_value); if (value.length() > 0) { print_to_string(&string, &length, " = %s", value.c_str()); @@ -414,6 +431,8 @@ main(int argc, const char *const *argv) int32 programArgCount = 0; bool printArguments = true; bool colorize = true; + uint32 contentsFlags = 0; + bool decimalFormat = false; bool fastMode = false; bool traceLoading = false; bool printReturnValues = true; @@ -433,8 +452,33 @@ main(int argc, const char *const *argv) printArguments = false; } else if (strcmp(arg, "-c") == 0) { colorize = false; + } else if (strcmp(arg, "-d") == 0) { + const char *what = NULL; + + if (arg[2] == '\0' + && argi + 1 < argc && argv[argi + 1][0] != '-') { + // next arg is what + what = argv[++argi]; + } else + print_usage_and_exit(true); + + if (strcasecmp(what, "strings") == 0) + contentsFlags |= Context::STRINGS; + else if (strcasecmp(what, "enums") == 0) + contentsFlags |= Context::ENUMERATIONS; + else if (strcasecmp(what, "simple") == 0) + contentsFlags |= Context::SIMPLE_STRUCTS; + else if (strcasecmp(what, "complex") == 0) + contentsFlags |= Context::COMPLEX_STRUCTS; + else { + fprintf(stderr, "%s: Unknown content filter `%s'\n", + kCommandName, what); + exit(1); + } } else if (strcmp(arg, "-f") == 0) { fastMode = true; + } else if (strcmp(arg, "-i") == 0) { + decimalFormat = true; } else if (strcmp(arg, "-l") == 0) { traceLoading = true; } else if (strcmp(arg, "-r") == 0) { @@ -479,6 +523,11 @@ main(int argc, const char *const *argv) if (!programArgs) print_usage_and_exit(true); + if (fastMode) + contentsFlags = 0; + else if (contentsFlags == 0) + contentsFlags = Context::ALL; + // initialize our syscalls vector and map init_syscalls(); @@ -500,7 +549,7 @@ main(int argc, const char *const *argv) programArgs[0], strerror(thread)); exit(1); } - } + } // get the team ID, if we have none yet if (team < 0) { @@ -571,7 +620,8 @@ main(int argc, const char *const *argv) case B_DEBUGGER_MESSAGE_POST_SYSCALL: { print_syscall(outputFile, message.post_syscall, memoryReader, - printArguments, !fastMode, printReturnValues, colorize); + printArguments, contentsFlags, printReturnValues, + colorize, decimalFormat); break; } @@ -611,3 +661,43 @@ main(int argc, const char *const *argv) return 0; } + +Syscall * +Syscall::GetSyscall(const char *name) +{ + map::const_iterator i = sSyscallMap.find(name); + if (i == sSyscallMap.end()) + return NULL; + + return i->second; +} + +string +Context::FormatSigned(int64 value, const char *type) const +{ + char modifier[16], tmp[32]; + + if (fDecimal) + snprintf(modifier, sizeof(modifier), "%%%si", type); + else + snprintf(modifier, sizeof(modifier), "0x%%%sx", type); + + snprintf(tmp, sizeof(tmp), modifier, value); + return tmp; +} + +string +Context::FormatUnsigned(uint64 value) const +{ + char tmp[32]; + snprintf(tmp, sizeof(tmp), fDecimal ? "%llu" : "0x%llx", value); + return tmp; +} + +string +Context::FormatFlags(uint64 value) const +{ + char tmp[32]; + snprintf(tmp, sizeof(tmp), "0x%llx", value); + return tmp; +}