debug.cpp 4.9 KB

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