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/Debug to the VTerm
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_FmtS(int bUseKTerm, const char *format, ...);
23 bool Debug_Fmt(int bUseKTerm, const char *format, va_list args);
24 void Debug_SetKTerminal(const char *File);
28 int giDebug_KTerm = -1;
29 int gbDebug_IsKPanic = 0;
30 volatile int gbInPutChar = 0;
32 tShortSpinlock glDebug_Lock;
34 // - Disabled because it breaks shit
35 int gbSendNetworkDebug = 0;
38 static void Debug_Putchar(char ch)
40 Debug_PutCharDebug(ch);
42 if( gbDebug_IsKPanic )
43 KernelPanic_PutChar(ch);
45 if( gbDebug_IsKPanic < 2 )
47 if(gbInPutChar) return ;
49 if(giDebug_KTerm != -1)
50 VFS_Write(giDebug_KTerm, 1, &ch);
54 if( gbSendNetworkDebug )
56 char str[2] = {ch, 0};
57 IPStack_SendDebugText(str);
61 static void Debug_Puts(int UseKTerm, const char *Str)
65 Debug_PutStringDebug(Str);
67 if( gbDebug_IsKPanic )
69 for( len = 0; Str[len]; len ++ )
70 KernelPanic_PutChar( Str[len] );
73 for( len = 0; Str[len]; len ++ );
75 if( gbSendNetworkDebug )
76 IPStack_SendDebugText(Str);
78 // Output to the kernel terminal
79 if( UseKTerm && gbDebug_IsKPanic < 2 && giDebug_KTerm != -1 && gbInPutChar == 0)
82 VFS_Write(giDebug_KTerm, len, Str);
87 bool Debug_Fmt(int bUseKTerm, const char *format, va_list args)
89 char buf[DEBUG_MAX_LINE_LEN];
90 buf[DEBUG_MAX_LINE_LEN-1] = 0;
91 size_t len = vsnprintf(buf, DEBUG_MAX_LINE_LEN-1, format, args);
92 Debug_Puts(bUseKTerm, buf);
93 if( len > DEBUG_MAX_LINE_LEN-1 ) {
95 Debug_Puts(bUseKTerm, "[...]");
101 void Debug_FmtS(int bUseKTerm, const char *format, ...)
104 va_start(args, format);
105 Debug_Fmt(bUseKTerm, format, args);
109 void Debug_KernelPanic(void)
111 // 5 nested panics? Fuck it
112 if( gbDebug_IsKPanic > 5 )
115 if( gbDebug_IsKPanic == 1 )
117 #if LOCK_DEBUG_OUTPUT
118 SHORTREL(&glDebug_Lock);
122 KernelPanic_SetMode();
126 * \fn void LogF(const char *Msg, ...)
127 * \brief Raw debug log (no new line, no prefix)
128 * \return True if all of the provided text was printed
130 bool LogF(const char *Fmt, ...)
132 #if LOCK_DEBUG_OUTPUT
133 if(CPU_HAS_LOCK(&glDebug_Lock)) {
137 SHORTLOCK(&glDebug_Lock);
142 bool rv = Debug_Fmt(1, Fmt, args);
145 #if LOCK_DEBUG_OUTPUT
146 SHORTREL(&glDebug_Lock);
151 * \fn void Debug(const char *Msg, ...)
152 * \brief Print only to the debug channel (not KTerm)
154 void Debug(const char *Fmt, ...)
158 #if LOCK_DEBUG_OUTPUT
159 if(CPU_HAS_LOCK(&glDebug_Lock)) return ;
160 SHORTLOCK(&glDebug_Lock);
163 Debug_Puts(TRACE_TO_KTERM, "Debug: ");
165 Debug_Fmt(TRACE_TO_KTERM, Fmt, args);
167 Debug_Puts(TRACE_TO_KTERM, "\r\n");
168 #if LOCK_DEBUG_OUTPUT
169 SHORTREL(&glDebug_Lock);
174 void LogFV(const char *Fmt, va_list args)
176 #if LOCK_DEBUG_OUTPUT
177 if(CPU_HAS_LOCK(&glDebug_Lock)) return ;
178 SHORTLOCK(&glDebug_Lock);
181 Debug_Fmt(1, Fmt, args);
183 #if LOCK_DEBUG_OUTPUT
184 SHORTREL(&glDebug_Lock);
188 void LogV(const char *Fmt, va_list args)
190 #if LOCK_DEBUG_OUTPUT
191 if(CPU_HAS_LOCK(&glDebug_Lock)) return ;
192 SHORTLOCK(&glDebug_Lock);
195 Debug_Puts(1, "Log: ");
196 Debug_Fmt(1, Fmt, args);
197 Debug_Puts(1, "\r\n");
199 #if LOCK_DEBUG_OUTPUT
200 SHORTREL(&glDebug_Lock);
205 * \fn void Log(const char *Msg, ...)
207 void Log(const char *Fmt, ...)
215 void Warning(const char *Fmt, ...)
219 #if LOCK_DEBUG_OUTPUT
220 if(CPU_HAS_LOCK(&glDebug_Lock)) return ;
221 SHORTLOCK(&glDebug_Lock);
224 Debug_Puts(1, "Warning: ");
226 Debug_Fmt(1, Fmt, args);
231 #if LOCK_DEBUG_OUTPUT
232 SHORTREL(&glDebug_Lock);
235 void Panic(const char *Fmt, ...)
239 #if LOCK_DEBUG_OUTPUT
240 if( !CPU_HAS_LOCK(&glDebug_Lock) )
241 SHORTLOCK(&glDebug_Lock);
243 // And never SHORTREL
247 Debug_Puts(1, "\x1b[31m");
248 Debug_Puts(1, "Panic: ");
250 Debug_Fmt(1, Fmt, args);
252 Debug_Puts(1, "\x1b[0m\r\n");
254 Proc_PrintBacktrace();
261 void Debug_SetKTerminal(const char *File)
263 if(giDebug_KTerm != -1) {
264 // Clear FD to -1 before closing (prevents writes to closed FD)
265 int oldfd = giDebug_KTerm;
269 giDebug_KTerm = VFS_Open(File, VFS_OPENFLAG_WRITE);
272 void Debug_Enter(const char *FuncName, const char *ArgTypes, ...)
277 tTID tid = Threads_GetTID();
279 #if LOCK_DEBUG_OUTPUT
280 if(CPU_HAS_LOCK(&glDebug_Lock)) return ;
281 SHORTLOCK(&glDebug_Lock);
286 va_start(args, ArgTypes);
288 Debug_FmtS(TRACE_TO_KTERM, "%014lli ", now());
289 while(i--) Debug_Puts(TRACE_TO_KTERM, " ");
291 Debug_Puts(TRACE_TO_KTERM, FuncName);
292 Debug_FmtS(TRACE_TO_KTERM, "[%i]", tid);
293 Debug_Puts(TRACE_TO_KTERM, ": (");
297 pos = strpos(ArgTypes, ' ');
298 if(pos == -1 || pos > 1) {
300 Debug_Puts(TRACE_TO_KTERM, ArgTypes+1);
302 Debug_FmtS(TRACE_TO_KTERM, "%.*s", pos-1, ArgTypes+1);
304 Debug_Puts(TRACE_TO_KTERM, "=");
308 case 'p': Debug_FmtS(TRACE_TO_KTERM, "%p", va_arg(args, void*)); break;
309 case 'P': Debug_FmtS(TRACE_TO_KTERM, "%P", va_arg(args, tPAddr)); break;
310 case 's': Debug_FmtS(TRACE_TO_KTERM, "'%s'", va_arg(args, char*)); break;
311 case 'i': Debug_FmtS(TRACE_TO_KTERM, "%i", va_arg(args, int)); break;
312 case 'u': Debug_FmtS(TRACE_TO_KTERM, "%u", va_arg(args, Uint)); break;
313 case 'x': Debug_FmtS(TRACE_TO_KTERM, "0x%x", va_arg(args, Uint)); break;
314 case 'b': Debug_FmtS(TRACE_TO_KTERM, "0b%b", va_arg(args, Uint)); break;
315 case 'X': Debug_FmtS(TRACE_TO_KTERM, "0x%llx", va_arg(args, Uint64)); break; // Extended (64-Bit)
316 case 'B': Debug_FmtS(TRACE_TO_KTERM, "0b%llb", va_arg(args, Uint64)); break; // Extended (64-Bit)
319 Debug_Puts(TRACE_TO_KTERM, ", ");
323 ArgTypes = &ArgTypes[pos+1];
327 Debug_Puts(TRACE_TO_KTERM, ")\r\n");
329 #if LOCK_DEBUG_OUTPUT
330 SHORTREL(&glDebug_Lock);
334 void Debug_Log(const char *FuncName, const char *Fmt, ...)
337 int i = gDebug_Level;
338 tTID tid = Threads_GetTID();
340 #if LOCK_DEBUG_OUTPUT
341 if(CPU_HAS_LOCK(&glDebug_Lock)) return ;
342 SHORTLOCK(&glDebug_Lock);
345 Debug_FmtS(TRACE_TO_KTERM, "%014lli ", now());
346 while(i--) Debug_Puts(TRACE_TO_KTERM, " ");
348 Debug_Puts(TRACE_TO_KTERM, FuncName);
349 Debug_FmtS(TRACE_TO_KTERM, "[%i]", tid);
350 Debug_Puts(TRACE_TO_KTERM, ": ");
353 Debug_Fmt(TRACE_TO_KTERM, Fmt, args);
356 Debug_Puts(TRACE_TO_KTERM, "\r\n");
358 #if LOCK_DEBUG_OUTPUT
359 SHORTREL(&glDebug_Lock);
363 void Debug_Leave(const char *FuncName, char RetType, ...)
367 tTID tid = Threads_GetTID();
369 #if LOCK_DEBUG_OUTPUT
370 if(CPU_HAS_LOCK(&glDebug_Lock)) return ;
371 SHORTLOCK(&glDebug_Lock);
376 va_start(args, RetType);
382 Debug_FmtS(TRACE_TO_KTERM, "%014lli ", now());
384 while(i--) Debug_Puts(TRACE_TO_KTERM, " ");
386 Debug_Puts(TRACE_TO_KTERM, FuncName);
387 Debug_FmtS(TRACE_TO_KTERM, "[%i]", tid);
388 Debug_Puts(TRACE_TO_KTERM, ": RETURN");
392 Debug_Puts(TRACE_TO_KTERM, "\r\n");
393 #if LOCK_DEBUG_OUTPUT
394 SHORTREL(&glDebug_Lock);
401 case 'n': Debug_Puts(TRACE_TO_KTERM, " NULL"); break;
402 case 'p': Debug_Fmt(TRACE_TO_KTERM, " %p", args); break;
403 case 'P': Debug_Fmt(TRACE_TO_KTERM, " %P", args); break; // PAddr
404 case 's': Debug_Fmt(TRACE_TO_KTERM, " '%s'", args); break;
405 case 'i': Debug_Fmt(TRACE_TO_KTERM, " %i", args); break;
406 case 'u': Debug_Fmt(TRACE_TO_KTERM, " %u", args); break;
407 case 'x': Debug_Fmt(TRACE_TO_KTERM, " 0x%x", args); break;
409 case 'X': Debug_Fmt(TRACE_TO_KTERM, " 0x%llx", args); break;
411 Debug_Puts(TRACE_TO_KTERM, "\r\n");
415 #if LOCK_DEBUG_OUTPUT
416 SHORTREL(&glDebug_Lock);
420 void Debug_HexDump(const char *Header, const void *Data, size_t Length)
422 const Uint8 *cdat = Data;
424 LogF("%014lli ", now());
425 Debug_Puts(1, Header);
426 LogF(" (Hexdump of %p+%i)\r\n", Data, Length);
428 #define CH(n) ((' '<=cdat[(n)]&&cdat[(n)]<0x7F) ? cdat[(n)] : '.')
432 LogF("%014lli Log: %04x:"
433 " %02x %02x %02x %02x %02x %02x %02x %02x "
434 " %02x %02x %02x %02x %02x %02x %02x %02x "
435 " %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c\r\n",
438 cdat[ 0], cdat[ 1], cdat[ 2], cdat[ 3], cdat[ 4], cdat[ 5], cdat[ 6], cdat[ 7],
439 cdat[ 8], cdat[ 9], cdat[10], cdat[11], cdat[12], cdat[13], cdat[14], cdat[15],
440 CH(0), CH(1), CH(2), CH(3), CH(4), CH(5), CH(6), CH(7),
441 CH(8), CH(9), CH(10), CH(11), CH(12), CH(13), CH(14), CH(15)
450 LogF("%014lli Log: %04x: ", now(), pos);
451 for(i = 0; i < Length; i ++)
453 LogF("%02x ", cdat[i]);
455 for( ; i < 16; i ++) LogF(" ");
457 for(i = 0; i < Length; i ++)
459 if( i == 8 ) LogF(" ");