Kernel: Add optional userspace backtrace to Process::crash

This is very useful for debugging the initial userspace applications, as
the CrashReporter is not yet running.
This commit is contained in:
Timon Kruiper 2023-01-30 12:10:29 +01:00 committed by Linus Groh
parent 3611427ce2
commit 3295137224
6 changed files with 23 additions and 6 deletions

View file

@ -39,7 +39,7 @@ void handle_crash(Kernel::RegisterState const& regs, char const* description, in
PANIC("Crash in kernel");
}
process.crash(signal, regs.ip(), out_of_memory);
process.crash(signal, { regs }, out_of_memory);
}
}

View file

@ -173,7 +173,8 @@ NEVER_INLINE static void dump_backtrace_impl(FlatPtr base_pointer, bool use_ksym
void dump_backtrace_from_base_pointer(FlatPtr base_pointer)
{
dump_backtrace_impl(base_pointer, g_kernel_symbols_available, PrintToScreen::Yes);
// FIXME: Change signature of dump_backtrace_impl to use an enum instead of a bool.
dump_backtrace_impl(base_pointer, /*use_ksym=*/false, PrintToScreen::No);
}
void dump_backtrace(PrintToScreen print_to_screen)

View file

@ -456,11 +456,13 @@ void create_signal_trampoline()
g_signal_trampoline_region->remap();
}
void Process::crash(int signal, FlatPtr ip, bool out_of_memory)
void Process::crash(int signal, Optional<RegisterState const&> regs, bool out_of_memory)
{
VERIFY(!is_dead());
VERIFY(&Process::current() == this);
auto ip = regs.has_value() ? regs->ip() : 0;
if (out_of_memory) {
dbgln("\033[31;1mOut of memory\033[m, killing: {}", *this);
} else {
@ -470,6 +472,20 @@ void Process::crash(int signal, FlatPtr ip, bool out_of_memory)
} else {
dbgln("\033[31;1m{:p} (?)\033[0m\n", ip);
}
#if ARCH(X86_64)
constexpr bool userspace_backtrace = false;
#elif ARCH(AARCH64)
constexpr bool userspace_backtrace = true;
#else
# error "Unknown architecture"
#endif
if constexpr (userspace_backtrace) {
dbgln("Userspace backtrace:");
auto bp = regs.has_value() ? regs->bp() : 0;
dump_backtrace_from_base_pointer(bp);
}
dbgln("Kernel backtrace:");
dump_backtrace();
}
with_mutable_protected_data([&](auto& protected_data) {

View file

@ -456,7 +456,7 @@ public:
static void initialize();
[[noreturn]] void crash(int signal, FlatPtr ip, bool out_of_memory = false);
[[noreturn]] void crash(int signal, Optional<RegisterState const&> regs, bool out_of_memory = false);
[[nodiscard]] siginfo_t wait_info() const;
const TTY* tty() const { return m_tty; }

View file

@ -183,7 +183,7 @@ NEVER_INLINE void syscall_handler(TrapFrame* trap)
if (result.is_error() && result.error().code() == EPROMISEVIOLATION) {
VERIFY(current_thread->is_promise_violation_pending());
current_thread->set_promise_violation_pending(false);
process.crash(SIGABRT, 0);
process.crash(SIGABRT, {});
} else {
VERIFY(!current_thread->is_promise_violation_pending());
}

View file

@ -86,7 +86,7 @@ void Process::sys$exit_thread(Userspace<void*> exit_value, Userspace<void*> stac
auto result = require_promise(Pledge::thread);
if (result.is_error()) {
// Crash now, as we will never reach back to the syscall handler.
crash(SIGABRT, 0);
crash(SIGABRT, {});
}
if (this->thread_count() == 1) {