debug.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /*
  2. * Copyright 2010-2017 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause
  4. */
  5. #include <bx/debug.h>
  6. #include <bx/string.h> // isPrint
  7. #include <inttypes.h> // PRIx*
  8. #if BX_PLATFORM_ANDROID
  9. # include <android/log.h>
  10. #elif BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE
  11. extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(const char* _str);
  12. #elif BX_PLATFORM_IOS || BX_PLATFORM_OSX
  13. # if defined(__OBJC__)
  14. # import <Foundation/NSObjCRuntime.h>
  15. # else
  16. # include <CoreFoundation/CFString.h>
  17. extern "C" void NSLog(CFStringRef _format, ...);
  18. # endif // defined(__OBJC__)
  19. #elif 0 // BX_PLATFORM_EMSCRIPTEN
  20. # include <emscripten.h>
  21. #else
  22. # include <stdio.h> // fputs, fflush
  23. #endif // BX_PLATFORM_WINDOWS
  24. namespace bx
  25. {
  26. void debugBreak()
  27. {
  28. #if BX_COMPILER_MSVC
  29. __debugbreak();
  30. #elif BX_CPU_ARM
  31. __builtin_trap();
  32. // asm("bkpt 0");
  33. #elif !BX_PLATFORM_NACL && BX_CPU_X86 && (BX_COMPILER_GCC || BX_COMPILER_CLANG)
  34. // NaCl doesn't like int 3:
  35. // NativeClient: NaCl module load failed: Validation failure. File violates Native Client safety rules.
  36. __asm__ ("int $3");
  37. #else // cross platform implementation
  38. int* int3 = (int*)3L;
  39. *int3 = 3;
  40. #endif // BX
  41. }
  42. void debugOutput(const char* _out)
  43. {
  44. #if BX_PLATFORM_ANDROID
  45. # ifndef BX_ANDROID_LOG_TAG
  46. # define BX_ANDROID_LOG_TAG ""
  47. # endif // BX_ANDROID_LOG_TAG
  48. __android_log_write(ANDROID_LOG_DEBUG, BX_ANDROID_LOG_TAG, _out);
  49. #elif BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE
  50. OutputDebugStringA(_out);
  51. #elif BX_PLATFORM_IOS || BX_PLATFORM_OSX
  52. # if defined(__OBJC__)
  53. NSLog(@"%s", _out);
  54. # else
  55. NSLog(__CFStringMakeConstantString("%s"), _out);
  56. # endif // defined(__OBJC__)
  57. #elif 0 // BX_PLATFORM_EMSCRIPTEN
  58. emscripten_log(EM_LOG_CONSOLE, "%s", _out);
  59. #else
  60. fputs(_out, stdout);
  61. fflush(stdout);
  62. #endif // BX_PLATFORM_
  63. }
  64. void debugPrintfVargs(const char* _format, va_list _argList)
  65. {
  66. char temp[8192];
  67. char* out = temp;
  68. int32_t len = vsnprintf(out, sizeof(temp), _format, _argList);
  69. if ( (int32_t)sizeof(temp) < len)
  70. {
  71. out = (char*)alloca(len+1);
  72. len = vsnprintf(out, len, _format, _argList);
  73. }
  74. out[len] = '\0';
  75. debugOutput(out);
  76. }
  77. void debugPrintf(const char* _format, ...)
  78. {
  79. va_list argList;
  80. va_start(argList, _format);
  81. debugPrintfVargs(_format, argList);
  82. va_end(argList);
  83. }
  84. #define DBG_ADDRESS "%" PRIxPTR
  85. void debugPrintfData(const void* _data, uint32_t _size, const char* _format, ...)
  86. {
  87. #define HEX_DUMP_WIDTH 16
  88. #define HEX_DUMP_SPACE_WIDTH 48
  89. #define HEX_DUMP_FORMAT "%-" BX_STRINGIZE(HEX_DUMP_SPACE_WIDTH) "." BX_STRINGIZE(HEX_DUMP_SPACE_WIDTH) "s"
  90. va_list argList;
  91. va_start(argList, _format);
  92. debugPrintfVargs(_format, argList);
  93. va_end(argList);
  94. debugPrintf("\ndata: " DBG_ADDRESS ", size: %d\n", _data, _size);
  95. if (NULL != _data)
  96. {
  97. const uint8_t* data = reinterpret_cast<const uint8_t*>(_data);
  98. char hex[HEX_DUMP_WIDTH*3+1];
  99. char ascii[HEX_DUMP_WIDTH+1];
  100. uint32_t hexPos = 0;
  101. uint32_t asciiPos = 0;
  102. for (uint32_t ii = 0; ii < _size; ++ii)
  103. {
  104. snprintf(&hex[hexPos], sizeof(hex)-hexPos, "%02x ", data[asciiPos]);
  105. hexPos += 3;
  106. ascii[asciiPos] = isPrint(data[asciiPos]) ? data[asciiPos] : '.';
  107. asciiPos++;
  108. if (HEX_DUMP_WIDTH == asciiPos)
  109. {
  110. ascii[asciiPos] = '\0';
  111. debugPrintf("\t" DBG_ADDRESS "\t" HEX_DUMP_FORMAT "\t%s\n", data, hex, ascii);
  112. data += asciiPos;
  113. hexPos = 0;
  114. asciiPos = 0;
  115. }
  116. }
  117. if (0 != asciiPos)
  118. {
  119. ascii[asciiPos] = '\0';
  120. debugPrintf("\t" DBG_ADDRESS "\t" HEX_DUMP_FORMAT "\t%s\n", data, hex, ascii);
  121. }
  122. }
  123. #undef HEX_DUMP_WIDTH
  124. #undef HEX_DUMP_SPACE_WIDTH
  125. #undef HEX_DUMP_FORMAT
  126. }
  127. } // namespace bx