debug.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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 <bx/readerwriter.h> // WriterI
  8. #include <inttypes.h> // PRIx*
  9. #if BX_PLATFORM_ANDROID
  10. # include <android/log.h>
  11. #elif BX_PLATFORM_WINDOWS \
  12. || BX_PLATFORM_WINRT \
  13. || BX_PLATFORM_XBOXONE
  14. extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(const char* _str);
  15. #elif BX_PLATFORM_IOS || BX_PLATFORM_OSX
  16. # if defined(__OBJC__)
  17. # import <Foundation/NSObjCRuntime.h>
  18. # else
  19. # include <CoreFoundation/CFString.h>
  20. extern "C" void NSLog(CFStringRef _format, ...);
  21. # endif // defined(__OBJC__)
  22. #elif 0 // BX_PLATFORM_EMSCRIPTEN
  23. # include <emscripten.h>
  24. #else
  25. # include <stdio.h> // fputs, fflush
  26. #endif // BX_PLATFORM_WINDOWS
  27. namespace bx
  28. {
  29. void debugBreak()
  30. {
  31. #if BX_COMPILER_MSVC
  32. __debugbreak();
  33. #elif BX_CPU_ARM
  34. __builtin_trap();
  35. // asm("bkpt 0");
  36. #elif BX_CPU_X86 && (BX_COMPILER_GCC || BX_COMPILER_CLANG)
  37. // NaCl doesn't like int 3:
  38. // NativeClient: NaCl module load failed: Validation failure. File violates Native Client safety rules.
  39. __asm__ ("int $3");
  40. #else // cross platform implementation
  41. int* int3 = (int*)3L;
  42. *int3 = 3;
  43. #endif // BX
  44. }
  45. void debugOutput(const char* _out)
  46. {
  47. #if BX_PLATFORM_ANDROID
  48. # ifndef BX_ANDROID_LOG_TAG
  49. # define BX_ANDROID_LOG_TAG ""
  50. # endif // BX_ANDROID_LOG_TAG
  51. __android_log_write(ANDROID_LOG_DEBUG, BX_ANDROID_LOG_TAG, _out);
  52. #elif BX_PLATFORM_WINDOWS \
  53. || BX_PLATFORM_WINRT \
  54. || BX_PLATFORM_XBOXONE
  55. OutputDebugStringA(_out);
  56. #elif BX_PLATFORM_IOS || BX_PLATFORM_OSX
  57. # if defined(__OBJC__)
  58. NSLog(@"%s", _out);
  59. # else
  60. NSLog(__CFStringMakeConstantString("%s"), _out);
  61. # endif // defined(__OBJC__)
  62. #elif 0 // BX_PLATFORM_EMSCRIPTEN
  63. emscripten_log(EM_LOG_CONSOLE, "%s", _out);
  64. #elif !BX_CRT_NONE
  65. fputs(_out, stdout);
  66. fflush(stdout);
  67. #else
  68. BX_UNUSED(_out);
  69. #endif // BX_PLATFORM_
  70. }
  71. void debugPrintfVargs(const char* _format, va_list _argList)
  72. {
  73. char temp[8192];
  74. char* out = temp;
  75. int32_t len = vsnprintf(out, sizeof(temp), _format, _argList);
  76. if ( (int32_t)sizeof(temp) < len)
  77. {
  78. out = (char*)alloca(len+1);
  79. len = vsnprintf(out, len, _format, _argList);
  80. }
  81. out[len] = '\0';
  82. debugOutput(out);
  83. }
  84. void debugPrintf(const char* _format, ...)
  85. {
  86. va_list argList;
  87. va_start(argList, _format);
  88. debugPrintfVargs(_format, argList);
  89. va_end(argList);
  90. }
  91. #define DBG_ADDRESS "%" PRIxPTR
  92. void debugPrintfData(const void* _data, uint32_t _size, const char* _format, ...)
  93. {
  94. #define HEX_DUMP_WIDTH 16
  95. #define HEX_DUMP_SPACE_WIDTH 48
  96. #define HEX_DUMP_FORMAT "%-" BX_STRINGIZE(HEX_DUMP_SPACE_WIDTH) "." BX_STRINGIZE(HEX_DUMP_SPACE_WIDTH) "s"
  97. va_list argList;
  98. va_start(argList, _format);
  99. debugPrintfVargs(_format, argList);
  100. va_end(argList);
  101. debugPrintf("\ndata: " DBG_ADDRESS ", size: %d\n", _data, _size);
  102. if (NULL != _data)
  103. {
  104. const uint8_t* data = reinterpret_cast<const uint8_t*>(_data);
  105. char hex[HEX_DUMP_WIDTH*3+1];
  106. char ascii[HEX_DUMP_WIDTH+1];
  107. uint32_t hexPos = 0;
  108. uint32_t asciiPos = 0;
  109. for (uint32_t ii = 0; ii < _size; ++ii)
  110. {
  111. snprintf(&hex[hexPos], sizeof(hex)-hexPos, "%02x ", data[asciiPos]);
  112. hexPos += 3;
  113. ascii[asciiPos] = isPrint(data[asciiPos]) ? data[asciiPos] : '.';
  114. asciiPos++;
  115. if (HEX_DUMP_WIDTH == asciiPos)
  116. {
  117. ascii[asciiPos] = '\0';
  118. debugPrintf("\t" DBG_ADDRESS "\t" HEX_DUMP_FORMAT "\t%s\n", data, hex, ascii);
  119. data += asciiPos;
  120. hexPos = 0;
  121. asciiPos = 0;
  122. }
  123. }
  124. if (0 != asciiPos)
  125. {
  126. ascii[asciiPos] = '\0';
  127. debugPrintf("\t" DBG_ADDRESS "\t" HEX_DUMP_FORMAT "\t%s\n", data, hex, ascii);
  128. }
  129. }
  130. #undef HEX_DUMP_WIDTH
  131. #undef HEX_DUMP_SPACE_WIDTH
  132. #undef HEX_DUMP_FORMAT
  133. }
  134. class DebugWriter : public WriterI
  135. {
  136. virtual int32_t write(const void* _data, int32_t _size, Error* _err) BX_OVERRIDE
  137. {
  138. BX_UNUSED(_err);
  139. int32_t total = 0;
  140. char temp[4096];
  141. while (total != _size)
  142. {
  143. uint32_t len = bx::uint32_min(sizeof(temp)-1, _size-total);
  144. memCopy(temp, _data, len);
  145. temp[len] = '\0';
  146. debugOutput(temp);
  147. total += len;
  148. }
  149. return total;
  150. }
  151. };
  152. WriterI* getDebugOut()
  153. {
  154. static DebugWriter s_debugOut;
  155. return &s_debugOut;
  156. }
  157. } // namespace bx