LMMS
Loading...
Searching...
No Matches
fdebug.cpp
Go to the documentation of this file.
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) 2021, 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
40#include "base/source/fdebug.h"
41
42#if SMTG_OS_WINDOWS
43#include <windows.h>
44
45bool AmIBeingDebugged ()
46{
47 return IsDebuggerPresent ();
48}
49#endif
50
51#if SMTG_OS_LINUX
52#include <signal.h>
53#include <sys/types.h>
54#include <unistd.h>
55//--------------------------------------------------------------------------
56bool AmIBeingDebugged ()
57{
58 // TODO: check if GDB or LLDB is attached
59 return true;
60}
61#endif
62
63#if SMTG_OS_MACOS
64
65#include <stdbool.h>
66#include <sys/sysctl.h>
67#include <sys/types.h>
68#include <unistd.h>
69
70//------------------------------------------------------------------------
71// from Technical Q&A QA1361 (http://developer.apple.com/qa/qa2004/qa1361.html)
72//------------------------------------------------------------------------
73bool AmIBeingDebugged ()
74// Returns true if the current process is being debugged (either
75// running under the debugger or has a debugger attached post facto).
76{
77 int mib[4];
78 struct kinfo_proc info;
79 size_t size;
80
81 // Initialize the flags so that, if sysctl fails for some bizarre
82 // reason, we get a predictable result.
83
84 info.kp_proc.p_flag = 0;
85
86 // Initialize mib, which tells sysctl the info we want, in this case
87 // we're looking for information about a specific process ID.
88
89 mib[0] = CTL_KERN;
90 mib[1] = KERN_PROC;
91 mib[2] = KERN_PROC_PID;
92 mib[3] = getpid ();
93
94 // Call sysctl.
95
96 size = sizeof (info);
97 sysctl (mib, sizeof (mib) / sizeof (*mib), &info, &size, NULL, 0);
98
99 // We're being debugged if the P_TRACED flag is set.
100 return ((info.kp_proc.p_flag & P_TRACED) != 0);
101}
102
103#endif // SMTG_OS_MACOS
104
105#if DEVELOPMENT
106
107#include <cassert>
108#include <cstdarg>
109#include <cstdio>
110
111#if SMTG_OS_WINDOWS
112#ifndef _WIN32_WINNT
113#define _WIN32_WINNT 0x0400
114#endif
115#if _MSC_VER
116#include <intrin.h>
117#endif
118#define vsnprintf _vsnprintf
119#define snprintf _snprintf
120
121#elif SMTG_OS_MACOS
122#include <errno.h>
123#include <mach/mach_init.h>
124#include <mach/mach_time.h>
125#include <new>
126#include <signal.h>
127
128#define THREAD_ALLOC_WATCH 0 // check allocations on specific threads
129
130#if THREAD_ALLOC_WATCH
131mach_port_t watchThreadID = 0;
132#endif
133
134#endif
135
136AssertionHandler gAssertionHandler = nullptr;
137AssertionHandler gPreAssertionHook = nullptr;
138DebugPrintLogger gDebugPrintLogger = nullptr;
139
140//--------------------------------------------------------------------------
141static const int kDebugPrintfBufferSize = 10000;
142static bool neverDebugger = false; // so I can switch it off in the debugger...
143
144//--------------------------------------------------------------------------
145static void printDebugString (const char* string)
146{
147 if (!string)
148 return;
149
150 if (gDebugPrintLogger)
151 {
152 gDebugPrintLogger (string);
153 }
154 else
155 {
156#if SMTG_OS_MACOS || defined(__MINGW32__)
157 fprintf (stderr, "%s", string);
158#elif SMTG_OS_WINDOWS
159 OutputDebugStringA (string);
160#endif
161 }
162}
163
164//--------------------------------------------------------------------------
165// printf style debugging output
166//--------------------------------------------------------------------------
167void FDebugPrint (const char* format, ...)
168{
169 char string[kDebugPrintfBufferSize];
170 va_list marker;
171 va_start (marker, format);
172 vsnprintf (string, kDebugPrintfBufferSize, format, marker);
173
174 printDebugString (string);
175}
176
177//--------------------------------------------------------------------------
178// printf style debugging output
179//--------------------------------------------------------------------------
180void FDebugBreak (const char* format, ...)
181{
182 char string[kDebugPrintfBufferSize];
183 va_list marker;
184 va_start (marker, format);
185 vsnprintf (string, kDebugPrintfBufferSize, format, marker);
186
187 printDebugString (string);
188
189 // The Pre-assertion hook is always called, even if we're not running in the debugger,
190 // so that we can log asserts without displaying them
191 if (gPreAssertionHook)
192 {
193 gPreAssertionHook (string);
194 }
195
196 if (neverDebugger)
197 return;
198 if (AmIBeingDebugged ())
199 {
200 // do not crash if no debugger present
201 // If there is an assertion handler defined then let this override the UI
202 // and tell us whether we want to break into the debugger
203 bool breakIntoDebugger = true;
204 if (gAssertionHandler && gAssertionHandler (string) == false)
205 {
206 breakIntoDebugger = false;
207 }
208
209 if (breakIntoDebugger)
210 {
211#if SMTG_OS_WINDOWS && _MSC_VER
212 __debugbreak (); // intrinsic version of DebugBreak()
213#elif SMTG_OS_MACOS && __arm64__
214 raise (SIGSTOP);
215
216#elif __ppc64__ || __ppc__ || __arm__
217 kill (getpid (), SIGINT);
218#elif __i386__ || __x86_64__
219 {
220 __asm__ volatile ("int3");
221 }
222#endif
223 }
224 }
225}
226
227//--------------------------------------------------------------------------
228void FPrintLastError (const char* file, int line)
229{
230#if SMTG_OS_WINDOWS
231 LPVOID lpMessageBuffer;
232 FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, nullptr,
233 GetLastError (), MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
234 (LPSTR)&lpMessageBuffer, 0, nullptr);
235 FDebugPrint ("%s(%d) : %s\n", file, line, lpMessageBuffer);
236 LocalFree (lpMessageBuffer);
237#endif
238
239#if SMTG_OS_MACOS
240#if !__MACH__
241 extern int errno;
242#endif
243 FDebugPrint ("%s(%d) : Errno %d\n", file, line, errno);
244#endif
245}
246
247#if SMTG_OS_MACOS
248
249//------------------------------------------------------------------------
250void* operator new (size_t size, int, const char* file, int line)
251{
252#if THREAD_ALLOC_WATCH
253 mach_port_t threadID = mach_thread_self ();
254 if (watchThreadID == threadID)
255 {
256 FDebugPrint ("Watched Thread Allocation : %s (Line:%d)\n", file ? file : "Unknown", line);
257 }
258#endif
259 try
260 {
261 return ::operator new (size);
262 }
263 catch (std::bad_alloc exception)
264 {
265 FDebugPrint ("bad_alloc exception : %s (Line:%d)", file ? file : "Unknown", line);
266 }
267 return (void*)-1;
268}
269
270//------------------------------------------------------------------------
271void* operator new[] (size_t size, int, const char* file, int line)
272{
273#if THREAD_ALLOC_WATCH
274 mach_port_t threadID = mach_thread_self ();
275 if (watchThreadID == threadID)
276 {
277 FDebugPrint ("Watched Thread Allocation : %s (Line:%d)\n", file ? file : "Unknown", line);
278 }
279#endif
280 try
281 {
282 return ::operator new[] (size);
283 }
284 catch (std::bad_alloc exception)
285 {
286 FDebugPrint ("bad_alloc exception : %s (Line:%d)", file ? file : "Unknown", line);
287 }
288 return (void*)-1;
289}
290
291//------------------------------------------------------------------------
292void operator delete (void* p, int, const char* file, int line)
293{
294 ::operator delete (p);
295}
296
297//------------------------------------------------------------------------
298void operator delete[] (void* p, int, const char* file, int line)
299{
300 ::operator delete[] (p);
301}
302
303#endif // SMTG_OS_MACOS
304
305#endif // DEVELOPMENT
306
307static bool smtg_unit_testing_active = false; // ugly hack to unit testing ...
308
309//------------------------------------------------------------------------
311{
313}
314
315//------------------------------------------------------------------------
317{
319}
#define NULL
Definition CarlaBridgeFormat.cpp:30
void setSmtgUnitTesting()
Definition fdebug.cpp:316
bool isSmtgUnitTesting()
Definition fdebug.cpp:310
static bool smtg_unit_testing_active
Definition fdebug.cpp:307
bool AmIBeingDebugged()
struct backing_store_struct * info
Definition jmemsys.h:183
int marker
Definition jpeglib.h:950
char * LPSTR
Definition swell-types.h:189
void * LPVOID
Definition swell-types.h:174
uch * p
Definition crypt.c:594
ulg size
Definition extract.c:2350
typedef int(UZ_EXP MsgFn)()
struct zdirent * file
Definition win32.c:1500
_WDL_CSTRING_PREFIX void INT_PTR const char * format
Definition wdlcstring.h:263