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:
parent
ea2de1a115
commit
567638c602
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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
91
src/bin/strace/ioctl.cpp
Normal 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()));
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user