2
0

debug.cpp 4.5 KB

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