debug.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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_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. #elif !BX_CRT_NONE
  60. fputs(_out, stdout);
  61. fflush(stdout);
  62. #else
  63. BX_UNUSED(_out);
  64. #endif // BX_PLATFORM_
  65. }
  66. void debugPrintfVargs(const char* _format, va_list _argList)
  67. {
  68. char temp[8192];
  69. char* out = temp;
  70. int32_t len = vsnprintf(out, sizeof(temp), _format, _argList);
  71. if ( (int32_t)sizeof(temp) < len)
  72. {
  73. out = (char*)alloca(len+1);
  74. len = vsnprintf(out, len, _format, _argList);
  75. }
  76. out[len] = '\0';
  77. debugOutput(out);
  78. }
  79. void debugPrintf(const char* _format, ...)
  80. {
  81. va_list argList;
  82. va_start(argList, _format);
  83. debugPrintfVargs(_format, argList);
  84. va_end(argList);
  85. }
  86. #define DBG_ADDRESS "%" PRIxPTR
  87. void debugPrintfData(const void* _data, uint32_t _size, const char* _format, ...)
  88. {
  89. #define HEX_DUMP_WIDTH 16
  90. #define HEX_DUMP_SPACE_WIDTH 48
  91. #define HEX_DUMP_FORMAT "%-" BX_STRINGIZE(HEX_DUMP_SPACE_WIDTH) "." BX_STRINGIZE(HEX_DUMP_SPACE_WIDTH) "s"
  92. va_list argList;
  93. va_start(argList, _format);
  94. debugPrintfVargs(_format, argList);
  95. va_end(argList);
  96. debugPrintf("\ndata: " DBG_ADDRESS ", size: %d\n", _data, _size);
  97. if (NULL != _data)
  98. {
  99. const uint8_t* data = reinterpret_cast<const uint8_t*>(_data);
  100. char hex[HEX_DUMP_WIDTH*3+1];
  101. char ascii[HEX_DUMP_WIDTH+1];
  102. uint32_t hexPos = 0;
  103. uint32_t asciiPos = 0;
  104. for (uint32_t ii = 0; ii < _size; ++ii)
  105. {
  106. snprintf(&hex[hexPos], sizeof(hex)-hexPos, "%02x ", data[asciiPos]);
  107. hexPos += 3;
  108. ascii[asciiPos] = isPrint(data[asciiPos]) ? data[asciiPos] : '.';
  109. asciiPos++;
  110. if (HEX_DUMP_WIDTH == asciiPos)
  111. {
  112. ascii[asciiPos] = '\0';
  113. debugPrintf("\t" DBG_ADDRESS "\t" HEX_DUMP_FORMAT "\t%s\n", data, hex, ascii);
  114. data += asciiPos;
  115. hexPos = 0;
  116. asciiPos = 0;
  117. }
  118. }
  119. if (0 != asciiPos)
  120. {
  121. ascii[asciiPos] = '\0';
  122. debugPrintf("\t" DBG_ADDRESS "\t" HEX_DUMP_FORMAT "\t%s\n", data, hex, ascii);
  123. }
  124. }
  125. #undef HEX_DUMP_WIDTH
  126. #undef HEX_DUMP_SPACE_WIDTH
  127. #undef HEX_DUMP_FORMAT
  128. }
  129. } // namespace bx