Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

271 lines
8.1KB

  1. //------------------------------------------------------------------------
  2. // Project : SDK Base
  3. // Version : 1.0
  4. //
  5. // Category : Helpers
  6. // Filename : base/source/fdebug.cpp
  7. // Created by : Steinberg, 1995
  8. // Description : There are 2 levels of debugging messages:
  9. // DEVELOPMENT During development
  10. // RELEASE Program is shipping.
  11. //
  12. //-----------------------------------------------------------------------------
  13. // LICENSE
  14. // (c) 2017, Steinberg Media Technologies GmbH, All Rights Reserved
  15. //-----------------------------------------------------------------------------
  16. // Redistribution and use in source and binary forms, with or without modification,
  17. // are permitted provided that the following conditions are met:
  18. //
  19. // * Redistributions of source code must retain the above copyright notice,
  20. // this list of conditions and the following disclaimer.
  21. // * Redistributions in binary form must reproduce the above copyright notice,
  22. // this list of conditions and the following disclaimer in the documentation
  23. // and/or other materials provided with the distribution.
  24. // * Neither the name of the Steinberg Media Technologies nor the names of its
  25. // contributors may be used to endorse or promote products derived from this
  26. // software without specific prior written permission.
  27. //
  28. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  29. // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  30. // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  31. // IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  32. // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  33. // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  34. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  35. // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  36. // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  37. // OF THE POSSIBILITY OF SUCH DAMAGE.
  38. //-----------------------------------------------------------------------------
  39. #include "base/source/fdebug.h"
  40. #if DEVELOPMENT
  41. #include <cstdio>
  42. #include <cstdarg>
  43. #if WINDOWS
  44. #ifndef _WIN32_WINNT
  45. #define _WIN32_WINNT 0x0400
  46. #endif
  47. #include <windows.h>
  48. #include <intrin.h>
  49. #define vsnprintf _vsnprintf
  50. #elif MAC
  51. #include <mach/mach_time.h>
  52. #include <mach/mach_init.h>
  53. #include <errno.h>
  54. #include <new>
  55. #include <stdbool.h>
  56. #include <sys/types.h>
  57. #include <unistd.h>
  58. #include <sys/sysctl.h>
  59. #include <signal.h>
  60. static bool AmIBeingDebugged (void);
  61. #define THREAD_ALLOC_WATCH 0 // check allocations on specific threads
  62. #if THREAD_ALLOC_WATCH
  63. mach_port_t watchThreadID = 0;
  64. #endif
  65. #endif
  66. AssertionHandler gAssertionHandler = 0;
  67. //--------------------------------------------------------------------------
  68. static const int kDebugPrintfBufferSize = 10000;
  69. static bool neverDebugger = false; // so I can switch it off in the debugger...
  70. //--------------------------------------------------------------------------
  71. static void printDebugString (const char* string)
  72. {
  73. if (!string)
  74. return;
  75. #if MAC
  76. fprintf (stderr, "%s", string);
  77. #elif WINDOWS
  78. OutputDebugStringA (string);
  79. #endif
  80. }
  81. //--------------------------------------------------------------------------
  82. // printf style debugging output
  83. //--------------------------------------------------------------------------
  84. void FDebugPrint (const char *format, ...)
  85. {
  86. char string[kDebugPrintfBufferSize];
  87. va_list marker;
  88. va_start (marker, format);
  89. vsnprintf (string, kDebugPrintfBufferSize, format, marker);
  90. printDebugString (string);
  91. }
  92. #if WINDOWS
  93. #define AmIBeingDebugged IsDebuggerPresent
  94. #endif
  95. #if LINUX
  96. #include <sys/types.h>
  97. #include <unistd.h>
  98. #include <signal.h>
  99. //--------------------------------------------------------------------------
  100. static inline bool AmIBeingDebugged ()
  101. {
  102. // TODO: check if GDB or LLDB is attached
  103. return true;
  104. }
  105. #endif
  106. //--------------------------------------------------------------------------
  107. // printf style debugging output
  108. //--------------------------------------------------------------------------
  109. void FDebugBreak (const char *format, ...)
  110. {
  111. char string[kDebugPrintfBufferSize];
  112. va_list marker;
  113. va_start (marker, format);
  114. vsnprintf (string, kDebugPrintfBufferSize, format, marker);
  115. printDebugString (string);
  116. if (neverDebugger)
  117. return;
  118. if (AmIBeingDebugged ())
  119. {
  120. // do not crash if no debugger present
  121. // If there is an assertion handler defined then let this override the UI
  122. // and tell us whether we want to break into the debugger
  123. bool breakIntoDebugger = true;
  124. if (gAssertionHandler && gAssertionHandler (string) == false)
  125. {
  126. breakIntoDebugger = false;
  127. }
  128. if (breakIntoDebugger)
  129. {
  130. #if WINDOWS
  131. __debugbreak (); // intrinsic version of DebugBreak()
  132. #elif __ppc64__ || __ppc__ || __arm__
  133. kill (getpid (), SIGINT);
  134. #elif __i386__ || __x86_64__
  135. { __asm__ volatile ("int3"); }
  136. #endif
  137. }
  138. }
  139. }
  140. //--------------------------------------------------------------------------
  141. void FPrintLastError (const char* file, int line)
  142. {
  143. #if WINDOWS
  144. LPVOID lpMessageBuffer;
  145. FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  146. NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  147. (LPSTR) &lpMessageBuffer, 0, NULL);
  148. FDebugPrint ("%s(%d) : %s\n", file, line, lpMessageBuffer);
  149. LocalFree (lpMessageBuffer);
  150. #endif
  151. #if MAC
  152. #if !__MACH__
  153. extern int errno;
  154. #endif
  155. FDebugPrint ("%s(%d) : Errno %d\n", file, line, errno);
  156. #endif
  157. }
  158. #if MAC
  159. //------------------------------------------------------------------------
  160. void* operator new (size_t size, int, const char *file, int line)
  161. {
  162. #if THREAD_ALLOC_WATCH
  163. mach_port_t threadID = mach_thread_self ();
  164. if (watchThreadID == threadID)
  165. {
  166. FDebugPrint ("Watched Thread Allocation : %s (Line:%d)\n", file ? file : "Unknown", line);
  167. }
  168. #endif
  169. try {
  170. return ::operator new (size);
  171. } catch (std::bad_alloc exception) { FDebugPrint ("bad_alloc exception : %s (Line:%d)", file ? file : "Unknown", line); }
  172. return (void*)-1;
  173. }
  174. //------------------------------------------------------------------------
  175. void* operator new [](size_t size, int, const char *file, int line)
  176. {
  177. #if THREAD_ALLOC_WATCH
  178. mach_port_t threadID = mach_thread_self ();
  179. if (watchThreadID == threadID)
  180. {
  181. FDebugPrint ("Watched Thread Allocation : %s (Line:%d)\n", file ? file : "Unknown", line);
  182. }
  183. #endif
  184. try {
  185. return ::operator new [](size);
  186. } catch (std::bad_alloc exception) { FDebugPrint ("bad_alloc exception : %s (Line:%d)", file ? file : "Unknown", line);}
  187. return (void*)-1;
  188. }
  189. //------------------------------------------------------------------------
  190. void operator delete(void* p, int, const char *file, int line)
  191. {
  192. ::operator delete (p);
  193. }
  194. //------------------------------------------------------------------------
  195. void operator delete[](void* p, int, const char *file, int line)
  196. {
  197. ::operator delete[] (p);
  198. }
  199. //------------------------------------------------------------------------
  200. // from Technical Q&A QA1361 (http://developer.apple.com/qa/qa2004/qa1361.html)
  201. //------------------------------------------------------------------------
  202. bool AmIBeingDebugged(void)
  203. // Returns true if the current process is being debugged (either
  204. // running under the debugger or has a debugger attached post facto).
  205. {
  206. int mib[4];
  207. struct kinfo_proc info;
  208. size_t size;
  209. // Initialize the flags so that, if sysctl fails for some bizarre
  210. // reason, we get a predictable result.
  211. info.kp_proc.p_flag = 0;
  212. // Initialize mib, which tells sysctl the info we want, in this case
  213. // we're looking for information about a specific process ID.
  214. mib[0] = CTL_KERN;
  215. mib[1] = KERN_PROC;
  216. mib[2] = KERN_PROC_PID;
  217. mib[3] = getpid();
  218. // Call sysctl.
  219. size = sizeof(info);
  220. sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
  221. // We're being debugged if the P_TRACED flag is set.
  222. return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
  223. }
  224. #endif // MAC
  225. #endif // DEVELOPMENT