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#include <String.h> 14 15#include "Context.h" 16#include "MemoryReader.h" 17#include "Syscall.h" 18 19template<typename value_t> 20static inline value_t 21get_value(const void *address) 22{ 23 if (sizeof(align_t) > sizeof(value_t)) 24 return value_t(*(align_t*)address); 25 else 26 return *(value_t*)address; 27} 28 29// #pragma mark - 30 31// create_pointer_type_handler 32TypeHandler * 33create_pointer_type_handler() 34{ 35 return new TypeHandlerImpl<const void*>(); 36} 37 38// create_string_type_handler 39TypeHandler * 40create_string_type_handler() 41{ 42 return new TypeHandlerImpl<const char*>(); 43} 44 45// #pragma mark - 46 47// complete specializations 48 49// void 50template<> 51string 52TypeHandlerImpl<void>::GetParameterValue(Context &, Parameter *, const void *) 53{ 54 return "void"; 55} 56 57template<> 58string 59TypeHandlerImpl<void>::GetReturnValue(Context &, uint64 value) 60{ 61 return ""; 62} 63 64template<> 65TypeHandler * 66TypeHandlerFactory<void>::Create() 67{ 68 return new TypeHandlerImpl<void>(); 69} 70 71// bool 72template<> 73string 74TypeHandlerImpl<bool>::GetParameterValue(Context &, Parameter *, 75 const void *address) 76{ 77 return (*(const align_t*)address ? "true" : "false"); 78} 79 80template<> 81string 82TypeHandlerImpl<bool>::GetReturnValue(Context &, uint64 value) 83{ 84 return (value ? "true" : "false"); 85} 86 87template<> 88TypeHandler * 89TypeHandlerFactory<bool>::Create() 90{ 91 return new TypeHandlerImpl<bool>(); 92} 93 94// status_t 95class StatusTypeHandler : public TypeHandler { 96public: 97 StatusTypeHandler() {} 98 99 string GetParameterValue(Context &context, Parameter *, const void *address) 100 { 101 return RenderValue(context, get_value<status_t>(address)); 102 } 103 104 string GetReturnValue(Context &context, uint64 value) 105 { 106 return RenderValue(context, value); 107 } 108 109private: 110 string RenderValue(Context &context, uint64 value) const 111 { 112 string rendered = context.FormatUnsigned(value); 113 if (value <= UINT32_MAX && (status_t)value <= 0) { 114 rendered += " "; 115 rendered += strerror(value); 116 } 117 return rendered; 118 } 119}; 120 121TypeHandler * 122create_status_t_type_handler() 123{ 124 return new StatusTypeHandler; 125} 126 127// read_string 128static 129string 130read_string(Context &context, void *data) 131{ 132 if (data == NULL || !context.GetContents(Context::STRINGS)) 133 return context.FormatPointer(data); 134 135 char buffer[256]; 136 int32 bytesRead; 137 status_t error = context.Reader().Read(data, buffer, sizeof(buffer), bytesRead); 138 if (error == B_OK) { 139 string result("\""); 140 result += string(buffer, strnlen(buffer, sizeof(buffer))); 141 result += "\""; 142 return result; 143 } 144 145 return context.FormatPointer(data) + " (" + strerror(error) + ")"; 146} 147 148// const void* 149template<> 150string 151TypeHandlerImpl<const void*>::GetParameterValue(Context &context, Parameter *, 152 const void *address) 153{ 154 return context.FormatPointer(*(void **)address); 155} 156 157template<> 158string 159TypeHandlerImpl<const void*>::GetReturnValue(Context &context, uint64 value) 160{ 161 return context.FormatPointer((void *)value); 162} 163 164// const char* 165template<> 166string 167TypeHandlerImpl<const char*>::GetParameterValue(Context &context, Parameter *, 168 const void *address) 169{ 170 return read_string(context, *(void **)address); 171} 172 173template<> 174string 175TypeHandlerImpl<const char*>::GetReturnValue(Context &context, uint64 value) 176{ 177 return read_string(context, (void *)value); 178} 179 180EnumTypeHandler::EnumTypeHandler(const EnumMap &m) : fMap(m) {} 181 182string 183EnumTypeHandler::GetParameterValue(Context &context, Parameter *, 184 const void *address) 185{ 186 return RenderValue(context, get_value<unsigned int>(address)); 187} 188 189string 190EnumTypeHandler::GetReturnValue(Context &context, uint64 value) 191{ 192 return RenderValue(context, value); 193} 194 195string 196EnumTypeHandler::RenderValue(Context &context, unsigned int value) const 197{ 198 if (context.GetContents(Context::ENUMERATIONS)) { 199 EnumMap::const_iterator i = fMap.find(value); 200 if (i != fMap.end() && i->second != NULL) 201 return i->second; 202 } 203 204 return context.FormatUnsigned(value); 205} 206 207FlagsTypeHandler::FlagsTypeHandler(const FlagsList &m) : fList(m) {} 208 209string 210FlagsTypeHandler::GetParameterValue(Context &context, Parameter *, 211 const void *address) 212{ 213 return RenderValue(context, get_value<unsigned int>(address)); 214} 215 216string 217FlagsTypeHandler::GetReturnValue(Context &context, uint64 value) 218{ 219 return RenderValue(context, value); 220} 221 222string 223FlagsTypeHandler::RenderValue(Context &context, unsigned int value) const 224{ 225 if (context.GetContents(Context::ENUMERATIONS)) { 226 // Enumerate the list in reverse. That way, any later values which use 227 // the same bits as earlier values will be processed correctly. 228 string rendered; 229 FlagsList::const_reverse_iterator i = fList.rbegin(); 230 for (; i != fList.rend(); i++) { 231 if (value == 0) 232 break; 233 if ((value & i->value) != i->value) 234 continue; 235 236 if (!rendered.empty()) 237 rendered.insert(0, "|"); 238 rendered.insert(0, i->name); 239 value &= ~(i->value); 240 } 241 if (value != 0) { 242 if (!rendered.empty()) 243 rendered += "|"; 244 245 char hex[20]; 246 snprintf(hex, sizeof(hex), "0x%x", value); 247 rendered += hex; 248 } 249 if (rendered.empty()) 250 rendered = "0"; 251 return rendered; 252 } 253 254 return context.FormatUnsigned(value); 255} 256 257TypeHandlerSelector::TypeHandlerSelector(const SelectMap &m, int sibling, 258 TypeHandler *def) 259 : fMap(m), fSibling(sibling), fDefault(def) {} 260 261string 262TypeHandlerSelector::GetParameterValue(Context &context, Parameter *param, 263 const void *address) 264{ 265 TypeHandler *target = fDefault; 266 267 int index = get_value<int>(context.GetValue(context.GetSibling(fSibling))); 268 269 SelectMap::const_iterator i = fMap.find(index); 270 if (i != fMap.end()) 271 target = i->second; 272 273 return target->GetParameterValue(context, param, address); 274} 275 276string 277TypeHandlerSelector::GetReturnValue(Context &context, uint64 value) 278{ 279 return fDefault->GetReturnValue(context, value); 280} 281 282template<typename Type> 283static bool 284obtain_pointer_data(Context &context, Type *data, void *address, uint32 what) 285{ 286 if (address == NULL || !context.GetContents(what)) 287 return false; 288 289 int32 bytesRead; 290 291 status_t err = context.Reader().Read(address, data, sizeof(Type), bytesRead); 292 if (err != B_OK || bytesRead < (int32)sizeof(Type)) 293 return false; 294 295 return true; 296} 297 298template<typename Type> 299static string 300format_signed_integer_pointer(Context &context, void *address, uint32 count) 301{ 302 Type data; 303 304 if (obtain_pointer_data(context, &data, address, Context::POINTER_VALUES)) { 305 string formatted = "[" + context.FormatSigned(data); 306 for (uint32 i = 1; i < count; i++) { 307 address = (void*)((Type*)address + 1); 308 obtain_pointer_data(context, &data, address, Context::POINTER_VALUES); 309 formatted += ", " + context.FormatSigned(data); 310 } 311 formatted += "]"; 312 return formatted; 313 } 314 return context.FormatPointer(address); 315} 316 317template<typename Type> 318static string 319format_unsigned_integer_pointer(Context &context, void *address, uint32 count) 320{ 321 Type data; 322 323 if (obtain_pointer_data(context, &data, address, Context::POINTER_VALUES)) { 324 string formatted = "[" + context.FormatUnsigned(data); 325 for (uint32 i = 1; i < count; i++) { 326 address = (void*)((Type*)address + 1); 327 obtain_pointer_data(context, &data, address, Context::POINTER_VALUES); 328 formatted += ", " + context.FormatUnsigned(data); 329 } 330 formatted += "]"; 331 return formatted; 332 } 333 334 return context.FormatPointer(address); 335} 336 337template<typename Type> 338class SignedIntegerTypeHandler : public TypeHandler { 339public: 340 string GetParameterValue(Context &context, Parameter *, 341 const void *address) 342 { 343 return context.FormatSigned(get_value<Type>(address), sizeof(Type)); 344 } 345 346 string GetReturnValue(Context &context, uint64 value) 347 { 348 return context.FormatSigned(value, sizeof(Type)); 349 } 350}; 351 352template<typename Type> 353class UnsignedIntegerTypeHandler : public TypeHandler { 354public: 355 string GetParameterValue(Context &context, Parameter *, 356 const void *address) 357 { 358 return context.FormatUnsigned(get_value<Type>(address)); 359 } 360 361 string GetReturnValue(Context &context, uint64 value) 362 { 363 return context.FormatUnsigned(value); 364 } 365}; 366 367template<typename Type> 368class SignedIntegerPointerTypeHandler : public TypeHandler { 369 string GetParameterValue(Context &context, Parameter *parameter, 370 const void *address) 371 { 372 return format_signed_integer_pointer<Type>(context, *(void **)address, 373 parameter->Count()); 374 } 375 376 string GetReturnValue(Context &context, uint64 value) 377 { 378 return format_signed_integer_pointer<Type>(context, (void *)value, 1); 379 } 380}; 381 382template<typename Type> 383class UnsignedIntegerPointerTypeHandler : public TypeHandler { 384 string GetParameterValue(Context &context, Parameter *parameter, 385 const void *address) 386 { 387 return format_unsigned_integer_pointer<Type>(context, *(void **)address, 388 parameter->Count()); 389 } 390 391 string GetReturnValue(Context &context, uint64 value) 392 { 393 return format_unsigned_integer_pointer<Type>(context, (void *)value, 1); 394 } 395}; 396 397#define SIGNED_INTEGER_TYPE(type) \ 398 template<> \ 399 TypeHandler * \ 400 TypeHandlerFactory<type>::Create() \ 401 { \ 402 return new SignedIntegerTypeHandler<type>(); \ 403 } 404 405#define UNSIGNED_INTEGER_TYPE(type) \ 406 template<> \ 407 TypeHandler * \ 408 TypeHandlerFactory<type>::Create() \ 409 { \ 410 return new UnsignedIntegerTypeHandler<type>(); \ 411 } 412 413#define SIGNED_INTEGER_POINTER_TYPE(name, type) \ 414 TypeHandler *create_##name##_type_handler() \ 415 { \ 416 return new SignedIntegerPointerTypeHandler<type>(); \ 417 } 418 419#define UNSIGNED_INTEGER_POINTER_TYPE(name, type) \ 420 TypeHandler *create_##name##_type_handler() \ 421 { \ 422 return new UnsignedIntegerPointerTypeHandler<type>(); \ 423 } 424 425 426SIGNED_INTEGER_TYPE(char); 427SIGNED_INTEGER_TYPE(short); 428SIGNED_INTEGER_TYPE(int); 429SIGNED_INTEGER_TYPE(long); 430SIGNED_INTEGER_TYPE(long long); 431 432UNSIGNED_INTEGER_TYPE(unsigned char); 433UNSIGNED_INTEGER_TYPE(unsigned short); 434UNSIGNED_INTEGER_TYPE(unsigned int); 435UNSIGNED_INTEGER_TYPE(unsigned long); 436UNSIGNED_INTEGER_TYPE(unsigned long long); 437 438SIGNED_INTEGER_POINTER_TYPE(int_ptr, int); 439SIGNED_INTEGER_POINTER_TYPE(long_ptr, long); 440SIGNED_INTEGER_POINTER_TYPE(longlong_ptr, long long); 441 442UNSIGNED_INTEGER_POINTER_TYPE(uint_ptr, unsigned int); 443UNSIGNED_INTEGER_POINTER_TYPE(ulong_ptr, unsigned long); 444UNSIGNED_INTEGER_POINTER_TYPE(ulonglong_ptr, unsigned long long); 445 446