1/* 2 * Copyright 2005-2007, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Ingo Weinhold <bonefish@cs.tu-berlin.de> 7 * Hugo Santos <hugosantos@gmail.com> 8 */ 9 10#include "TypeHandler.h" 11 12#include <string.h> 13 14#include "Context.h" 15#include "MemoryReader.h" 16#include "Syscall.h" 17 18template<typename value_t> 19static inline value_t 20get_value(const void *address) 21{ 22 if (sizeof(align_t) > sizeof(value_t)) 23 return value_t(*(align_t*)address); 24 else 25 return *(value_t*)address; 26} 27 28// #pragma mark - 29 30// create_pointer_type_handler 31TypeHandler * 32create_pointer_type_handler() 33{ 34 return new TypeHandlerImpl<const void*>(); 35} 36 37// create_string_type_handler 38TypeHandler * 39create_string_type_handler() 40{ 41 return new TypeHandlerImpl<const char*>(); 42} 43 44// #pragma mark - 45 46// complete specializations 47 48// void 49template<> 50string 51TypeHandlerImpl<void>::GetParameterValue(Context &, Parameter *, const void *) 52{ 53 return "void"; 54} 55 56template<> 57string 58TypeHandlerImpl<void>::GetReturnValue(Context &, uint64 value) 59{ 60 return ""; 61} 62 63template<> 64TypeHandler * 65TypeHandlerFactory<void>::Create() 66{ 67 return new TypeHandlerImpl<void>(); 68} 69 70// bool 71template<> 72string 73TypeHandlerImpl<bool>::GetParameterValue(Context &, Parameter *, 74 const void *address) 75{ 76 return (*(const align_t*)address ? "true" : "false"); 77} 78 79template<> 80string 81TypeHandlerImpl<bool>::GetReturnValue(Context &, uint64 value) 82{ 83 return (value ? "true" : "false"); 84} 85 86template<> 87TypeHandler * 88TypeHandlerFactory<bool>::Create() 89{ 90 return new TypeHandlerImpl<bool>(); 91} 92 93// read_string 94static 95string 96read_string(Context &context, void *data) 97{ 98 if (data == NULL || !context.GetContents(Context::STRINGS)) 99 return context.FormatPointer(data); 100 101 char buffer[256]; 102 int32 bytesRead; 103 status_t error = context.Reader().Read(data, buffer, sizeof(buffer), bytesRead); 104 if (error == B_OK) { 105// return string("\"") + string(buffer, bytesRead) + "\""; 106//string result("\""); 107//result += string(buffer, bytesRead); 108//result += "\""; 109//return result; 110 111// TODO: Unless I'm missing something obvious, our STL string class is broken. 112// The appended "\"" doesn't appear in either of the above cases. 113 114 int32 len = strnlen(buffer, sizeof(buffer)); 115 char largeBuffer[259]; 116 largeBuffer[0] = '"'; 117 memcpy(largeBuffer + 1, buffer, len); 118 largeBuffer[len + 1] = '"'; 119 largeBuffer[len + 2] = '\0'; 120 return largeBuffer; 121 } 122 123 return context.FormatPointer(data) + " (" + strerror(error) + ")"; 124} 125 126// const void* 127template<> 128string 129TypeHandlerImpl<const void*>::GetParameterValue(Context &context, Parameter *, 130 const void *address) 131{ 132 return context.FormatPointer(*(void **)address); 133} 134 135template<> 136string 137TypeHandlerImpl<const void*>::GetReturnValue(Context &context, uint64 value) 138{ 139 return context.FormatPointer((void *)value); 140} 141 142// const char* 143template<> 144string 145TypeHandlerImpl<const char*>::GetParameterValue(Context &context, Parameter *, 146 const void *address) 147{ 148 return read_string(context, *(void **)address); 149} 150 151template<> 152string 153TypeHandlerImpl<const char*>::GetReturnValue(Context &context, uint64 value) 154{ 155 return read_string(context, (void *)value); 156} 157 158EnumTypeHandler::EnumTypeHandler(const EnumMap &m) : fMap(m) {} 159 160string 161EnumTypeHandler::GetParameterValue(Context &context, Parameter *, 162 const void *address) 163{ 164 return RenderValue(context, get_value<unsigned int>(address)); 165} 166 167string 168EnumTypeHandler::GetReturnValue(Context &context, uint64 value) 169{ 170 return RenderValue(context, value); 171} 172 173string 174EnumTypeHandler::RenderValue(Context &context, unsigned int value) const 175{ 176 if (context.GetContents(Context::ENUMERATIONS)) { 177 EnumMap::const_iterator i = fMap.find(value); 178 if (i != fMap.end() && i->second != NULL) 179 return i->second; 180 } 181 182 return context.FormatUnsigned(value); 183} 184 185TypeHandlerSelector::TypeHandlerSelector(const SelectMap &m, int sibling, 186 TypeHandler *def) 187 : fMap(m), fSibling(sibling), fDefault(def) {} 188 189string 190TypeHandlerSelector::GetParameterValue(Context &context, Parameter *param, 191 const void *address) 192{ 193 TypeHandler *target = fDefault; 194 195 int index = get_value<int>(context.GetValue(context.GetSibling(fSibling))); 196 197 SelectMap::const_iterator i = fMap.find(index); 198 if (i != fMap.end()) 199 target = i->second; 200 201 return target->GetParameterValue(context, param, address); 202} 203 204string 205TypeHandlerSelector::GetReturnValue(Context &context, uint64 value) 206{ 207 return fDefault->GetReturnValue(context, value); 208} 209 210template<typename Type> 211static bool 212obtain_pointer_data(Context &context, Type *data, void *address, uint32 what) 213{ 214 if (address == NULL || !context.GetContents(what)) 215 return false; 216 217 int32 bytesRead; 218 219 status_t err = context.Reader().Read(address, data, sizeof(Type), bytesRead); 220 if (err != B_OK || bytesRead < (int32)sizeof(Type)) 221 return false; 222 223 return true; 224} 225 226template<typename Type> 227static string 228format_signed_integer_pointer(Context &context, void *address) 229{ 230 Type data; 231 232 if (obtain_pointer_data(context, &data, address, Context::POINTER_VALUES)) 233 return "[" + context.FormatSigned(data, sizeof(Type)) + "]"; 234 235 return context.FormatPointer(address); 236} 237 238template<typename Type> 239static string 240format_unsigned_integer_pointer(Context &context, void *address) 241{ 242 Type data; 243 244 if (obtain_pointer_data(context, &data, address, Context::POINTER_VALUES)) 245 return "[" + context.FormatUnsigned(data) + "]"; 246 247 return context.FormatPointer(address); 248} 249 250template<typename Type> 251class SignedIntegerTypeHandler : public TypeHandler { 252public: 253 string GetParameterValue(Context &context, Parameter *, 254 const void *address) 255 { 256 return context.FormatSigned(get_value<Type>(address), sizeof(Type)); 257 } 258 259 string GetReturnValue(Context &context, uint64 value) 260 { 261 return context.FormatSigned(value, sizeof(Type)); 262 } 263}; 264 265template<typename Type> 266class UnsignedIntegerTypeHandler : public TypeHandler { 267public: 268 string GetParameterValue(Context &context, Parameter *, 269 const void *address) 270 { 271 return context.FormatUnsigned(get_value<Type>(address)); 272 } 273 274 string GetReturnValue(Context &context, uint64 value) 275 { 276 return context.FormatUnsigned(value); 277 } 278}; 279 280template<typename Type> 281class SignedIntegerPointerTypeHandler : public TypeHandler { 282 string GetParameterValue(Context &context, Parameter *, 283 const void *address) 284 { 285 return format_signed_integer_pointer<Type>(context, *(void **)address); 286 } 287 288 string GetReturnValue(Context &context, uint64 value) 289 { 290 return format_signed_integer_pointer<Type>(context, (void *)value); 291 } 292}; 293 294template<typename Type> 295class UnsignedIntegerPointerTypeHandler : public TypeHandler { 296 string GetParameterValue(Context &context, Parameter *, 297 const void *address) 298 { 299 return format_unsigned_integer_pointer<Type>(context, *(void **)address); 300 } 301 302 string GetReturnValue(Context &context, uint64 value) 303 { 304 return format_unsigned_integer_pointer<Type>(context, (void *)value); 305 } 306}; 307 308#define SIGNED_INTEGER_TYPE(type) \ 309 template<> \ 310 TypeHandler * \ 311 TypeHandlerFactory<type>::Create() \ 312 { \ 313 return new SignedIntegerTypeHandler<type>(); \ 314 } 315 316#define UNSIGNED_INTEGER_TYPE(type) \ 317 template<> \ 318 TypeHandler * \ 319 TypeHandlerFactory<type>::Create() \ 320 { \ 321 return new UnsignedIntegerTypeHandler<type>(); \ 322 } 323 324#define SIGNED_INTEGER_POINTER_TYPE(name, type) \ 325 TypeHandler *create_##name##_type_handler() \ 326 { \ 327 return new SignedIntegerPointerTypeHandler<type>(); \ 328 } 329 330#define UNSIGNED_INTEGER_POINTER_TYPE(name, type) \ 331 TypeHandler *create_##name##_type_handler() \ 332 { \ 333 return new UnsignedIntegerPointerTypeHandler<type>(); \ 334 } 335 336 337SIGNED_INTEGER_TYPE(char); 338SIGNED_INTEGER_TYPE(short); 339SIGNED_INTEGER_TYPE(int); 340SIGNED_INTEGER_TYPE(long); 341SIGNED_INTEGER_TYPE(long long); 342 343UNSIGNED_INTEGER_TYPE(unsigned char); 344UNSIGNED_INTEGER_TYPE(unsigned short); 345UNSIGNED_INTEGER_TYPE(unsigned int); 346UNSIGNED_INTEGER_TYPE(unsigned long); 347UNSIGNED_INTEGER_TYPE(unsigned long long); 348 349SIGNED_INTEGER_POINTER_TYPE(int_ptr, int); 350SIGNED_INTEGER_POINTER_TYPE(long_ptr, long); 351SIGNED_INTEGER_POINTER_TYPE(longlong_ptr, long long); 352 353UNSIGNED_INTEGER_POINTER_TYPE(uint_ptr, unsigned int); 354UNSIGNED_INTEGER_POINTER_TYPE(ulong_ptr, unsigned long); 355UNSIGNED_INTEGER_POINTER_TYPE(ulonglong_ptr, unsigned long long); 356 357