From f6c0fccc01556155d171d2ba86d998c5ddae87ad Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 12 Jan 2020 10:19:37 +0100 Subject: [PATCH] Kernel: Fix busted backtraces when a thread backtraces itself When the current thread is backtracing itself, we now start walking the stack from the current EBP register value, instead of the TSS one. Now SystemMonitor always appears to be running Thread::backtrace() when sampled, which makes perfect sense. :^) --- Kernel/Thread.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp index e516d25e15..9fb87b9cba 100644 --- a/Kernel/Thread.cpp +++ b/Kernel/Thread.cpp @@ -698,6 +698,14 @@ String Thread::backtrace(ProcessInspectionHandle&) const String Thread::backtrace_impl() const { + u32 start_frame; + if (current == this) { + asm volatile("movl %%ebp, %%eax" + : "=a"(start_frame)); + } else { + start_frame = frame_ptr(); + } + SmapDisabler disabler; auto& process = const_cast(this->process()); ProcessPagingScope paging_scope(process); @@ -706,11 +714,14 @@ String Thread::backtrace_impl() const const KSym* ksym; }; StringBuilder builder; - Vector recognized_symbols; - recognized_symbols.append({ tss().eip, ksymbolicate(tss().eip) }); - for (u32* stack_ptr = (u32*)frame_ptr(); process.validate_read_from_kernel(VirtualAddress((u32)stack_ptr), sizeof(void*) * 2); stack_ptr = (u32*)*stack_ptr) { + Vector recognized_symbols; + if (current != this) + recognized_symbols.append({ tss().eip, ksymbolicate(tss().eip) }); + for (u32* stack_ptr = (u32*)start_frame; process.validate_read_from_kernel(VirtualAddress((u32)stack_ptr), sizeof(void*) * 2); stack_ptr = (u32*)*stack_ptr) { u32 retaddr = stack_ptr[1]; recognized_symbols.append({ retaddr, ksymbolicate(retaddr) }); + if (recognized_symbols.size() == 256) + break; } bool mask_kernel_addresses = !current->process().is_superuser();