2 * AcessOS Microkernel Version
7 #include <debug_hooks.h>
9 #define DEBUG_MAX_LINE_LEN 256
10 #define LOCK_DEBUG_OUTPUT 0 // Avoid interleaving of output lines?
11 #define TRACE_TO_KTERM 0 // Send ENTER/DEBUG/LEAVE to debug?
14 extern void KernelPanic_SetMode(void);
15 extern void KernelPanic_PutChar(char Ch);
16 extern void IPStack_SendDebugText(const char *Text);
17 extern void VT_SetTerminal(int TerminalID);
20 static void Debug_Putchar(char ch);
21 static void Debug_Puts(int bUseKTerm, const char *Str);
22 void Debug_DbgOnlyFmt(const char *format, va_list args);
23 void Debug_FmtS(int bUseKTerm, const char *format, ...);
24 bool Debug_Fmt(int bUseKTerm, const char *format, va_list args);
25 void Debug_SetKTerminal(const char *File);
29 int giDebug_KTerm = -1;
30 int gbDebug_IsKPanic = 0;
31 volatile int gbInPutChar = 0;
33 tShortSpinlock glDebug_Lock;
35 // - Disabled because it breaks shit
36 int gbSendNetworkDebug = 0;
39 static void Debug_Putchar(char ch)
41 Debug_PutCharDebug(ch);
43 if( gbDebug_IsKPanic )
44 KernelPanic_PutChar(ch);
46 if( gbDebug_IsKPanic < 2 )
48 if(gbInPutChar) return ;
50 if(giDebug_KTerm != -1)
51 VFS_Write(giDebug_KTerm, 1, &ch);
55 if( gbSendNetworkDebug )
57 char str[2] = {ch, 0};
58 IPStack_SendDebugText(str);
62 static void Debug_Puts(int UseKTerm, const char *Str)
66 Debug_PutStringDebug(Str);
68 if( gbDebug_IsKPanic )
70 for( len = 0; Str[len]; len ++ )
71 KernelPanic_PutChar( Str[len] );
74 for( len = 0; Str[len]; len ++ );
76 if( gbSendNetworkDebug )
77 IPStack_SendDebugText(Str);
79 // Output to the kernel terminal
80 if( UseKTerm && gbDebug_IsKPanic < 2 && giDebug_KTerm != -1 && gbInPutChar == 0)
83 VFS_Write(giDebug_KTerm, len, Str);
88 void Debug_DbgOnlyFmt(const char *format, va_list args)
90 Debug_Fmt(0, format, args);
93 bool Debug_Fmt(int bUseKTerm, const char *format, va_list args)
95 char buf[DEBUG_MAX_LINE_LEN];
96 buf[DEBUG_MAX_LINE_LEN-1] = 0;
97 size_t len = vsnprintf(buf, DEBUG_MAX_LINE_LEN-1, format, args);
98 Debug_Puts(bUseKTerm, buf);
99 if( len > DEBUG_MAX_LINE_LEN-1 ) {
101 Debug_Puts(bUseKTerm, "[...]");
107 void Debug_FmtS(int bUseKTerm, const char *format, ...)
110 va_start(args, format);
111 Debug_Fmt(bUseKTerm, format, args);
115 void Debug_KernelPanic(void)
117 // 5 nested panics? Fuck it
118 if( gbDebug_IsKPanic > 5 )
121 if( gbDebug_IsKPanic == 1 )
123 #if LOCK_DEBUG_OUTPUT
124 SHORTREL(&glDebug_Lock);
128 KernelPanic_SetMode();
132 * \fn void LogF(const char *Msg, ...)
133 * \brief Raw debug log (no new line, no prefix)
134 * \return True if all of the provided text was printed
136 bool LogF(const char *Fmt, ...)
138 #if LOCK_DEBUG_OUTPUT
139 if(CPU_HAS_LOCK(&glDebug_Lock)) {
143 SHORTLOCK(&glDebug_Lock);
148 bool rv = Debug_Fmt(1, Fmt, args);
151 #if LOCK_DEBUG_OUTPUT
152 SHORTREL(&glDebug_Lock);
157 * \fn void Debug(const char *Msg, ...)
158 * \brief Print only to the debug channel (not KTerm)
160 void Debug(const char *Fmt, ...)
164 #if LOCK_DEBUG_OUTPUT
165 if(CPU_HAS_LOCK(&glDebug_Lock)) return ;
166 SHORTLOCK(&glDebug_Lock);
169 Debug_Puts(0, "Debug: ");
171 Debug_DbgOnlyFmt(Fmt, args);
173 Debug_PutCharDebug('\r');
174 Debug_PutCharDebug('\n');
175 #if LOCK_DEBUG_OUTPUT
176 SHORTREL(&glDebug_Lock);
181 void LogFV(const char *Fmt, va_list args)
183 #if LOCK_DEBUG_OUTPUT
184 if(CPU_HAS_LOCK(&glDebug_Lock)) return ;
185 SHORTLOCK(&glDebug_Lock);
188 Debug_Fmt(1, Fmt, args);
190 #if LOCK_DEBUG_OUTPUT
191 SHORTREL(&glDebug_Lock);
195 void LogV(const char *Fmt, va_list args)
197 #if LOCK_DEBUG_OUTPUT
198 if(CPU_HAS_LOCK(&glDebug_Lock)) return ;
199 SHORTLOCK(&glDebug_Lock);
202 Debug_Puts(1, "Log: ");
203 Debug_Fmt(1, Fmt, args);
204 Debug_Puts(1, "\r\n");
206 #if LOCK_DEBUG_OUTPUT
207 SHORTREL(&glDebug_Lock);
212 * \fn void Log(const char *Msg, ...)
214 void Log(const char *Fmt, ...)
222 void Warning(const char *Fmt, ...)
226 #if LOCK_DEBUG_OUTPUT
227 if(CPU_HAS_LOCK(&glDebug_Lock)) return ;
228 SHORTLOCK(&glDebug_Lock);
231 Debug_Puts(1, "Warning: ");
233 Debug_Fmt(1, Fmt, args);
238 #if LOCK_DEBUG_OUTPUT
239 SHORTREL(&glDebug_Lock);
242 void Panic(const char *Fmt, ...)
246 #if LOCK_DEBUG_OUTPUT
247 if( !CPU_HAS_LOCK(&glDebug_Lock) )
248 SHORTLOCK(&glDebug_Lock);
250 // And never SHORTREL
254 Debug_Puts(1, "\x1b[31m");
255 Debug_Puts(1, "Panic: ");
257 Debug_Fmt(1, Fmt, args);
259 Debug_Puts(1, "\x1b[0m\r\n");
261 Proc_PrintBacktrace();
268 void Debug_SetKTerminal(const char *File)
270 if(giDebug_KTerm != -1) {
271 // Clear FD to -1 before closing (prevents writes to closed FD)
272 int oldfd = giDebug_KTerm;
276 giDebug_KTerm = VFS_Open(File, VFS_OPENFLAG_WRITE);
279 void Debug_Enter(const char *FuncName, const char *ArgTypes, ...)
284 tTID tid = Threads_GetTID();
286 #if LOCK_DEBUG_OUTPUT
287 if(CPU_HAS_LOCK(&glDebug_Lock)) return ;
288 SHORTLOCK(&glDebug_Lock);
293 va_start(args, ArgTypes);
295 Debug_FmtS(TRACE_TO_KTERM, "%014lli ", now());
296 while(i--) Debug_Puts(TRACE_TO_KTERM, " ");
298 Debug_Puts(TRACE_TO_KTERM, FuncName);
299 Debug_FmtS(TRACE_TO_KTERM, "[%i]", tid);
300 Debug_Puts(TRACE_TO_KTERM, ": (");
304 pos = strpos(ArgTypes, ' ');
305 if(pos == -1 || pos > 1) {
307 Debug_Puts(TRACE_TO_KTERM, ArgTypes+1);
309 Debug_FmtS(TRACE_TO_KTERM, "%.*s", pos-1, ArgTypes+1);
311 Debug_Puts(TRACE_TO_KTERM, "=");
315 case 'p': Debug_FmtS(TRACE_TO_KTERM, "%p", va_arg(args, void*)); break;
316 case 'P': Debug_FmtS(TRACE_TO_KTERM, "%P", va_arg(args, tPAddr)); break;
317 case 's': Debug_FmtS(TRACE_TO_KTERM, "'%s'", va_arg(args, char*)); break;
318 case 'i': Debug_FmtS(TRACE_TO_KTERM, "%i", va_arg(args, int)); break;
319 case 'u': Debug_FmtS(TRACE_TO_KTERM, "%u", va_arg(args, Uint)); break;
320 case 'x': Debug_FmtS(TRACE_TO_KTERM, "0x%x", va_arg(args, Uint)); break;
321 case 'b': Debug_FmtS(TRACE_TO_KTERM, "0b%b", va_arg(args, Uint)); break;
322 case 'X': Debug_FmtS(TRACE_TO_KTERM, "0x%llx", va_arg(args, Uint64)); break; // Extended (64-Bit)
323 case 'B': Debug_FmtS(TRACE_TO_KTERM, "0b%llb", va_arg(args, Uint64)); break; // Extended (64-Bit)
326 Debug_Puts(TRACE_TO_KTERM, ", ");
330 ArgTypes = &ArgTypes[pos+1];
334 Debug_Puts(TRACE_TO_KTERM, ")\r\n");
336 #if LOCK_DEBUG_OUTPUT
337 SHORTREL(&glDebug_Lock);
341 void Debug_Log(const char *FuncName, const char *Fmt, ...)
344 int i = gDebug_Level;
345 tTID tid = Threads_GetTID();
347 #if LOCK_DEBUG_OUTPUT
348 if(CPU_HAS_LOCK(&glDebug_Lock)) return ;
349 SHORTLOCK(&glDebug_Lock);
352 Debug_FmtS(TRACE_TO_KTERM, "%014lli ", now());
353 while(i--) Debug_Puts(TRACE_TO_KTERM, " ");
355 Debug_Puts(TRACE_TO_KTERM, FuncName);
356 Debug_FmtS(TRACE_TO_KTERM, "[%i]", tid);
357 Debug_Puts(TRACE_TO_KTERM, ": ");
360 Debug_Fmt(TRACE_TO_KTERM, Fmt, args);
363 Debug_Puts(TRACE_TO_KTERM, "\r\n");
365 #if LOCK_DEBUG_OUTPUT
366 SHORTREL(&glDebug_Lock);
370 void Debug_Leave(const char *FuncName, char RetType, ...)
374 tTID tid = Threads_GetTID();
376 #if LOCK_DEBUG_OUTPUT
377 if(CPU_HAS_LOCK(&glDebug_Lock)) return ;
378 SHORTLOCK(&glDebug_Lock);
383 va_start(args, RetType);
389 Debug_FmtS(TRACE_TO_KTERM, "%014lli ", now());
391 while(i--) Debug_Puts(TRACE_TO_KTERM, " ");
393 Debug_Puts(TRACE_TO_KTERM, FuncName);
394 Debug_FmtS(TRACE_TO_KTERM, "[%i]", tid);
395 Debug_Puts(TRACE_TO_KTERM, ": RETURN");
399 Debug_Puts(TRACE_TO_KTERM, "\r\n");
400 #if LOCK_DEBUG_OUTPUT
401 SHORTREL(&glDebug_Lock);
408 case 'n': Debug_Puts(TRACE_TO_KTERM, " NULL"); break;
409 case 'p': Debug_Fmt(TRACE_TO_KTERM, " %p", args); break;
410 case 'P': Debug_Fmt(TRACE_TO_KTERM, " %P", args); break; // PAddr
411 case 's': Debug_Fmt(TRACE_TO_KTERM, " '%s'", args); break;
412 case 'i': Debug_Fmt(TRACE_TO_KTERM, " %i", args); break;
413 case 'u': Debug_Fmt(TRACE_TO_KTERM, " %u", args); break;
414 case 'x': Debug_Fmt(TRACE_TO_KTERM, " 0x%x", args); break;
416 case 'X': Debug_Fmt(TRACE_TO_KTERM, " 0x%llx", args); break;
418 Debug_Puts(TRACE_TO_KTERM, "\r\n");
422 #if LOCK_DEBUG_OUTPUT
423 SHORTREL(&glDebug_Lock);
427 void Debug_HexDump(const char *Header, const void *Data, size_t Length)
429 const Uint8 *cdat = Data;
431 LogF("%014lli ", now());
432 Debug_Puts(1, Header);
433 LogF(" (Hexdump of %p+%i)\r\n", Data, Length);
435 #define CH(n) ((' '<=cdat[(n)]&&cdat[(n)]<0x7F) ? cdat[(n)] : '.')
439 LogF("%014lli Log: %04x:"
440 " %02x %02x %02x %02x %02x %02x %02x %02x "
441 " %02x %02x %02x %02x %02x %02x %02x %02x "
442 " %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c\r\n",
445 cdat[ 0], cdat[ 1], cdat[ 2], cdat[ 3], cdat[ 4], cdat[ 5], cdat[ 6], cdat[ 7],
446 cdat[ 8], cdat[ 9], cdat[10], cdat[11], cdat[12], cdat[13], cdat[14], cdat[15],
447 CH(0), CH(1), CH(2), CH(3), CH(4), CH(5), CH(6), CH(7),
448 CH(8), CH(9), CH(10), CH(11), CH(12), CH(13), CH(14), CH(15)
457 LogF("%014lli Log: %04x: ", now(), pos);
458 for(i = 0; i < Length; i ++)
460 LogF("%02x ", cdat[i]);
462 for( ; i < 16; i ++) LogF(" ");
464 for(i = 0; i < Length; i ++)
466 if( i == 8 ) LogF(" ");