Patch by Hugo Santos:

* Print structures passed to ioctl() for several commands (networking and
  terminal).
* Optional hex/decimal formatting of numbers (option -i).
* New level of detail option -d.
* Other improvements, like the introduction of a Context class to simplify
  passing around stuff.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20423 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2007-03-26 01:25:59 +00:00
parent ea2de1a115
commit 567638c602
6 changed files with 623 additions and 319 deletions

View File

@ -3,11 +3,12 @@ SubDir HAIKU_TOP src bin strace ;
UseArchHeaders $(TARGET_ARCH) ; UseArchHeaders $(TARGET_ARCH) ;
UsePrivateHeaders kernel ; UsePrivateHeaders kernel ;
UsePrivateHeaders shared ; UsePrivateHeaders shared ;
UsePrivateHeaders net ;
# find headers generated by gensyscalls # find headers generated by gensyscalls
SubDirHdrs $(TARGET_COMMON_DEBUG_LOCATE_TARGET) ; 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 # Our compiler badly chokes when compiling the generated file. So will
# split up the job into 20 pieces. # split up the job into 20 pieces.

View File

@ -106,10 +106,50 @@ public:
return NULL; return NULL;
} }
static Syscall *GetSyscall(const char *);
private: private:
string fName; string fName;
Type *fReturnType; Type *fReturnType;
vector<Parameter*> fParameters; vector<Parameter*> 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 #endif // STRACE_SYSCALL_H

View File

@ -7,47 +7,38 @@
* Hugo Santos <hugosantos@gmail.com> * Hugo Santos <hugosantos@gmail.com>
*/ */
#include "MemoryReader.h"
#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 "MemoryReader.h"
#include "Syscall.h"
// TypeHandlerImpl // TypeHandlerImpl
template<typename Type> template<typename Type>
class TypeHandlerImpl : public TypeHandler { class TypeHandlerImpl : public TypeHandler {
public: public:
virtual string GetParameterValue(const void *address, bool getContents, virtual string GetParameterValue(Context &, Parameter *, const void *);
MemoryReader &reader); virtual string GetReturnValue(Context &, uint64 value);
virtual string GetReturnValue(uint64 value, bool getContents,
MemoryReader &reader);
}; };
// #pragma mark -
// get_number_value
template<typename value_t> template<typename value_t>
static inline static inline value_t
string get_value(const void *address)
get_number_value(value_t value, const char *format)
{
char buffer[32];
sprintf(buffer, format, value);
return buffer;
}
// get_number_value
template<typename value_t>
static inline
string
get_number_value(const void *address, const char *format)
{ {
if (sizeof(align_t) > sizeof(value_t)) if (sizeof(align_t) > sizeof(value_t))
return get_number_value<value_t>(value_t(*(align_t*)address), format); return value_t(*(align_t*)address);
else else
return get_number_value<value_t>(*(value_t*)address, format); return *(value_t*)address;
} }
// #pragma mark -
// get_pointer_value // get_pointer_value
static inline static inline
string string
@ -82,13 +73,6 @@ create_string_type_handler()
return new TypeHandlerImpl<const char*>(); return new TypeHandlerImpl<const char*>();
} }
TypeHandler *
create_fdset_type_handler()
{
return new TypeHandlerImpl<struct fd_set *>();
}
// #pragma mark - // #pragma mark -
// complete specializations // complete specializations
@ -96,16 +80,14 @@ create_fdset_type_handler()
// void // void
template<> template<>
string string
TypeHandlerImpl<void>::GetParameterValue(const void *address, bool getContents, TypeHandlerImpl<void>::GetParameterValue(Context &, Parameter *, const void *)
MemoryReader &reader)
{ {
return "void"; return "void";
} }
template<> template<>
string string
TypeHandlerImpl<void>::GetReturnValue(uint64 value, bool getContents, TypeHandlerImpl<void>::GetReturnValue(Context &, uint64 value)
MemoryReader &reader)
{ {
return ""; return "";
} }
@ -120,16 +102,15 @@ TypeHandlerFactory<void>::Create()
// bool // bool
template<> template<>
string string
TypeHandlerImpl<bool>::GetParameterValue(const void *address, bool getContents, TypeHandlerImpl<bool>::GetParameterValue(Context &, Parameter *,
MemoryReader &reader) const void *address)
{ {
return (*(align_t*)address ? "true" : "false"); return (*(const align_t*)address ? "true" : "false");
} }
template<> template<>
string string
TypeHandlerImpl<bool>::GetReturnValue(uint64 value, bool getContents, TypeHandlerImpl<bool>::GetReturnValue(Context &, uint64 value)
MemoryReader &reader)
{ {
return (value ? "true" : "false"); return (value ? "true" : "false");
} }
@ -141,223 +122,6 @@ TypeHandlerFactory<bool>::Create()
return new TypeHandlerImpl<bool>(); return new TypeHandlerImpl<bool>();
} }
// char
template<>
string
TypeHandlerImpl<char>::GetParameterValue(const void *address, bool getContents,
MemoryReader &reader)
{
return get_number_value<char>(address, "0x%x");
}
template<>
string
TypeHandlerImpl<char>::GetReturnValue(uint64 value, bool getContents,
MemoryReader &reader)
{
return get_number_value<char>(value, "0x%x");
}
template<>
TypeHandler *
TypeHandlerFactory<char>::Create()
{
return new TypeHandlerImpl<char>();
}
// short
template<>
string
TypeHandlerImpl<short>::GetParameterValue(const void *address, bool getContents,
MemoryReader &reader)
{
return get_number_value<short>(address, "0x%x");
}
template<>
string
TypeHandlerImpl<short>::GetReturnValue(uint64 value, bool getContents,
MemoryReader &reader)
{
return get_number_value<short>(value, "0x%x");
}
template<>
TypeHandler *
TypeHandlerFactory<short>::Create()
{
return new TypeHandlerImpl<short>();
}
// unsigned short
template<>
string
TypeHandlerImpl<unsigned short>::GetParameterValue(const void *address,
bool getContents, MemoryReader &reader)
{
return get_number_value<unsigned short>(address, "0x%x");
}
template<>
string
TypeHandlerImpl<unsigned short>::GetReturnValue(uint64 value, bool getContents,
MemoryReader &reader)
{
return get_number_value<unsigned short>(value, "0x%x");
}
template<>
TypeHandler *
TypeHandlerFactory<unsigned short>::Create()
{
return new TypeHandlerImpl<unsigned short>();
}
// int
template<>
string
TypeHandlerImpl<int>::GetParameterValue(const void *address, bool getContents,
MemoryReader &reader)
{
return get_number_value<int>(address, "0x%x");
}
template<>
string
TypeHandlerImpl<int>::GetReturnValue(uint64 value, bool getContents,
MemoryReader &reader)
{
return get_number_value<int>(value, "0x%x");
}
template<>
TypeHandler *
TypeHandlerFactory<int>::Create()
{
return new TypeHandlerImpl<int>();
}
// unsigned int
template<>
string
TypeHandlerImpl<unsigned int>::GetParameterValue(const void *address,
bool getContents, MemoryReader &reader)
{
return get_number_value<unsigned int>(address, "0x%x");
}
template<>
string
TypeHandlerImpl<unsigned int>::GetReturnValue(uint64 value, bool getContents,
MemoryReader &reader)
{
return get_number_value<unsigned int>(value, "0x%x");
}
template<>
TypeHandler *
TypeHandlerFactory<unsigned int>::Create()
{
return new TypeHandlerImpl<unsigned int>();
}
// long
template<>
string
TypeHandlerImpl<long>::GetParameterValue(const void *address, bool getContents,
MemoryReader &reader)
{
return get_number_value<long>(address, "0x%lx");
}
template<>
string
TypeHandlerImpl<long>::GetReturnValue(uint64 value, bool getContents,
MemoryReader &reader)
{
return get_number_value<long>(value, "0x%lx");
}
template<>
TypeHandler *
TypeHandlerFactory<long>::Create()
{
return new TypeHandlerImpl<long>();
}
// unsigned long
template<>
string
TypeHandlerImpl<unsigned long>::GetParameterValue(const void *address,
bool getContents, MemoryReader &reader)
{
return get_number_value<unsigned long>(address, "0x%lx");
}
template<>
string
TypeHandlerImpl<unsigned long>::GetReturnValue(uint64 value, bool getContents,
MemoryReader &reader)
{
return get_number_value<unsigned long>(value, "0x%lx");
}
template<>
TypeHandler *
TypeHandlerFactory<unsigned long>::Create()
{
return new TypeHandlerImpl<unsigned long>();
}
// long long
template<>
string
TypeHandlerImpl<long long>::GetParameterValue(const void *address,
bool getContents, MemoryReader &reader)
{
return get_number_value<long long>(address, "0x%llx");
}
template<>
string
TypeHandlerImpl<long long>::GetReturnValue(uint64 value, bool getContents,
MemoryReader &reader)
{
return get_number_value<long long>(value, "0x%llx");
}
template<>
TypeHandler *
TypeHandlerFactory<long long>::Create()
{
return new TypeHandlerImpl<long long>();
}
// unsigned long
template<>
string
TypeHandlerImpl<unsigned long long>::GetParameterValue(const void *address,
bool getContents, MemoryReader &reader)
{
return get_number_value<unsigned long>(address, "0x%llx");
}
template<>
string
TypeHandlerImpl<unsigned long long>::GetReturnValue(uint64 value,
bool getContents, MemoryReader &reader)
{
return get_number_value<unsigned long long>(value, "0x%llx");
}
template<>
TypeHandler *
TypeHandlerFactory<unsigned long long>::Create()
{
return new TypeHandlerImpl<unsigned long long>();
}
// read_string // read_string
static static
string string
@ -388,13 +152,21 @@ read_string(MemoryReader &reader, void *data)
} }
static string 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)]; unsigned long tmp[1024 / (sizeof(unsigned long) * 8)];
int32 bytesRead; 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) if (err != B_OK)
return get_pointer_value(&data); return get_pointer_value(&data);
@ -402,17 +174,19 @@ read_fdset(MemoryReader &reader, void *data)
int count = bytesRead / sizeof(unsigned long); int count = bytesRead / sizeof(unsigned long);
int added = 0; int added = 0;
string r = "["; string r;
r.reserve(16);
r = "[";
for (int i = 0; i < count && added < 8; i++) { for (int i = 0; i < count && added < 8; i++) {
for (int j = 0; for (int j = 0;
j < (int)(sizeof(unsigned long) * 8) && added < 8; j++) { j < (int)(sizeof(unsigned long) * 8) && added < 8; j++) {
if (tmp[i] & (1 << j)) { if (tmp[i] & (1 << j)) {
if (added > 0) if (added > 0)
r += ", "; r += " ";
r += get_number_value<unsigned long>( unsigned int fd = i * sizeof(unsigned long) * 8 + j;
i * (sizeof(unsigned long) * 8) + j, r += format_number(fd);
"%u");
added++; added++;
} }
} }
@ -421,22 +195,23 @@ read_fdset(MemoryReader &reader, void *data)
if (added >= 8) if (added >= 8)
r += " ..."; r += " ...";
return r + "]"; r += "]";
return r;
} }
// const void* // const void*
template<> template<>
string string
TypeHandlerImpl<const void*>::GetParameterValue(const void *address, TypeHandlerImpl<const void*>::GetParameterValue(Context &, Parameter *,
bool getContents, MemoryReader &reader) const void *address)
{ {
return get_pointer_value(address); return get_pointer_value(address);
} }
template<> template<>
string string
TypeHandlerImpl<const void*>::GetReturnValue(uint64 value, bool getContents, TypeHandlerImpl<const void*>::GetReturnValue(Context &, uint64 value)
MemoryReader &reader)
{ {
return get_pointer_value(value); return get_pointer_value(value);
} }
@ -444,48 +219,317 @@ TypeHandlerImpl<const void*>::GetReturnValue(uint64 value, bool getContents,
// const char* // const char*
template<> template<>
string string
TypeHandlerImpl<const char*>::GetParameterValue(const void *address, TypeHandlerImpl<const char*>::GetParameterValue(Context &context, Parameter *,
bool getContents, MemoryReader &reader) const void *address)
{ {
void *data = *(void**)address; void *data = *(void **)address;
if (getContents && data) if (data != NULL && context.GetContents(Context::STRINGS))
return read_string(reader, data); return read_string(context.Reader(), data);
return get_pointer_value(&data); return get_pointer_value(&data);
} }
template<> template<>
string string
TypeHandlerImpl<const char*>::GetReturnValue(uint64 value, TypeHandlerImpl<const char*>::GetReturnValue(Context &context, uint64 value)
bool getContents, MemoryReader &reader)
{ {
void *data = (void*)value; void *ptr = (void *)value;
if (getContents && data) return GetParameterValue(context, NULL, (const void *)&ptr);
return read_string(reader, data);
return get_pointer_value(&data);
} }
// struct fd_set * // struct fd_set *
template<> template<>
string string
TypeHandlerImpl<struct fd_set *>::GetParameterValue(const void *address, TypeHandlerImpl<struct fd_set *>::GetParameterValue(Context &context, Parameter *,
bool getContents, MemoryReader &reader) const void *address)
{ {
void *data = *(void **)address; void *data = *(void **)address;
if (getContents && data) if (data != NULL && context.GetContents(Context::SIMPLE_STRUCTS))
return read_fdset(reader, data); return read_fdset(context, data);
return get_pointer_value(&data); return get_pointer_value(&data);
} }
template<> template<>
string string
TypeHandlerImpl<struct fd_set *>::GetReturnValue(uint64 value, TypeHandlerImpl<struct fd_set *>::GetReturnValue(Context &, uint64 value)
bool getContents, MemoryReader &reader)
{ {
void *data = (void *)value; return get_pointer_value(value);
if (getContents && data)
return read_fdset(reader, data);
return get_pointer_value(&data);
} }
EnumTypeHandler::EnumTypeHandler(const EnumMap &m) : fMap(m) {}
string
EnumTypeHandler::GetParameterValue(Context &context, Parameter *,
const void *address)
{
return RenderValue(context, get_value<unsigned int>(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<int>(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<typename Base>
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<typename Base>
static string
format_pointer_value(Context &context, const void *pointer)
{
return format_pointer_deep<Base>(context, *(void **)pointer);
}
template<typename Base>
static string
format_pointer_value(Context &context, uint64 value)
{
return format_pointer_deep<Base>(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<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>
class SignedIntegerTypeHandler : public TypeHandler {
public:
SignedIntegerTypeHandler(const char *modifier)
: fModifier(modifier) {}
string GetParameterValue(Context &context, Parameter *,
const void *address)
{
return context.FormatSigned(get_value<Type>(address), fModifier);
}
string GetReturnValue(Context &context, uint64 value)
{
return context.FormatSigned(value, fModifier);
}
private:
const char *fModifier;
};
template<typename Type>
class UnsignedIntegerTypeHandler : public TypeHandler {
public:
string GetParameterValue(Context &context, Parameter *,
const void *address)
{
return context.FormatUnsigned(get_value<Type>(address));
}
string GetReturnValue(Context &context, uint64 value)
{
return context.FormatUnsigned(value);
}
};
template<typename Type>
class SpecializedPointerTypeHandler : public TypeHandler {
string GetParameterValue(Context &context, Parameter *,
const void *address)
{
return format_pointer_value<Type>(context, address);
}
string GetReturnValue(Context &context, uint64 value)
{
return format_pointer_value<Type>(context, value);
}
};
#define DEFINE_TYPE(name, type) \
TypeHandler *create_##name##_type_handler() \
{ \
return new TypeHandlerImpl<type>(); \
}
#define SIGNED_INTEGER_TYPE(type, modifier) \
template<> \
TypeHandler * \
TypeHandlerFactory<type>::Create() \
{ \
return new SignedIntegerTypeHandler<type>(modifier); \
}
#define UNSIGNED_INTEGER_TYPE(type) \
template<> \
TypeHandler * \
TypeHandlerFactory<type>::Create() \
{ \
return new UnsignedIntegerTypeHandler<type>(); \
}
#define POINTER_TYPE(name, type) \
TypeHandler *create_##name##_type_handler() \
{ \
return new SpecializedPointerTypeHandler<type>(); \
}
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);

View File

@ -10,12 +10,15 @@
#define STRACE_TYPE_HANDLER_H #define STRACE_TYPE_HANDLER_H
#include <string> #include <string>
#include <map>
#include <arch_config.h> #include <arch_config.h>
#include <SupportDefs.h> #include <SupportDefs.h>
using std::string; using std::string;
class Context;
class Parameter;
class MemoryReader; class MemoryReader;
typedef FUNCTION_CALL_PARAMETER_ALIGNMENT_TYPE align_t; typedef FUNCTION_CALL_PARAMETER_ALIGNMENT_TYPE align_t;
@ -26,11 +29,41 @@ public:
TypeHandler() {} TypeHandler() {}
virtual ~TypeHandler() {} virtual ~TypeHandler() {}
virtual string GetParameterValue(const void *address, bool getContents, virtual string GetParameterValue(Context &, Parameter *,
MemoryReader &reader) = 0; const void *value) = 0;
virtual string GetReturnValue(Context &, uint64 value) = 0;
};
virtual string GetReturnValue(uint64 value, bool getContents, class EnumTypeHandler : public TypeHandler {
MemoryReader &reader) = 0; public:
typedef std::map<int, const char *> 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<int, TypeHandler *> 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 // templatized TypeHandler factory class
@ -44,7 +77,6 @@ struct TypeHandlerFactory {
extern TypeHandler *create_pointer_type_handler(); extern TypeHandler *create_pointer_type_handler();
extern TypeHandler *create_string_type_handler(); extern TypeHandler *create_string_type_handler();
extern TypeHandler *create_fdset_type_handler();
// specialization for "const char*" // specialization for "const char*"
template<> template<>
@ -55,14 +87,20 @@ struct TypeHandlerFactory<const char*> {
} }
}; };
// specialization for 'struct fdset *' #define DEFINE_FACTORY(name, type) \
template<> template<> \
struct TypeHandlerFactory<struct fd_set *> { struct TypeHandlerFactory<type> { \
static inline TypeHandler *Create() static inline TypeHandler *Create() \
{ { \
return create_fdset_type_handler(); 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 // partial specialization for generic pointers
template<typename Type> template<typename Type>

91
src/bin/strace/ioctl.cpp Normal file
View File

@ -0,0 +1,91 @@
/*
* Copyright 2007, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Hugo Santos <hugosantos@gmail.com>
*/
#include <net_stack_driver.h>
#include <termios.h>
#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<type>::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<void *>::Create()));
}

View File

@ -59,8 +59,11 @@ static const char *kUsage =
"Options:\n" "Options:\n"
" -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"
" <name> is one of: strings, enums, simple or complex\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"
" -l - Also trace loading the excecutable. Only considered when\n" " -l - Also trace loading the excecutable. Only considered when\n"
" an executable is provided.\n" " an executable is provided.\n"
" -r - Don't print syscall return values.\n" " -r - Don't print syscall return values.\n"
@ -88,7 +91,6 @@ static const char *const *sArgv;
static vector<Syscall*> sSyscallVector; static vector<Syscall*> sSyscallVector;
static map<string, Syscall*> sSyscallMap; static map<string, Syscall*> sSyscallMap;
// print_usage // print_usage
void void
print_usage(bool error) 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 // init_syscalls
static static
void void
@ -299,6 +312,8 @@ init_syscalls()
Syscall *syscall = sSyscallVector[i]; Syscall *syscall = sSyscallVector[i];
sSyscallMap[syscall->Name()] = syscall; sSyscallMap[syscall->Name()] = syscall;
} }
patch_syscalls();
} }
// print_to_string // print_to_string
@ -319,14 +334,17 @@ print_to_string(char **_buffer, int32 *_length, const char *format, ...)
static static
void void
print_syscall(FILE *outputFile, debug_post_syscall &message, print_syscall(FILE *outputFile, debug_post_syscall &message,
MemoryReader &memoryReader, bool printArguments, bool getContents, MemoryReader &memoryReader, bool printArguments, uint32 contentsFlags,
bool printReturnValue, bool colorize) bool printReturnValue, bool colorize, bool decimal)
{ {
char buffer[4096], *string = buffer; char buffer[4096], *string = buffer;
int32 length = (int32)sizeof(buffer); int32 length = (int32)sizeof(buffer);
int32 syscallNumber = message.syscall; int32 syscallNumber = message.syscall;
Syscall *syscall = sSyscallVector[syscallNumber]; Syscall *syscall = sSyscallVector[syscallNumber];
Context ctx(syscall, (char *)message.args, memoryReader,
contentsFlags, decimal);
// print syscall name // print syscall name
if (colorize) { if (colorize) {
print_to_string(&string, &length, "[%6ld] %s%s%s(", print_to_string(&string, &length, "[%6ld] %s%s%s(",
@ -344,9 +362,9 @@ print_syscall(FILE *outputFile, debug_post_syscall &message,
// get the value // get the value
Parameter *parameter = syscall->ParameterAt(i); Parameter *parameter = syscall->ParameterAt(i);
TypeHandler *handler = parameter->Handler(); TypeHandler *handler = parameter->Handler();
::string value = handler->GetParameterValue( ::string value =
(char*)message.args + parameter->Offset(), getContents, handler->GetParameterValue(ctx, parameter,
memoryReader); ctx.GetValue(parameter));
print_to_string(&string, &length, (i > 0 ? ", %s" : "%s"), print_to_string(&string, &length, (i > 0 ? ", %s" : "%s"),
value.c_str()); value.c_str());
@ -359,8 +377,7 @@ print_syscall(FILE *outputFile, debug_post_syscall &message,
if (printReturnValue) { if (printReturnValue) {
Type *returnType = syscall->ReturnType(); Type *returnType = syscall->ReturnType();
TypeHandler *handler = returnType->Handler(); TypeHandler *handler = returnType->Handler();
::string value = handler->GetReturnValue(message.return_value, ::string value = handler->GetReturnValue(ctx, message.return_value);
getContents, memoryReader);
if (value.length() > 0) { if (value.length() > 0) {
print_to_string(&string, &length, " = %s", value.c_str()); print_to_string(&string, &length, " = %s", value.c_str());
@ -414,6 +431,8 @@ main(int argc, const char *const *argv)
int32 programArgCount = 0; int32 programArgCount = 0;
bool printArguments = true; bool printArguments = true;
bool colorize = true; bool colorize = true;
uint32 contentsFlags = 0;
bool decimalFormat = false;
bool fastMode = false; bool fastMode = false;
bool traceLoading = false; bool traceLoading = false;
bool printReturnValues = true; bool printReturnValues = true;
@ -433,8 +452,33 @@ main(int argc, const char *const *argv)
printArguments = false; printArguments = false;
} else if (strcmp(arg, "-c") == 0) { } else if (strcmp(arg, "-c") == 0) {
colorize = false; 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) { } else if (strcmp(arg, "-f") == 0) {
fastMode = true; fastMode = true;
} else if (strcmp(arg, "-i") == 0) {
decimalFormat = true;
} else if (strcmp(arg, "-l") == 0) { } else if (strcmp(arg, "-l") == 0) {
traceLoading = true; traceLoading = true;
} else if (strcmp(arg, "-r") == 0) { } else if (strcmp(arg, "-r") == 0) {
@ -479,6 +523,11 @@ main(int argc, const char *const *argv)
if (!programArgs) if (!programArgs)
print_usage_and_exit(true); print_usage_and_exit(true);
if (fastMode)
contentsFlags = 0;
else if (contentsFlags == 0)
contentsFlags = Context::ALL;
// initialize our syscalls vector and map // initialize our syscalls vector and map
init_syscalls(); init_syscalls();
@ -500,7 +549,7 @@ main(int argc, const char *const *argv)
programArgs[0], strerror(thread)); programArgs[0], strerror(thread));
exit(1); exit(1);
} }
} }
// get the team ID, if we have none yet // get the team ID, if we have none yet
if (team < 0) { if (team < 0) {
@ -571,7 +620,8 @@ main(int argc, const char *const *argv)
case B_DEBUGGER_MESSAGE_POST_SYSCALL: case B_DEBUGGER_MESSAGE_POST_SYSCALL:
{ {
print_syscall(outputFile, message.post_syscall, memoryReader, print_syscall(outputFile, message.post_syscall, memoryReader,
printArguments, !fastMode, printReturnValues, colorize); printArguments, contentsFlags, printReturnValues,
colorize, decimalFormat);
break; break;
} }
@ -611,3 +661,43 @@ main(int argc, const char *const *argv)
return 0; return 0;
} }
Syscall *
Syscall::GetSyscall(const char *name)
{
map<string, Syscall *>::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;
}