#include "TypeHandler.h"
#include <string.h>
#include <String.h>
#include <sys/uio.h>
#include "Context.h"
#include "MemoryReader.h"
#include "Syscall.h"
template<typename value_t>
static inline value_t
get_value(const void *address)
{
if (sizeof(align_t) > sizeof(value_t))
return value_t(*(align_t*)address);
else
return *(value_t*)address;
}
TypeHandler *
create_pointer_type_handler()
{
return new TypeHandlerImpl<const void*>();
}
TypeHandler *
create_string_type_handler()
{
return new TypeHandlerImpl<const char*>();
}
template<>
string
TypeHandlerImpl<void>::GetParameterValue(Context &, Parameter *, const void *)
{
return "void";
}
template<>
string
TypeHandlerImpl<void>::GetReturnValue(Context &, uint64 value)
{
return "";
}
template<>
TypeHandler *
TypeHandlerFactory<void>::Create()
{
return new TypeHandlerImpl<void>();
}
template<>
string
TypeHandlerImpl<bool>::GetParameterValue(Context &, Parameter *,
const void *address)
{
return (*(const align_t*)address ? "true" : "false");
}
template<>
string
TypeHandlerImpl<bool>::GetReturnValue(Context &, uint64 value)
{
return (value ? "true" : "false");
}
template<>
TypeHandler *
TypeHandlerFactory<bool>::Create()
{
return new TypeHandlerImpl<bool>();
}
template<typename T>
class StatusTypeHandler : public TypeHandler {
public:
StatusTypeHandler() {}
string GetParameterValue(Context &context, Parameter *, const void *address)
{
return RenderValue(context, get_value<T>(address));
}
string GetReturnValue(Context &context, uint64 value)
{
return RenderValue(context, value);
}
private:
string RenderValue(Context &context, uint64 value) const
{
string rendered = context.FormatUnsigned(value);
if ((T)value <= 0) {
rendered += " ";
rendered += strerror(value);
}
return rendered;
}
};
TypeHandler *
create_status_t_type_handler()
{
return new StatusTypeHandler<status_t>;
}
TypeHandler *
create_ssize_t_type_handler()
{
return new StatusTypeHandler<ssize_t>;
}
static
string
read_string(Context &context, void *data)
{
if (data == NULL || !context.GetContents(Context::STRINGS))
return context.FormatPointer(data);
char buffer[256];
int32 bytesRead;
status_t error = context.Reader().Read(data, buffer, sizeof(buffer), bytesRead);
if (error == B_OK) {
string result("\"");
result += string(buffer, strnlen(buffer, sizeof(buffer)));
result += "\"";
return result;
}
return context.FormatPointer(data) + " (" + strerror(error) + ")";
}
template<>
string
TypeHandlerImpl<const void*>::GetParameterValue(Context &context, Parameter *,
const void *address)
{
return context.FormatPointer(*(void **)address);
}
template<>
string
TypeHandlerImpl<const void*>::GetReturnValue(Context &context, uint64 value)
{
return context.FormatPointer((void *)value);
}
template<>
string
TypeHandlerImpl<const char*>::GetParameterValue(Context &context, Parameter *,
const void *address)
{
return read_string(context, *(void **)address);
}
template<>
string
TypeHandlerImpl<const char*>::GetReturnValue(Context &context, uint64 value)
{
return read_string(context, (void *)value);
}
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);
}
FlagsTypeHandler::FlagsTypeHandler(const FlagsList &m) : fList(m) {}
string
FlagsTypeHandler::GetParameterValue(Context &context, Parameter *,
const void *address)
{
return RenderValue(context, get_value<unsigned int>(address));
}
string
FlagsTypeHandler::GetReturnValue(Context &context, uint64 value)
{
return RenderValue(context, value);
}
string
FlagsTypeHandler::RenderValue(Context &context, unsigned int value) const
{
if (context.GetContents(Context::ENUMERATIONS)) {
string rendered;
FlagsList::const_reverse_iterator i = fList.rbegin();
for (; i != fList.rend(); i++) {
if (value == 0)
break;
if ((value & i->value) != i->value)
continue;
if (!rendered.empty())
rendered.insert(0, "|");
rendered.insert(0, i->name);
value &= ~(i->value);
}
if (value != 0) {
if (!rendered.empty())
rendered += "|";
char hex[20];
snprintf(hex, sizeof(hex), "0x%x", value);
rendered += hex;
}
if (rendered.empty())
rendered = "0";
return rendered;
}
return context.FormatUnsigned(value);
}
EnumFlagsTypeHandler::EnumFlagsTypeHandler(const EnumMap &m, const FlagsTypeHandler::FlagsList &l)
:
EnumTypeHandler(m), fList(l) {}
string
EnumFlagsTypeHandler::RenderValue(Context &context, unsigned int value) const
{
if (context.GetContents(Context::ENUMERATIONS)) {
string rendered;
FlagsTypeHandler::FlagsList::const_reverse_iterator i = fList.rbegin();
for (; i != fList.rend(); i++) {
if (value == 0)
break;
if ((value & i->value) != i->value)
continue;
if (!rendered.empty())
rendered.insert(0, "|");
rendered.insert(0, i->name);
value &= ~(i->value);
}
EnumMap::const_iterator j = fMap.find(value);
if (j != fMap.end() && j->second != NULL) {
if (!rendered.empty())
rendered.insert(0, "|");
rendered.insert(0, j->second);
}
return rendered;
}
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 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;
}
template<typename Type>
static string
format_signed_integer_pointer(Context &context, void *address, uint32 count)
{
Type data;
if (obtain_pointer_data(context, &data, address, Context::POINTER_VALUES)) {
string formatted = "[" + context.FormatSigned(data);
for (uint32 i = 1; i < count; i++) {
address = (void*)((Type*)address + 1);
obtain_pointer_data(context, &data, address, Context::POINTER_VALUES);
formatted += ", " + context.FormatSigned(data);
}
formatted += "]";
return formatted;
}
return context.FormatPointer(address);
}
template<typename Type>
static string
format_unsigned_integer_pointer(Context &context, void *address, uint32 count)
{
Type data;
if (obtain_pointer_data(context, &data, address, Context::POINTER_VALUES)) {
string formatted = "[" + context.FormatUnsigned(data);
for (uint32 i = 1; i < count; i++) {
address = (void*)((Type*)address + 1);
obtain_pointer_data(context, &data, address, Context::POINTER_VALUES);
formatted += ", " + context.FormatUnsigned(data);
}
formatted += "]";
return formatted;
}
return context.FormatPointer(address);
}
template<typename Type>
class SignedIntegerTypeHandler : public TypeHandler {
public:
string GetParameterValue(Context &context, Parameter *,
const void *address)
{
return context.FormatSigned(get_value<Type>(address), sizeof(Type));
}
string GetReturnValue(Context &context, uint64 value)
{
return context.FormatSigned(value, sizeof(Type));
}
};
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 SignedIntegerPointerTypeHandler : public TypeHandler {
string GetParameterValue(Context &context, Parameter *parameter,
const void *address)
{
return format_signed_integer_pointer<Type>(context, *(void **)address,
parameter->Count());
}
string GetReturnValue(Context &context, uint64 value)
{
return format_signed_integer_pointer<Type>(context, (void *)value, 1);
}
};
template<typename Type>
class UnsignedIntegerPointerTypeHandler : public TypeHandler {
string GetParameterValue(Context &context, Parameter *parameter,
const void *address)
{
return format_unsigned_integer_pointer<Type>(context, *(void **)address,
parameter->Count());
}
string GetReturnValue(Context &context, uint64 value)
{
return format_unsigned_integer_pointer<Type>(context, (void *)value, 1);
}
};
#define SIGNED_INTEGER_TYPE(type) \
template<> \
TypeHandler * \
TypeHandlerFactory<type>::Create() \
{ \
return new SignedIntegerTypeHandler<type>(); \
}
#define UNSIGNED_INTEGER_TYPE(type) \
template<> \
TypeHandler * \
TypeHandlerFactory<type>::Create() \
{ \
return new UnsignedIntegerTypeHandler<type>(); \
}
#define SIGNED_INTEGER_POINTER_TYPE(name, type) \
TypeHandler *create_##name##_type_handler() \
{ \
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(short);
SIGNED_INTEGER_TYPE(int);
SIGNED_INTEGER_TYPE(long);
SIGNED_INTEGER_TYPE(long long);
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);
SIGNED_INTEGER_POINTER_TYPE(int_ptr, int);
SIGNED_INTEGER_POINTER_TYPE(long_ptr, long);
SIGNED_INTEGER_POINTER_TYPE(longlong_ptr, long long);
UNSIGNED_INTEGER_POINTER_TYPE(uint_ptr, unsigned int);
UNSIGNED_INTEGER_POINTER_TYPE(ulong_ptr, unsigned long);
UNSIGNED_INTEGER_POINTER_TYPE(ulonglong_ptr, unsigned long long);