diff --git a/src/bin/strace/Context.cpp b/src/bin/strace/Context.cpp index 0c81b1b1d7..11212f876e 100644 --- a/src/bin/strace/Context.cpp +++ b/src/bin/strace/Context.cpp @@ -12,7 +12,6 @@ #include #include - string Context::FormatSigned(int64 value, int bytes) const { @@ -42,7 +41,7 @@ Context::FormatSigned(int64 value, int bytes) const tmp[--offset] = 'x'; tmp[--offset] = '0'; } - + return tmp + offset; } @@ -61,3 +60,11 @@ Context::FormatFlags(uint64 value) const snprintf(tmp, sizeof(tmp), "0x%llx", value); return tmp; } + +string +Context::FormatPointer(const void *address) const +{ + char buffer[32]; + sprintf(buffer, "%p", address); + return buffer; +} diff --git a/src/bin/strace/Context.h b/src/bin/strace/Context.h index c61a02fa8d..f8ba3bfbeb 100644 --- a/src/bin/strace/Context.h +++ b/src/bin/strace/Context.h @@ -18,6 +18,7 @@ public: ENUMERATIONS = 1 << 1, SIMPLE_STRUCTS = 1 << 2, COMPLEX_STRUCTS = 1 << 3, + POINTER_VALUES = 1 << 4, ALL = 0xffffffff }; @@ -41,6 +42,8 @@ public: string FormatUnsigned(uint64 value) const; string FormatFlags(uint64 value) const; + string FormatPointer(const void *address) const; + private: Syscall *fSyscall; char *fData; diff --git a/src/bin/strace/Jamfile b/src/bin/strace/Jamfile index b8da2b1592..be11bdbabc 100644 --- a/src/bin/strace/Jamfile +++ b/src/bin/strace/Jamfile @@ -9,7 +9,8 @@ UsePrivateHeaders net ; SubDirHdrs $(TARGET_COMMON_DEBUG_LOCATE_TARGET) ; local straceSources = - Context.cpp ioctl.cpp MemoryReader.cpp strace.cpp TypeHandler.cpp + Context.cpp ioctl.cpp MemoryReader.cpp NetworkTypes.cpp + strace.cpp TypeHandler.cpp ; # Our compiler badly chokes when compiling the generated file. So will diff --git a/src/bin/strace/NetworkTypes.cpp b/src/bin/strace/NetworkTypes.cpp new file mode 100644 index 0000000000..05c5bbe094 --- /dev/null +++ b/src/bin/strace/NetworkTypes.cpp @@ -0,0 +1,412 @@ +/* + * Copyright 2007, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Hugo Santos + * Ingo Weinhold + */ + +// headers required for network structures +#include +#include +#include + +#include + +#include "Context.h" +#include "MemoryReader.h" +#include "TypeHandler.h" + +template +static bool +obtain_pointer_data(Context &context, Type *data, void *address, uint32 what) +{ + if (address == NULL || !context.GetContents(what)) + return false; + + int32 bytesRead; + + status_t err = context.Reader().Read(address, data, sizeof(Type), bytesRead); + if (err != B_OK || bytesRead < (int32)sizeof(Type)) + return false; + + return true; +} + +static string +format_number(uint32 value) +{ + 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 = context.Reader().Read(data, &tmp, sizeof(tmp), bytesRead); + if (err != B_OK) + return context.FormatPointer(data); + + /* implicitly align to unsigned long lower boundary */ + int count = bytesRead / sizeof(unsigned long); + int added = 0; + + 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 += " "; + unsigned int fd = i * sizeof(unsigned long) * 8 + j; + r += format_number(fd); + added++; + } + } + } + + if (added >= 8) + r += " ..."; + + r += "]"; + + return r; +} + +template<> +string +TypeHandlerImpl::GetParameterValue(Context &context, Parameter *, + const void *address) +{ + void *data = *(void **)address; + if (data != NULL && context.GetContents(Context::SIMPLE_STRUCTS)) + return read_fdset(context, data); + return context.FormatPointer(data); +} + +template<> +string +TypeHandlerImpl::GetReturnValue(Context &context, uint64 value) +{ + return context.FormatPointer((void *)value); +} + +template +static string +format_pointer_value(Context &context, void *address) +{ + Type data; + + if (obtain_pointer_data(context, &data, address,Context::COMPLEX_STRUCTS)) + return "{" + format_pointer(context, &data) + "}"; + + return context.FormatPointer(address); +} + +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_socket_family(Context &context, int family) +{ + if (context.GetContents(Context::ENUMERATIONS)) { + switch (family) { + case AF_INET: + return "AF_INET"; + } + } + + return "family = " + context.FormatSigned(family); +} + +static string +format_socket_type(Context &context, int type) +{ + if (context.GetContents(Context::ENUMERATIONS)) { + switch (type) { + case SOCK_RAW: + return "SOCK_RAW"; + case SOCK_DGRAM: + return "SOCK_DGRAM"; + case SOCK_STREAM: + return "SOCK_STREAM"; + } + } + + return "type = " + context.FormatSigned(type); +} + +static string +format_socket_protocol(Context &context, int protocol) +{ + if (context.GetContents(Context::ENUMERATIONS)) { + switch (protocol) { + case IPPROTO_IP: + return "IPPROTO_IP"; + case IPPROTO_RAW: + return "IPPROTO_RAW"; + case IPPROTO_ICMP: + return "IPPROTO_ICMP"; + case IPPROTO_UDP: + return "IPPROTO_UDP"; + case IPPROTO_TCP: + return "IPPROTO_TCP"; + } + } + + return "protocol = " + context.FormatSigned(protocol); +} + +static string +format_pointer(Context &context, sockaddr *saddr) +{ + string r; + + struct sockaddr_in *sin = (struct sockaddr_in *)saddr; + + r = format_socket_family(context, saddr->sa_family) + ", "; + + switch (saddr->sa_family) { + case AF_INET: + r += get_ipv4_address(&sin->sin_addr); + r += "/"; + r += format_number(ntohs(sin->sin_port)); + break; + + default: + r += "..."; + break; + } + + return r; +} + +static string +format_pointer(Context &context, sockaddr_args *args) +{ + string r; + + r = "addr = " + format_pointer_value(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 = " + context.FormatPointer(args->data); + r += ", len = " + context.FormatUnsigned(args->data_length); + r += ", flags = " + context.FormatFlags(args->flags); + r += ", addr = " + format_pointer_value(context, args->address); + + return r; +} + +struct socket_option_info { + int level; + int option; + const char *name; + TypeHandler *handler; + int length; +}; + +#define SOCKET_OPTION_INFO_ENTRY(level, option) \ + { level, option, #option, NULL, 0 } + +#define SOCKET_OPTION_INFO_ENTRY_TYPE(level, option, type) \ + { level, option, #option, TypeHandlerFactory::Create(), sizeof(type) } + +static const socket_option_info kSocketOptions[] = { + SOCKET_OPTION_INFO_ENTRY(SOL_SOCKET, SO_ACCEPTCONN), + SOCKET_OPTION_INFO_ENTRY_TYPE(SOL_SOCKET, SO_BROADCAST, int32), + SOCKET_OPTION_INFO_ENTRY_TYPE(SOL_SOCKET, SO_DEBUG, int32), + SOCKET_OPTION_INFO_ENTRY_TYPE(SOL_SOCKET, SO_DONTROUTE, int32), + SOCKET_OPTION_INFO_ENTRY_TYPE(SOL_SOCKET, SO_KEEPALIVE, int32), + SOCKET_OPTION_INFO_ENTRY_TYPE(SOL_SOCKET, SO_OOBINLINE, int32), + SOCKET_OPTION_INFO_ENTRY_TYPE(SOL_SOCKET, SO_REUSEADDR, int32), + SOCKET_OPTION_INFO_ENTRY_TYPE(SOL_SOCKET, SO_REUSEPORT, int32), + SOCKET_OPTION_INFO_ENTRY_TYPE(SOL_SOCKET, SO_USELOOPBACK, int32), + SOCKET_OPTION_INFO_ENTRY(SOL_SOCKET, SO_LINGER), + SOCKET_OPTION_INFO_ENTRY_TYPE(SOL_SOCKET, SO_SNDBUF, uint32), + SOCKET_OPTION_INFO_ENTRY(SOL_SOCKET, SO_SNDLOWAT), + SOCKET_OPTION_INFO_ENTRY(SOL_SOCKET, SO_SNDTIMEO), + SOCKET_OPTION_INFO_ENTRY_TYPE(SOL_SOCKET, SO_RCVBUF, uint32), + SOCKET_OPTION_INFO_ENTRY(SOL_SOCKET, SO_RCVLOWAT), + SOCKET_OPTION_INFO_ENTRY(SOL_SOCKET, SO_RCVTIMEO), + SOCKET_OPTION_INFO_ENTRY(SOL_SOCKET, SO_ERROR), + SOCKET_OPTION_INFO_ENTRY(SOL_SOCKET, SO_TYPE), + SOCKET_OPTION_INFO_ENTRY_TYPE(SOL_SOCKET, SO_NONBLOCK, int32), + SOCKET_OPTION_INFO_ENTRY(SOL_SOCKET, SO_BINDTODEVICE), + SOCKET_OPTION_INFO_ENTRY(IPPROTO_IP, IP_OPTIONS), + SOCKET_OPTION_INFO_ENTRY_TYPE(IPPROTO_IP, IP_HDRINCL, int), + SOCKET_OPTION_INFO_ENTRY_TYPE(IPPROTO_IP, IP_TOS, int), + SOCKET_OPTION_INFO_ENTRY_TYPE(IPPROTO_IP, IP_TTL, int), + SOCKET_OPTION_INFO_ENTRY(IPPROTO_IP, IP_RECVOPTS), + SOCKET_OPTION_INFO_ENTRY(IPPROTO_IP, IP_RECVRETOPTS), + SOCKET_OPTION_INFO_ENTRY(IPPROTO_IP, IP_RECVDSTADDR), + SOCKET_OPTION_INFO_ENTRY(IPPROTO_IP, IP_RETOPTS), + SOCKET_OPTION_INFO_ENTRY(IPPROTO_IP, IP_MULTICAST_IF), + SOCKET_OPTION_INFO_ENTRY(IPPROTO_IP, IP_MULTICAST_TTL), + SOCKET_OPTION_INFO_ENTRY(IPPROTO_IP, IP_MULTICAST_LOOP), + SOCKET_OPTION_INFO_ENTRY(IPPROTO_IP, IP_ADD_MEMBERSHIP), + SOCKET_OPTION_INFO_ENTRY(IPPROTO_IP, IP_DROP_MEMBERSHIP), + { -1, -1, NULL, NULL } +}; + +class SocketOptionsMap { +public: + typedef map, const socket_option_info *> ThisMap; + + SocketOptionsMap() + { + for (int i = 0; kSocketOptions[i].name != NULL; i++) { + fMap.insert(make_pair( + make_pair(kSocketOptions[i].level, + kSocketOptions[i].option), + &kSocketOptions[i])); + } + } + + const socket_option_info *GetEntry(int level, int option) const + { + ThisMap::const_iterator i = fMap.find(make_pair(level, option)); + if (i == fMap.end()) + return NULL; + + return i->second; + } + +private: + ThisMap fMap; +}; + +static const SocketOptionsMap kSocketOptionsMap; + +static string +format_pointer(Context &context, sockopt_args *args) +{ + const socket_option_info *info = + kSocketOptionsMap.GetEntry(args->level, args->option); + + string level, option, value; + + if (context.GetContents(Context::ENUMERATIONS)) { + switch (args->level) { + case SOL_SOCKET: + level = "SOL_SOCKET"; + break; + case IPPROTO_IP: + level = "IPPROTO_IP"; + break; + } + + if (info != NULL) + option = info->name; + } + + if (info != NULL && info->length == args->length) + value = info->handler->GetParameterValue(context, NULL, &args->value); + else { + value = "value = " + context.FormatPointer(args->value); + value += ", len = " + context.FormatUnsigned(args->length); + } + + if (level.empty()) + level = "level = " + context.FormatSigned(args->level, sizeof(int)); + + if (option.empty()) + option = "option = " + context.FormatSigned(args->option, sizeof(int)); + + return level + ", " + option + ", " + value; +} + +static string +format_pointer(Context &context, socket_args *args) +{ + string r; + + r = format_socket_family(context, args->family) + ", "; + r += format_socket_type(context, args->type) + ", "; + r += format_socket_protocol(context, args->protocol); + + return r; +} + +static string +get_iovec(Context &context, struct iovec *iov, int iovlen) +{ + string r = "{"; + r += context.FormatPointer(iov); + r += ", " + context.FormatSigned(iovlen); + return r + "}"; +} + +static string +format_pointer(Context &context, msghdr *h) +{ + string r; + + r = "name = " + format_pointer_value(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 = " + context.FormatPointer(h->msg_control); + r += ", control_len = " + context.FormatUnsigned(h->msg_controllen); + r += ", flags = " + context.FormatFlags(h->msg_flags); + + return r; +} + +template +class SpecializedPointerTypeHandler : public TypeHandler { + string GetParameterValue(Context &context, Parameter *, + const void *address) + { + return format_pointer_value(context, *(void **)address); + } + + string GetReturnValue(Context &context, uint64 value) + { + return format_pointer_value(context, (void *)value); + } +}; + +#define DEFINE_TYPE(name, type) \ + TypeHandler *create_##name##_type_handler() \ + { \ + return new TypeHandlerImpl(); \ + } + +#define POINTER_TYPE(name, type) \ + TypeHandler *create_##name##_type_handler() \ + { \ + return new SpecializedPointerTypeHandler(); \ + } + +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(socket_args_ptr, struct socket_args); +POINTER_TYPE(msghdr_ptr, struct msghdr); diff --git a/src/bin/strace/TypeHandler.cpp b/src/bin/strace/TypeHandler.cpp index 5121be9c32..d271af5db1 100644 --- a/src/bin/strace/TypeHandler.cpp +++ b/src/bin/strace/TypeHandler.cpp @@ -9,25 +9,10 @@ #include "TypeHandler.h" -// headers required for network structures -#include -#include -#include - -#include - #include "Context.h" #include "MemoryReader.h" #include "Syscall.h" -// TypeHandlerImpl -template -class TypeHandlerImpl : public TypeHandler { -public: - virtual string GetParameterValue(Context &, Parameter *, const void *); - virtual string GetReturnValue(Context &, uint64 value); -}; - template static inline value_t get_value(const void *address) @@ -40,26 +25,6 @@ get_value(const void *address) // #pragma mark - -// get_pointer_value -static inline -string -get_pointer_value(const void *address) -{ - char buffer[32]; - sprintf(buffer, "%p", *(void **)address); - return buffer; -} - -// get_pointer_value -static inline -string -get_pointer_value(uint64 value) -{ - char buffer[32]; - sprintf(buffer, "%p", (void*)value); - return buffer; -} - // create_pointer_type_handler TypeHandler * create_pointer_type_handler() @@ -126,11 +91,11 @@ TypeHandlerFactory::Create() // read_string static string -read_string(MemoryReader &reader, void *data) +read_string(Context &context, void *data) { char buffer[256]; int32 bytesRead; - status_t error = reader.Read(data, buffer, sizeof(buffer), bytesRead); + status_t error = context.Reader().Read(data, buffer, sizeof(buffer), bytesRead); if (error == B_OK) { // return string("\"") + string(buffer, bytesRead) + "\""; //string result("\""); @@ -149,72 +114,24 @@ read_string(MemoryReader &reader, void *data) largeBuffer[len + 2] = '\0'; return largeBuffer; } - return get_pointer_value(&data) + " (" + strerror(error) + ")"; -} -static string -format_number(uint32 value) -{ - 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 = context.Reader().Read(data, &tmp, sizeof(tmp), bytesRead); - if (err != B_OK) - return get_pointer_value(&data); - - /* implicitly align to unsigned long lower boundary */ - int count = bytesRead / sizeof(unsigned long); - int added = 0; - - 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 += " "; - unsigned int fd = i * sizeof(unsigned long) * 8 + j; - r += format_number(fd); - added++; - } - } - } - - if (added >= 8) - r += " ..."; - - r += "]"; - - return r; + return context.FormatPointer(data) + " (" + strerror(error) + ")"; } // const void* template<> string -TypeHandlerImpl::GetParameterValue(Context &, Parameter *, +TypeHandlerImpl::GetParameterValue(Context &context, Parameter *, const void *address) { - return get_pointer_value(address); + return context.FormatPointer(*(void **)address); } template<> string -TypeHandlerImpl::GetReturnValue(Context &, uint64 value) +TypeHandlerImpl::GetReturnValue(Context &context, uint64 value) { - return get_pointer_value(value); + return context.FormatPointer((void *)value); } // const char* @@ -225,9 +142,9 @@ TypeHandlerImpl::GetParameterValue(Context &context, Parameter *, { void *data = *(void **)address; if (data != NULL && context.GetContents(Context::STRINGS)) - return read_string(context.Reader(), data); + return read_string(context, data); - return get_pointer_value(&data); + return context.FormatPointer(data); } template<> @@ -238,25 +155,6 @@ TypeHandlerImpl::GetReturnValue(Context &context, uint64 value) return GetParameterValue(context, NULL, (const void *)&ptr); } -// struct fd_set * -template<> -string -TypeHandlerImpl::GetParameterValue(Context &context, Parameter *, - const void *address) -{ - void *data = *(void **)address; - if (data != NULL && context.GetContents(Context::SIMPLE_STRUCTS)) - return read_fdset(context, data); - return get_pointer_value(&data); -} - -template<> -string -TypeHandlerImpl::GetReturnValue(Context &, uint64 value) -{ - return get_pointer_value(value); -} - EnumTypeHandler::EnumTypeHandler(const EnumMap &m) : fMap(m) {} string @@ -309,133 +207,44 @@ TypeHandlerSelector::GetReturnValue(Context &context, uint64 value) return fDefault->GetReturnValue(context, value); } -template -static string -format_pointer_deep(Context &context, void *address) +template +static bool +obtain_pointer_data(Context &context, Type *data, void *address, uint32 what) { - if (address == NULL || !context.GetContents(Context::COMPLEX_STRUCTS)) - return get_pointer_value(&address); + if (address == NULL || !context.GetContents(what)) + return false; - 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); + status_t err = context.Reader().Read(address, data, sizeof(Type), bytesRead); + if (err != B_OK || bytesRead < (int32)sizeof(Type)) + return false; - return format_pointer(context, &data); + return true; } -template +template static string -format_pointer_value(Context &context, const void *pointer) +format_signed_integer_pointer(Context &context, void *address) { - return format_pointer_deep(context, *(void **)pointer); + Type data; + + if (obtain_pointer_data(context, &data, address, Context::POINTER_VALUES)) + return "[" + context.FormatSigned(data, sizeof(Type)) + "]"; + + return context.FormatPointer(address); } -template +template static string -format_pointer_value(Context &context, uint64 value) +format_unsigned_integer_pointer(Context &context, void *address) { - return format_pointer_deep(context, (void *)value); -} + Type data; -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; -} + if (obtain_pointer_data(context, &data, address, Context::POINTER_VALUES)) + return "[" + context.FormatUnsigned(data) + "]"; -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 + "}"; + return context.FormatPointer(address); } template @@ -469,25 +278,33 @@ public: }; template -class SpecializedPointerTypeHandler : public TypeHandler { +class SignedIntegerPointerTypeHandler : public TypeHandler { string GetParameterValue(Context &context, Parameter *, const void *address) { - return format_pointer_value(context, address); + return format_signed_integer_pointer(context, *(void **)address); } string GetReturnValue(Context &context, uint64 value) { - return format_pointer_value(context, value); + return format_signed_integer_pointer(context, (void *)value); } }; -#define DEFINE_TYPE(name, type) \ - TypeHandler *create_##name##_type_handler() \ - { \ - return new TypeHandlerImpl(); \ +template +class UnsignedIntegerPointerTypeHandler : public TypeHandler { + string GetParameterValue(Context &context, Parameter *, + const void *address) + { + return format_unsigned_integer_pointer(context, *(void **)address); } + string GetReturnValue(Context &context, uint64 value) + { + return format_unsigned_integer_pointer(context, (void *)value); + } +}; + #define SIGNED_INTEGER_TYPE(type) \ template<> \ TypeHandler * \ @@ -504,12 +321,19 @@ class SpecializedPointerTypeHandler : public TypeHandler { return new UnsignedIntegerTypeHandler(); \ } -#define POINTER_TYPE(name, type) \ +#define SIGNED_INTEGER_POINTER_TYPE(name, type) \ TypeHandler *create_##name##_type_handler() \ { \ - return new SpecializedPointerTypeHandler(); \ + return new SignedIntegerPointerTypeHandler(); \ } +#define UNSIGNED_INTEGER_POINTER_TYPE(name, type) \ + TypeHandler *create_##name##_type_handler() \ + { \ + return new UnsignedIntegerPointerTypeHandler(); \ + } + + SIGNED_INTEGER_TYPE(char); SIGNED_INTEGER_TYPE(short); SIGNED_INTEGER_TYPE(int); @@ -522,9 +346,11 @@ 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); +SIGNED_INTEGER_POINTER_TYPE(int_ptr, int); +SIGNED_INTEGER_POINTER_TYPE(long_ptr, long); +SIGNED_INTEGER_POINTER_TYPE(longlong_ptr, long long); + +UNSIGNED_INTEGER_POINTER_TYPE(uint_ptr, unsigned int); +UNSIGNED_INTEGER_POINTER_TYPE(ulong_ptr, unsigned long); +UNSIGNED_INTEGER_POINTER_TYPE(ulonglong_ptr, unsigned long long); diff --git a/src/bin/strace/TypeHandler.h b/src/bin/strace/TypeHandler.h index 7f7a54cc19..9180e26bc7 100644 --- a/src/bin/strace/TypeHandler.h +++ b/src/bin/strace/TypeHandler.h @@ -101,6 +101,14 @@ 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 *); +DEFINE_FACTORY(socket_args_ptr, struct socket_args *); + +DEFINE_FACTORY(int_ptr, int *); +DEFINE_FACTORY(long_ptr, long *); +DEFINE_FACTORY(longlong_ptr, long long *); +DEFINE_FACTORY(uint_ptr, unsigned int *); +DEFINE_FACTORY(ulong_ptr, unsigned long *); +DEFINE_FACTORY(ulonglong_ptr, unsigned long long *); // partial specialization for generic pointers template @@ -111,4 +119,11 @@ struct TypeHandlerFactory { } }; +template +class TypeHandlerImpl : public TypeHandler { +public: + string GetParameterValue(Context &, Parameter *, const void *); + string GetReturnValue(Context &, uint64 value); +}; + #endif // STRACE_TYPE_HANDLER_H diff --git a/src/bin/strace/ioctl.cpp b/src/bin/strace/ioctl.cpp index e2bc1a6744..291f7cf06b 100644 --- a/src/bin/strace/ioctl.cpp +++ b/src/bin/strace/ioctl.cpp @@ -27,7 +27,7 @@ struct ioctl_info { static const ioctl_info kIOCtls[] = { // network stack ioctls - IOCTL_INFO_ENTRY(NET_STACK_SOCKET), + IOCTL_INFO_ENTRY_TYPE(NET_STACK_SOCKET, struct socket_args *), IOCTL_INFO_ENTRY(NET_STACK_GET_COOKIE), IOCTL_INFO_ENTRY(NET_STACK_CONTROL_NET_MODULE), IOCTL_INFO_ENTRY(NET_STACK_GET_NEXT_STAT), diff --git a/src/bin/strace/strace.cpp b/src/bin/strace/strace.cpp index 7ed3396b98..f8c24c1461 100644 --- a/src/bin/strace/strace.cpp +++ b/src/bin/strace/strace.cpp @@ -61,7 +61,8 @@ static const char *kUsage = " -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" +" is one of: strings, enums, simple, complex or\n" +" pointer_values\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" @@ -483,6 +484,8 @@ main(int argc, const char *const *argv) contentsFlags |= Context::SIMPLE_STRUCTS; else if (strcasecmp(what, "complex") == 0) contentsFlags |= Context::COMPLEX_STRUCTS; + else if (strcasecmp(what, "pointer_values") == 0) + contentsFlags |= Context::POINTER_VALUES; else { fprintf(stderr, "%s: Unknown content filter `%s'\n", kCommandName, what);