Kernel panic is a special case, and there is no signal or exception for that so we need to rely on special workaround called `dumptid`. FreeBSDKernel plugin is supposed to find this thread and set it manually through `SetStopInfo()` in `CalculateStopInfo()` like Mach core plugin does. Before (We had to find and select crashed thread list otherwise thread 1 was selected by default): ``` ➜ sudo lldb /boot/panic/kernel -c /var/crash/vmcore.last (lldb) target create "/boot/panic/kernel" --core "/var/crash/vmcore.last" Core file '/var/crash/vmcore.last' (x86_64) was loaded. (lldb) bt * thread #1, name = '(pid 12991) dtrace' * frame #0: 0xffffffff80bf9322 kernel`sched_switch(td=0xfffff8015882f780, flags=259) at sched_ule.c:2448:26 frame #1: 0xffffffff80bd38d2 kernel`mi_switch(flags=259) at kern_synch.c:530:2 frame #2: 0xffffffff80c29799 kernel`sleepq_switch(wchan=0xfffff8014edff300, pri=0) at subr_sleepqueue.c:608:2 frame #3: 0xffffffff80c29b76 kernel`sleepq_catch_signals(wchan=0xfffff8014edff300, pri=0) at subr_sleepqueue.c:523:3 frame #4: 0xffffffff80c29d32 kernel`sleepq_timedwait_sig(wchan=<unavailable>, pri=<unavailable>) at subr_sleepqueue.c:704:11 frame #5: 0xffffffff80bd2e2d kernel`_sleep(ident=0xfffff8014edff300, lock=0xffffffff81df2880, priority=768, wmesg="uwait", sbt=2573804118162, pr=0, flags=512) at kern_synch.c:215:10 frame #6: 0xffffffff80be8622 kernel`umtxq_sleep(uq=0xfffff8014edff300, wmesg="uwait", timo=0xfffffe0279cb3d20) at kern_umtx.c:843:11 frame #7: 0xffffffff80bef87a kernel`do_wait(td=0xfffff8015882f780, addr=<unavailable>, id=0, timeout=0xfffffe0279cb3d90, compat32=1, is_private=1) at kern_umtx.c:1316:12 frame #8: 0xffffffff80bed264 kernel`__umtx_op_wait_uint_private(td=0xfffff8015882f780, uap=0xfffffe0279cb3dd8, ops=<unavailable>) at kern_umtx.c:3990:10 frame #9: 0xffffffff80beaabe kernel`sys__umtx_op [inlined] kern__umtx_op(td=<unavailable>, obj=<unavailable>, op=<unavailable>, val=<unavailable>, uaddr1=<unavailable>, uaddr2=<unavailable>, ops=<unavailable>) at kern_umtx.c:4999:10 frame #10: 0xffffffff80beaa89 kernel`sys__umtx_op(td=<unavailable>, uap=<unavailable>) at kern_umtx.c:5024:10 frame #11: 0xffffffff81122cd1 kernel`amd64_syscall [inlined] syscallenter(td=0xfffff8015882f780) at subr_syscall.c:165:11 frame #12: 0xffffffff81122c19 kernel`amd64_syscall(td=0xfffff8015882f780, traced=0) at trap.c:1208:2 frame #13: 0xffffffff810f1dbb kernel`fast_syscall_common at exception.S:570 ``` After: ``` ➜ sudo ./build/bin/lldb /boot/panic/kernel -c /var/crash/vmcore.last (lldb) target create "/boot/panic/kernel" --core "/var/crash/vmcore.last" Core file '/var/crash/vmcore.last' (x86_64) was loaded. (lldb) bt * thread #18, name = '(pid 5409) powerd (crashed)', stop reason = kernel panic * frame #0: 0xffffffff80bc6c91 kernel`__curthread at pcpu_aux.h:57:2 [inlined] frame #1: 0xffffffff80bc6c91 kernel`doadump(textdump=0) at kern_shutdown.c:399:2 frame #2: 0xffffffff804b3b7a kernel`db_dump(dummy=<unavailable>, dummy2=<unavailable>, dummy3=<unavailable>, dummy4=<unavailable>) at db_command.c:596:10 frame #3: 0xffffffff804b396d kernel`db_command(last_cmdp=<unavailable>, cmd_table=<unavailable>, dopager=true) at db_command.c:508:3 frame #4: 0xffffffff804b362d kernel`db_command_loop at db_command.c:555:3 frame #5: 0xffffffff804b7026 kernel`db_trap(type=<unavailable>, code=<unavailable>) at db_main.c:267:3 frame #6: 0xffffffff80c16aaf kernel`kdb_trap(type=3, code=0, tf=0xfffffe01b605b930) at subr_kdb.c:790:13 frame #7: 0xffffffff8112154e kernel`trap(frame=<unavailable>) at trap.c:614:8 frame #8: 0xffffffff810f14c8 kernel`calltrap at exception.S:285 frame #9: 0xffffffff81da2290 kernel`cn_devtab + 64 frame #10: 0xfffffe01b605b8b0 frame #11: 0xffffffff84001c43 dtrace.ko`dtrace_panic(format=<unavailable>) at dtrace.c:652:2 frame #12: 0xffffffff84005524 dtrace.ko`dtrace_action_panic(ecb=0xfffff80539cad580) at dtrace.c:7022:2 [inlined] frame #13: 0xffffffff840054de dtrace.ko`dtrace_probe(id=88998, arg0=14343377283488, arg1=<unavailable>, arg2=<unavailable>, arg3=<unavailable>, arg4=<unavailable>) at dtrace.c:7665:6 frame #14: 0xffffffff83e5213d systrace.ko`systrace_probe(sa=<unavailable>, type=<unavailable>, retval=<unavailable>) at systrace.c:226:2 frame #15: 0xffffffff8112318d kernel`syscallenter(td=0xfffff801318d5780) at subr_syscall.c:160:4 [inlined] frame #16: 0xffffffff81123112 kernel`amd64_syscall(td=0xfffff801318d5780, traced=0) at trap.c:1208:2 frame #17: 0xffffffff810f1dbb kernel`fast_syscall_common at exception.S:570 ```
95 lines
3.2 KiB
C++
95 lines
3.2 KiB
C++
//===-- ThreadFreeBSDKernel.cpp -------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "ThreadFreeBSDKernel.h"
|
|
|
|
#include "lldb/Target/StopInfo.h"
|
|
#include "lldb/Target/Unwind.h"
|
|
#include "lldb/Utility/Log.h"
|
|
|
|
#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
|
|
#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
|
|
#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
|
|
#include "ProcessFreeBSDKernel.h"
|
|
#include "RegisterContextFreeBSDKernel_arm64.h"
|
|
#include "RegisterContextFreeBSDKernel_i386.h"
|
|
#include "RegisterContextFreeBSDKernel_x86_64.h"
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
|
|
ThreadFreeBSDKernel::ThreadFreeBSDKernel(Process &process, lldb::tid_t tid,
|
|
lldb::addr_t pcb_addr,
|
|
std::string thread_name)
|
|
: Thread(process, tid), m_thread_name(std::move(thread_name)),
|
|
m_pcb_addr(pcb_addr) {}
|
|
|
|
ThreadFreeBSDKernel::~ThreadFreeBSDKernel() {}
|
|
|
|
void ThreadFreeBSDKernel::RefreshStateAfterStop() {}
|
|
|
|
lldb::RegisterContextSP ThreadFreeBSDKernel::GetRegisterContext() {
|
|
if (!m_reg_context_sp)
|
|
m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
|
|
return m_reg_context_sp;
|
|
}
|
|
|
|
lldb::RegisterContextSP
|
|
ThreadFreeBSDKernel::CreateRegisterContextForFrame(StackFrame *frame) {
|
|
RegisterContextSP reg_ctx_sp;
|
|
uint32_t concrete_frame_idx = 0;
|
|
|
|
if (frame)
|
|
concrete_frame_idx = frame->GetConcreteFrameIndex();
|
|
|
|
if (concrete_frame_idx == 0) {
|
|
if (m_thread_reg_ctx_sp)
|
|
return m_thread_reg_ctx_sp;
|
|
|
|
ProcessFreeBSDKernel *process =
|
|
static_cast<ProcessFreeBSDKernel *>(GetProcess().get());
|
|
ArchSpec arch = process->GetTarget().GetArchitecture();
|
|
|
|
switch (arch.GetMachine()) {
|
|
case llvm::Triple::aarch64:
|
|
m_thread_reg_ctx_sp =
|
|
std::make_shared<RegisterContextFreeBSDKernel_arm64>(
|
|
*this, std::make_unique<RegisterInfoPOSIX_arm64>(arch, 0),
|
|
m_pcb_addr);
|
|
break;
|
|
case llvm::Triple::x86:
|
|
m_thread_reg_ctx_sp = std::make_shared<RegisterContextFreeBSDKernel_i386>(
|
|
*this, new RegisterContextFreeBSD_i386(arch), m_pcb_addr);
|
|
break;
|
|
case llvm::Triple::x86_64:
|
|
m_thread_reg_ctx_sp =
|
|
std::make_shared<RegisterContextFreeBSDKernel_x86_64>(
|
|
*this, new RegisterContextFreeBSD_x86_64(arch), m_pcb_addr);
|
|
break;
|
|
default:
|
|
assert(false && "Unsupported architecture passed to ThreadFreeBSDKernel");
|
|
break;
|
|
}
|
|
|
|
reg_ctx_sp = m_thread_reg_ctx_sp;
|
|
} else {
|
|
reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame);
|
|
}
|
|
return reg_ctx_sp;
|
|
}
|
|
|
|
bool ThreadFreeBSDKernel::CalculateStopInfo() {
|
|
if (m_is_crashed) {
|
|
// Set a stop reason for crashing threads only so that they get selected
|
|
// preferentially.
|
|
SetStopInfo(StopInfo::CreateStopReasonWithException(*this, "kernel panic"));
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|