Patch by Hugo Santos. In his own words:
- moved the network type handling into NetworkTypes.cpp. - list the known socket options and some of their types (mostly only handling integers right now). - in order to look at the socket options values, i added specialized pointers to look at the value pointed by int *, unsigned int *, long *, unsigned long *, long long * and unsigned long long *. This proved helpful in other situations, such as looking at the msgCode of read_port_etc and other similiar cases. - i added a new option to -d, "pointer_values" to enable/disable this "look at integer pointer values" behavior. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20429 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
2f142f6139
commit
a71744ba3a
@ -12,7 +12,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
string
|
string
|
||||||
Context::FormatSigned(int64 value, int bytes) const
|
Context::FormatSigned(int64 value, int bytes) const
|
||||||
{
|
{
|
||||||
@ -42,7 +41,7 @@ Context::FormatSigned(int64 value, int bytes) const
|
|||||||
tmp[--offset] = 'x';
|
tmp[--offset] = 'x';
|
||||||
tmp[--offset] = '0';
|
tmp[--offset] = '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmp + offset;
|
return tmp + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,3 +60,11 @@ Context::FormatFlags(uint64 value) const
|
|||||||
snprintf(tmp, sizeof(tmp), "0x%llx", value);
|
snprintf(tmp, sizeof(tmp), "0x%llx", value);
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
Context::FormatPointer(const void *address) const
|
||||||
|
{
|
||||||
|
char buffer[32];
|
||||||
|
sprintf(buffer, "%p", address);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
@ -18,6 +18,7 @@ public:
|
|||||||
ENUMERATIONS = 1 << 1,
|
ENUMERATIONS = 1 << 1,
|
||||||
SIMPLE_STRUCTS = 1 << 2,
|
SIMPLE_STRUCTS = 1 << 2,
|
||||||
COMPLEX_STRUCTS = 1 << 3,
|
COMPLEX_STRUCTS = 1 << 3,
|
||||||
|
POINTER_VALUES = 1 << 4,
|
||||||
ALL = 0xffffffff
|
ALL = 0xffffffff
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -41,6 +42,8 @@ public:
|
|||||||
string FormatUnsigned(uint64 value) const;
|
string FormatUnsigned(uint64 value) const;
|
||||||
string FormatFlags(uint64 value) const;
|
string FormatFlags(uint64 value) const;
|
||||||
|
|
||||||
|
string FormatPointer(const void *address) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Syscall *fSyscall;
|
Syscall *fSyscall;
|
||||||
char *fData;
|
char *fData;
|
||||||
|
@ -9,7 +9,8 @@ UsePrivateHeaders net ;
|
|||||||
SubDirHdrs $(TARGET_COMMON_DEBUG_LOCATE_TARGET) ;
|
SubDirHdrs $(TARGET_COMMON_DEBUG_LOCATE_TARGET) ;
|
||||||
|
|
||||||
local straceSources =
|
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
|
# Our compiler badly chokes when compiling the generated file. So will
|
||||||
|
412
src/bin/strace/NetworkTypes.cpp
Normal file
412
src/bin/strace/NetworkTypes.cpp
Normal file
@ -0,0 +1,412 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2007, Haiku Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Hugo Santos <hugosantos@gmail.com>
|
||||||
|
* Ingo Weinhold <bonefish@cs.tu-berlin.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
// headers required for network structures
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#include <net_stack_driver.h>
|
||||||
|
|
||||||
|
#include "Context.h"
|
||||||
|
#include "MemoryReader.h"
|
||||||
|
#include "TypeHandler.h"
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
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<struct fd_set *>::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<struct fd_set *>::GetReturnValue(Context &context, uint64 value)
|
||||||
|
{
|
||||||
|
return context.FormatPointer((void *)value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
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<struct sockaddr>(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<struct sockaddr>(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<type *>::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<pair<int, int>, 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<struct sockaddr>(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<typename Type>
|
||||||
|
class SpecializedPointerTypeHandler : public TypeHandler {
|
||||||
|
string GetParameterValue(Context &context, Parameter *,
|
||||||
|
const void *address)
|
||||||
|
{
|
||||||
|
return format_pointer_value<Type>(context, *(void **)address);
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetReturnValue(Context &context, uint64 value)
|
||||||
|
{
|
||||||
|
return format_pointer_value<Type>(context, (void *)value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEFINE_TYPE(name, type) \
|
||||||
|
TypeHandler *create_##name##_type_handler() \
|
||||||
|
{ \
|
||||||
|
return new TypeHandlerImpl<type>(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define POINTER_TYPE(name, type) \
|
||||||
|
TypeHandler *create_##name##_type_handler() \
|
||||||
|
{ \
|
||||||
|
return new SpecializedPointerTypeHandler<type>(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
@ -9,25 +9,10 @@
|
|||||||
|
|
||||||
#include "TypeHandler.h"
|
#include "TypeHandler.h"
|
||||||
|
|
||||||
// headers required for network structures
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
|
|
||||||
#include <net_stack_driver.h>
|
|
||||||
|
|
||||||
#include "Context.h"
|
#include "Context.h"
|
||||||
#include "MemoryReader.h"
|
#include "MemoryReader.h"
|
||||||
#include "Syscall.h"
|
#include "Syscall.h"
|
||||||
|
|
||||||
// TypeHandlerImpl
|
|
||||||
template<typename Type>
|
|
||||||
class TypeHandlerImpl : public TypeHandler {
|
|
||||||
public:
|
|
||||||
virtual string GetParameterValue(Context &, Parameter *, const void *);
|
|
||||||
virtual string GetReturnValue(Context &, uint64 value);
|
|
||||||
};
|
|
||||||
|
|
||||||
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)
|
||||||
@ -40,26 +25,6 @@ get_value(const void *address)
|
|||||||
|
|
||||||
// #pragma mark -
|
// #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
|
// create_pointer_type_handler
|
||||||
TypeHandler *
|
TypeHandler *
|
||||||
create_pointer_type_handler()
|
create_pointer_type_handler()
|
||||||
@ -126,11 +91,11 @@ TypeHandlerFactory<bool>::Create()
|
|||||||
// read_string
|
// read_string
|
||||||
static
|
static
|
||||||
string
|
string
|
||||||
read_string(MemoryReader &reader, void *data)
|
read_string(Context &context, void *data)
|
||||||
{
|
{
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
int32 bytesRead;
|
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) {
|
if (error == B_OK) {
|
||||||
// return string("\"") + string(buffer, bytesRead) + "\"";
|
// return string("\"") + string(buffer, bytesRead) + "\"";
|
||||||
//string result("\"");
|
//string result("\"");
|
||||||
@ -149,72 +114,24 @@ read_string(MemoryReader &reader, void *data)
|
|||||||
largeBuffer[len + 2] = '\0';
|
largeBuffer[len + 2] = '\0';
|
||||||
return largeBuffer;
|
return largeBuffer;
|
||||||
}
|
}
|
||||||
return get_pointer_value(&data) + " (" + strerror(error) + ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
static string
|
return context.FormatPointer(data) + " (" + strerror(error) + ")";
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// const void*
|
// const void*
|
||||||
template<>
|
template<>
|
||||||
string
|
string
|
||||||
TypeHandlerImpl<const void*>::GetParameterValue(Context &, Parameter *,
|
TypeHandlerImpl<const void*>::GetParameterValue(Context &context, Parameter *,
|
||||||
const void *address)
|
const void *address)
|
||||||
{
|
{
|
||||||
return get_pointer_value(address);
|
return context.FormatPointer(*(void **)address);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
string
|
string
|
||||||
TypeHandlerImpl<const void*>::GetReturnValue(Context &, uint64 value)
|
TypeHandlerImpl<const void*>::GetReturnValue(Context &context, uint64 value)
|
||||||
{
|
{
|
||||||
return get_pointer_value(value);
|
return context.FormatPointer((void *)value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// const char*
|
// const char*
|
||||||
@ -225,9 +142,9 @@ TypeHandlerImpl<const char*>::GetParameterValue(Context &context, Parameter *,
|
|||||||
{
|
{
|
||||||
void *data = *(void **)address;
|
void *data = *(void **)address;
|
||||||
if (data != NULL && context.GetContents(Context::STRINGS))
|
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<>
|
template<>
|
||||||
@ -238,25 +155,6 @@ TypeHandlerImpl<const char*>::GetReturnValue(Context &context, uint64 value)
|
|||||||
return GetParameterValue(context, NULL, (const void *)&ptr);
|
return GetParameterValue(context, NULL, (const void *)&ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// struct fd_set *
|
|
||||||
template<>
|
|
||||||
string
|
|
||||||
TypeHandlerImpl<struct fd_set *>::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<struct fd_set *>::GetReturnValue(Context &, uint64 value)
|
|
||||||
{
|
|
||||||
return get_pointer_value(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
EnumTypeHandler::EnumTypeHandler(const EnumMap &m) : fMap(m) {}
|
EnumTypeHandler::EnumTypeHandler(const EnumMap &m) : fMap(m) {}
|
||||||
|
|
||||||
string
|
string
|
||||||
@ -309,133 +207,44 @@ TypeHandlerSelector::GetReturnValue(Context &context, uint64 value)
|
|||||||
return fDefault->GetReturnValue(context, value);
|
return fDefault->GetReturnValue(context, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Base>
|
template<typename Type>
|
||||||
static string
|
static bool
|
||||||
format_pointer_deep(Context &context, void *address)
|
obtain_pointer_data(Context &context, Type *data, void *address, uint32 what)
|
||||||
{
|
{
|
||||||
if (address == NULL || !context.GetContents(Context::COMPLEX_STRUCTS))
|
if (address == NULL || !context.GetContents(what))
|
||||||
return get_pointer_value(&address);
|
return false;
|
||||||
|
|
||||||
Base data;
|
|
||||||
int32 bytesRead;
|
int32 bytesRead;
|
||||||
|
|
||||||
status_t err = context.Reader().Read(address, &data, sizeof(Base), bytesRead);
|
status_t err = context.Reader().Read(address, data, sizeof(Type), bytesRead);
|
||||||
if (err != B_OK || bytesRead < (int32)sizeof(Base))
|
if (err != B_OK || bytesRead < (int32)sizeof(Type))
|
||||||
return get_pointer_value(&address);
|
return false;
|
||||||
|
|
||||||
return format_pointer(context, &data);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Base>
|
template<typename Type>
|
||||||
static string
|
static string
|
||||||
format_pointer_value(Context &context, const void *pointer)
|
format_signed_integer_pointer(Context &context, void *address)
|
||||||
{
|
{
|
||||||
return format_pointer_deep<Base>(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<typename Base>
|
template<typename Type>
|
||||||
static string
|
static string
|
||||||
format_pointer_value(Context &context, uint64 value)
|
format_unsigned_integer_pointer(Context &context, void *address)
|
||||||
{
|
{
|
||||||
return format_pointer_deep<Base>(context, (void *)value);
|
Type data;
|
||||||
}
|
|
||||||
|
|
||||||
static string
|
if (obtain_pointer_data(context, &data, address, Context::POINTER_VALUES))
|
||||||
get_ipv4_address(struct in_addr *addr)
|
return "[" + context.FormatUnsigned(data) + "]";
|
||||||
{
|
|
||||||
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
|
return context.FormatPointer(address);
|
||||||
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<struct sockaddr>(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<struct sockaddr>(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<struct sockaddr>(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<typename Type>
|
template<typename Type>
|
||||||
@ -469,25 +278,33 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
class SpecializedPointerTypeHandler : public TypeHandler {
|
class SignedIntegerPointerTypeHandler : public TypeHandler {
|
||||||
string GetParameterValue(Context &context, Parameter *,
|
string GetParameterValue(Context &context, Parameter *,
|
||||||
const void *address)
|
const void *address)
|
||||||
{
|
{
|
||||||
return format_pointer_value<Type>(context, address);
|
return format_signed_integer_pointer<Type>(context, *(void **)address);
|
||||||
}
|
}
|
||||||
|
|
||||||
string GetReturnValue(Context &context, uint64 value)
|
string GetReturnValue(Context &context, uint64 value)
|
||||||
{
|
{
|
||||||
return format_pointer_value<Type>(context, value);
|
return format_signed_integer_pointer<Type>(context, (void *)value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEFINE_TYPE(name, type) \
|
template<typename Type>
|
||||||
TypeHandler *create_##name##_type_handler() \
|
class UnsignedIntegerPointerTypeHandler : public TypeHandler {
|
||||||
{ \
|
string GetParameterValue(Context &context, Parameter *,
|
||||||
return new TypeHandlerImpl<type>(); \
|
const void *address)
|
||||||
|
{
|
||||||
|
return format_unsigned_integer_pointer<Type>(context, *(void **)address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string GetReturnValue(Context &context, uint64 value)
|
||||||
|
{
|
||||||
|
return format_unsigned_integer_pointer<Type>(context, (void *)value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#define SIGNED_INTEGER_TYPE(type) \
|
#define SIGNED_INTEGER_TYPE(type) \
|
||||||
template<> \
|
template<> \
|
||||||
TypeHandler * \
|
TypeHandler * \
|
||||||
@ -504,12 +321,19 @@ class SpecializedPointerTypeHandler : public TypeHandler {
|
|||||||
return new UnsignedIntegerTypeHandler<type>(); \
|
return new UnsignedIntegerTypeHandler<type>(); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define POINTER_TYPE(name, type) \
|
#define SIGNED_INTEGER_POINTER_TYPE(name, type) \
|
||||||
TypeHandler *create_##name##_type_handler() \
|
TypeHandler *create_##name##_type_handler() \
|
||||||
{ \
|
{ \
|
||||||
return new SpecializedPointerTypeHandler<type>(); \
|
return new SignedIntegerPointerTypeHandler<type>(); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define UNSIGNED_INTEGER_POINTER_TYPE(name, type) \
|
||||||
|
TypeHandler *create_##name##_type_handler() \
|
||||||
|
{ \
|
||||||
|
return new UnsignedIntegerPointerTypeHandler<type>(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SIGNED_INTEGER_TYPE(char);
|
SIGNED_INTEGER_TYPE(char);
|
||||||
SIGNED_INTEGER_TYPE(short);
|
SIGNED_INTEGER_TYPE(short);
|
||||||
SIGNED_INTEGER_TYPE(int);
|
SIGNED_INTEGER_TYPE(int);
|
||||||
@ -522,9 +346,11 @@ UNSIGNED_INTEGER_TYPE(unsigned int);
|
|||||||
UNSIGNED_INTEGER_TYPE(unsigned long);
|
UNSIGNED_INTEGER_TYPE(unsigned long);
|
||||||
UNSIGNED_INTEGER_TYPE(unsigned long long);
|
UNSIGNED_INTEGER_TYPE(unsigned long long);
|
||||||
|
|
||||||
DEFINE_TYPE(fdset_ptr, struct fd_set *);
|
SIGNED_INTEGER_POINTER_TYPE(int_ptr, int);
|
||||||
POINTER_TYPE(sockaddr_args_ptr, struct sockaddr_args);
|
SIGNED_INTEGER_POINTER_TYPE(long_ptr, long);
|
||||||
POINTER_TYPE(transfer_args_ptr, struct transfer_args);
|
SIGNED_INTEGER_POINTER_TYPE(longlong_ptr, long long);
|
||||||
POINTER_TYPE(sockopt_args_ptr, struct sockopt_args);
|
|
||||||
POINTER_TYPE(msghdr_ptr, struct msghdr);
|
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);
|
||||||
|
|
||||||
|
@ -101,6 +101,14 @@ DEFINE_FACTORY(fdset_ptr, struct fd_set *);
|
|||||||
DEFINE_FACTORY(sockaddr_args_ptr, struct sockaddr_args *);
|
DEFINE_FACTORY(sockaddr_args_ptr, struct sockaddr_args *);
|
||||||
DEFINE_FACTORY(transfer_args_ptr, struct transfer_args *);
|
DEFINE_FACTORY(transfer_args_ptr, struct transfer_args *);
|
||||||
DEFINE_FACTORY(sockopt_args_ptr, struct sockopt_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
|
// partial specialization for generic pointers
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
@ -111,4 +119,11 @@ struct TypeHandlerFactory<Type*> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
class TypeHandlerImpl : public TypeHandler {
|
||||||
|
public:
|
||||||
|
string GetParameterValue(Context &, Parameter *, const void *);
|
||||||
|
string GetReturnValue(Context &, uint64 value);
|
||||||
|
};
|
||||||
|
|
||||||
#endif // STRACE_TYPE_HANDLER_H
|
#endif // STRACE_TYPE_HANDLER_H
|
||||||
|
@ -27,7 +27,7 @@ struct ioctl_info {
|
|||||||
|
|
||||||
static const ioctl_info kIOCtls[] = {
|
static const ioctl_info kIOCtls[] = {
|
||||||
// network stack ioctls
|
// 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_GET_COOKIE),
|
||||||
IOCTL_INFO_ENTRY(NET_STACK_CONTROL_NET_MODULE),
|
IOCTL_INFO_ENTRY(NET_STACK_CONTROL_NET_MODULE),
|
||||||
IOCTL_INFO_ENTRY(NET_STACK_GET_NEXT_STAT),
|
IOCTL_INFO_ENTRY(NET_STACK_GET_NEXT_STAT),
|
||||||
|
@ -61,7 +61,8 @@ static const char *kUsage =
|
|||||||
" -a - Don't print syscall arguments.\n"
|
" -a - Don't print syscall arguments.\n"
|
||||||
" -c - Don't colorize output.\n"
|
" -c - Don't colorize output.\n"
|
||||||
" -d <name> - Filter the types that have their contents retrieved.\n"
|
" -d <name> - Filter the types that have their contents retrieved.\n"
|
||||||
" <name> is one of: strings, enums, simple or complex\n"
|
" <name> is one of: strings, enums, simple, complex or\n"
|
||||||
|
" pointer_values\n"
|
||||||
" -f - Fast mode. Syscall arguments contents aren't retrieved.\n"
|
" -f - Fast mode. Syscall arguments contents aren't retrieved.\n"
|
||||||
" -h, --help - Print this text.\n"
|
" -h, --help - Print this text.\n"
|
||||||
" -i - Print integers in decimal format instead of hexadecimal.\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;
|
contentsFlags |= Context::SIMPLE_STRUCTS;
|
||||||
else if (strcasecmp(what, "complex") == 0)
|
else if (strcasecmp(what, "complex") == 0)
|
||||||
contentsFlags |= Context::COMPLEX_STRUCTS;
|
contentsFlags |= Context::COMPLEX_STRUCTS;
|
||||||
|
else if (strcasecmp(what, "pointer_values") == 0)
|
||||||
|
contentsFlags |= Context::POINTER_VALUES;
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, "%s: Unknown content filter `%s'\n",
|
fprintf(stderr, "%s: Unknown content filter `%s'\n",
|
||||||
kCommandName, what);
|
kCommandName, what);
|
||||||
|
Loading…
Reference in New Issue
Block a user