#include #include #include #include #include #include #include #include bool g_disable_debug = false; namespace Debug { Kernel::RecursiveSpinLock s_debug_lock; void dump_stack_trace() { using namespace Kernel; struct stackframe { stackframe* bp; uintptr_t ip; }; SpinLockGuard _(s_debug_lock); stackframe* frame = (stackframe*)__builtin_frame_address(0); if (!frame) { dprintln("Could not get frame address"); return; } uintptr_t first_ip = frame->ip; uintptr_t last_ip = 0; bool first = true; BAN::Formatter::print(Debug::putchar, "\e[36mStack trace:\r\n"); while (frame) { if (!PageTable::is_valid_pointer((vaddr_t)frame)) { derrorln("invalid pointer {H}", (vaddr_t)frame); break; } if (PageTable::current().is_page_free((vaddr_t)frame & PAGE_ADDR_MASK)) { derrorln(" {} not mapped", frame); break; } BAN::Formatter::print(Debug::putchar, " {}\r\n", (void*)frame->ip); if (!first && frame->ip == first_ip) { derrorln("looping kernel panic :("); break; } else if (!first && frame->ip == last_ip) { derrorln("repeating stack trace"); break; } last_ip = frame->ip; frame = frame->bp; first = false; } BAN::Formatter::print(Debug::putchar, "\e[m"); } void putchar(char ch) { using namespace Kernel; if (g_disable_debug) return; if (Kernel::Serial::has_devices()) return Kernel::Serial::putchar_any(ch); if (Kernel::TTY::is_initialized()) return Kernel::TTY::putchar_current(ch); if (g_terminal_driver) { static uint32_t col = 0; static uint32_t row = 0; uint32_t row_copy = row; if (ch == '\n') { row++; col = 0; } else if (ch == '\r') { col = 0; } else { if (!isprint(ch)) ch = '?'; g_terminal_driver->putchar_at(ch, col, row, TerminalColor::WHITE, TerminalColor::BLACK); col++; if (col >= g_terminal_driver->width()) { row++; col = 0; } } if (row >= g_terminal_driver->height()) row = 0; if (row != row_copy) { for (uint32_t i = col; i < g_terminal_driver->width(); i++) { g_terminal_driver->putchar_at(' ', i, row, TerminalColor::WHITE, TerminalColor::BLACK); if (row + 1 < g_terminal_driver->height()) g_terminal_driver->putchar_at(' ', i, row + 1, TerminalColor::WHITE, TerminalColor::BLACK); } } } } void print_prefix(const char* file, int line) { auto ms_since_boot = Kernel::SystemTimer::is_initialized() ? Kernel::SystemTimer::get().ms_since_boot() : 0; BAN::Formatter::print(Debug::putchar, "[{5}.{3}] {}:{}: ", ms_since_boot / 1000, ms_since_boot % 1000, file, line); } }