Linux 故障转储

本文介绍如何创建和查看不同类型的 Linux 故障转储文件。 查看 Linux 故障转储需要 WinDbg 版本 1.2402.24001.0 或更高版本。

在 WinDbg 中打开 Linux(非 Windows)核心转储时,基本调试器命令应全部正常工作,但引用 Windows 结构的扩展和特定于 Windows 的命令将不起作用。

支持的故障转储文件

Linux 内核转储

在 Windows 调试器中提供了打开 Linux 内核压缩的 KDUMP,并使用完整的专用 DWARF 符号执行事后调试和分析。

WinDbg 仅支持 ZLIB 压缩的 KDUMP 文件。 不支持 LZO 和 Snappy 压缩 KDUMP。

有关 Linux KDUMP 的一般信息,请参阅 KDump (Linux) 维基百科页和 核心转储

ELF 核心转储

作为支持 Open Enclave 的一部分,WinDbg 可以从 Enclave 和 Linux 应用程序打开 ELF 核心转储和二进制文件以及 DWARF 符号(DWARF 5 不受支持)。 有关 Open Enclave 的详细信息,请参阅 Open Enclave 调试

进程转储

支持单个进程转储。 有多种方法可以收集进程转储,包括 Linux Sysinternals ProcDump for Linux 实用工具。 另一个选项是使用 GNU 调试器 - GDBServer 生成核心转储。 有关 GDBServer 的详细信息,请参阅 https://en.wikipedia.org/wiki/Gdbserver。 Sourceware 网站提供了远程 gdb 调试文档 - 调试远程程序

Windows 调试器中的标准模板库 (STL) 扩展性由 NatVis 文件提供, stl.natvis 该文件可了解随 Visual Studio 和 Windows 一起随附的许多版本的 STL。 有关 NATVIS 的常规信息,请参阅 NatVis 中的本机调试器对象。 用于 Linux 组件(GCC 或 LLDB)的 STL 版本非常不同。

若要为 Linux 启用 NATVIS 可视化和 DML 链接遍历优化,请先卸载默认 natvis 文件 .scriptunloadstl.natvis

然后 .scriptload 文件 gstl.natvis 。 使用 .scriptlist 确认是否 gstl.natvis 处于活动状态。

0: kd> .scriptlist
Command Loaded Scripts:
...
    NatVis script from 'C:\Users\Bob\AppData\Local\dbg\UI\2402.24001.0\amd64\Visualizers\gstl.natvis'

有关使用 DML 的详细信息,请参阅 使用 DML 自定义调试器输出。

DisplayGreeting 应用的单个进程核心转储

此示例演示如何使用 gdb 创建单个进程核心转储。 有关将 GDBServer 与 WinDbg 配合使用以及代码演练的详细信息,请参阅 Linux 实时远程进程调试。 有关 DisplayGreeting 的示例代码,请参阅 C++应用演练

找到所需的进程

我们可以使用 ps -A 命令列出 Linux 中的所有进程,或者将 -f 选项与 pgrep 一起使用,因为我们知道我们要查找 DisplayGreeting 应用。

$ pgrep -f DisplayGreeting
9382

在本示例演练中,它显示了 9382 的进程 ID。

使用 gdb 附加到进程并生成核心转储

使用 gdb 附加到进程。

$ gdb -p 9382

显示 gdb 命令的 generate-core-file 帮助。

(gdb) help generate-core-file
Save a core file with the current state of the debugged process.
Argument is optional filename.  Default filename is 'core.<process_id>'.

然后在 (gdb) 提示符下,生成包含默认文件名的进程核心转储文件。

(gdb) generate-core-file
Saved corefile core.9382
(gdb) quit

加载并检查 Linux 进程核心转储

使用 WinDbg 中的“打开转储文件”菜单选项加载生成的核心转储。

在调试器会话中添加源和符号路径

若要查看源代码和变量,请设置符号和源路径。 有关设置符号路径的一般信息,请参阅使用符号。 有关 Linux 符号的详细信息,请参阅 Linux 符号和源

使用 .sympath 将符号路径添加到调试器会话。 在此 WSL Linux Ubuntu 示例中,DisplayGreetings 代码和符号可用于名为 Bob 的用户。

\\wsl$\Ubuntu\mnt\c\Users\Bob\

在 WSL 中,此目录映射到 Windows OS 位置: C:\Users\Bob\ 因此使用这两个命令。

.sympath C:\Users\Bob\

.srcpath C:\Users\Bob\

有关在 Windows 中访问 WSL 文件系统的详细信息,请参阅 WSL 的文件权限。

若要从其他 Linux OS 符号中受益,请使用 .sympath 位置添加 DebugInfoD 符号。

.sympath+ DebugInfoD*https://debuginfod.elfutils.org

.reload使用命令重新加载符号。

此外,还支持从 DebugInfoD 服务器自动下载源,这些源支持返回该项目类型。 若要利用此功能,请使用 .srcpath 添加 elfutils 服务器。

.srcpath+ DebugInfoD*https://debuginfod.elfutils.org

检查进程转储

使用 lm 命令确认转储文件是否包含 DisplayGreeting 应用。

0:000> lm
start             end                 module name
00005555`55554000 00005555`55558140   DisplayGreeting T (service symbols: DWARF Private Symbols)        c:\users\bob\DisplayGreeting
00007fff`f7a54000 00007fff`f7a732e8   libgcc_s_so   (deferred)    
00007fff`f7a74000 00007fff`f7b5a108   libm_so    (deferred)    
00007fff`f7b5b000 00007fff`f7d82e50   libc_so  T (service symbols: DWARF Private Symbols)        C:\ProgramData\Dbg\sym\_.debug\elf-buildid-sym-a43bfc8428df6623cd498c9c0caeb91aec9be4f9\_.debug
00007fff`f7d83000 00007fff`f7fae8c0   libstdc___so   (deferred)    
00007fff`f7fc1000 00007fff`f7fc1000   linux_vdso_so   (deferred)    
00007fff`f7fc3000 00007fff`f7ffe2d8   ld_linux_x86_64_so T (service symbols: DWARF Private Symbols)        C:\ProgramData\Dbg\sym\_.debug\elf-buildid-sym-9718d3757f00d2366056830aae09698dbd35e32c\_.debug

请注意,第一个命令执行可能需要一些时间,因为调试符号将加载到缓存中。 除了通过符号服务器或本地搜索路径查找符号和二进制文件之外,由于 GDBServer 集成,如果无法在本地找到这些文件,它可能会从远程文件系统加载这些文件。 此操作通常比从 symsrv 或本地搜索路径获取符号慢。

x使用命令显示 DisplayGreeting 中可用的函数。

0:000> x /D /f DisplayGreeting!*
 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

*** WARNING: Unable to verify timestamp for DisplayGreeting
00005651`7935b331 DisplayGreeting!_GLOBAL__sub_I__Z17GetCppConGreetingPwm (void)
00005651`7935b2db DisplayGreeting!__static_initialization_and_destruction_0 (int, int)
00005651`7935b37b DisplayGreeting!std::__array_traits<wchar_t, 50>::_S_ptr (wchar_t (*)[50])
00005651`7935b368 DisplayGreeting!std::array<wchar_t, 50>::size (std::array<wchar_t, 50> *)
00005651`7935b34a DisplayGreeting!std::array<wchar_t, 50>::data (std::array<wchar_t, 50> *)
00005651`7935b225 DisplayGreeting!main (void)
00005651`7935b1e9 DisplayGreeting!GetCppConGreeting (wchar_t *, size_t)

dx使用命令查看局部变量问候语

0:000> dx greeting
...
Error: Unable to bind name 'greeting'

由于在进行转储时尚未使用参数问候语,因此在转储文件中不可用。

dx使用命令检查转储文件中可用的进程。

:000> dx @$cursession.Processes.Take(30)
@$cursession.Processes.Take(30)                
    [0x24a6]         : DisplayGreeting [Switch To]

Click on the `[Switch To]` DML link to switch to the 9382 process.

```dbgcmd
0:000> dx -s @$cursession.Processes.Take(30)[9382].SwitchTo()
0:000> dx -r1 @$cursession.Processes.Take(30)[9382]
@$cursession.Processes.Take(30)[9382]                 : DisplayGreeting [Switch To]
    Name             : DisplayGreeting
    Id               : 0x24a6
    Index            : 0x0
    Handle           : 0x24a6
    Threads         
    Modules         
    Environment     
    Direct3D        
    Attributes      
    Devices         
    Io              
    Memory          
    TTD    
    GroupedStacks   

若要查看有关线程和模块的信息,请单击输出中生成的 DML 链接,或键入类似于此命令的命令进行故障转储。

0:000> dx -r1 @$cursession.Processes.Take(30)[9382].Threads
@$cursession.Processes.Take(30)[9382].Threads       
    [0x24a6]         [Switch To]
0:000> dx -r1 @$cursession.Processes.Take(30)[9382].Modules
@$cursession.Processes.Take(30)[9382].Modules       
    [0x0]            : /mnt/c/Users/Bob/DisplayGreeting
    [0x1]            : /usr/lib/x86_64-linux-gnu/libgcc_s.so.1
    [0x2]            : /usr/lib/x86_64-linux-gnu/libm.so.6
    [0x3]            : /usr/lib/x86_64-linux-gnu/libc.so.6
    [0x4]            : /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30
    [0x5]            : /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
    [0x6]            : linux-vdso.so.1

使用 ELF/CORE 诊断扩展显示转储文件信息

使用 Linux 诊断扩展 - ELFBinComposition.dll显示转储文件信息。 例如,用于 !dumpdebug 确认这是 ELF 用户核心转储,并显示其他信息。

0:000> !dumpdebug
Dump Diagnostics: Format = ELF User Core
********************************************************************************
File Mapping Size:           0x151d78 (1 Mb)
Highest Memory Offset:       0x14e5f0 (1 Mb)
...

用于 !ntprpsinfo 显示NT_PRPSINFO数据。

0:000> !ntprpsinfo
NT_PRPSINFO (process info):
    state: 0, sname: t, zomb: 0, nice: 0, flag: 0x4040000019999999
    uid: 1000, gid: 1000, pid: 9382, ppid: 388, pgrp: 9382, sid: 388
    fname: DisplayGreeting
    psargs: ./DisplayGreeting

内核 KDump 故障转储

在 Linux 中创建故障转储文件有多种方法。 例如,内核故障转储介绍了 Ubuntu Linux 的一个选项。

其他选项包括使用 kexectools 来启用 Kdump。 有关详细信息,请参阅 KDump (Linux)。 如果已启用 kdump,则可以验证 kdump 是否处于活动状态并使用它运行 systemctl status kdump

在测试系统上触发 OS 崩溃后,将创建故障转储文件。

加载并检查 Linux OS 故障转储

使用“打开转储文件”菜单选项加载生成的 kdump。

如上一部分所述,通过加载 gstl.natvis 文件启用 NATVIS 可视化和 DML 链接遍历优化 Linux。

使用 ELF Bin 组合命令分析 Linux 内核转储

若要能够使用其他 ELF Bin 组合命令,请使用 .chain 命令确认加载了ELFBinComposition.dll。

0: kd> .chain
Extension DLL chain:
    ELFBinComposition: image 10.0.27606.1000, API 0.0.0, 
        [path: C:\Users\Bob\AppData\Local\dbg\UI\Fast.20240423.1\amd64\winext\ELFBinComposition.dll]
...

如果未加载 ELFBinComposition,请使用 .load 加载它。 有关详细信息,请参阅 .load、.loadby (加载扩展 DLL)

!ELFBinComposition.dumpdebug使用命令显示有关已加载转储文件的信息。 在此示例中,已加载 ELF 用户核心转储文件。

0: kd> !ELFBinComposition.dumpdebug
Dump Diagnostics: Format = Kernel KDump
********************************************************************************
File Mapping Size:           0x3b34090 (59 Mb)
Highest Memory Offset:       0x3b34090 (59 Mb)

使用 ELFBinComposition !vmcoreinfo 显示正在调试的 Linux 内核核心转储(KDUMP)中的 VMCOREINFO 表。

0: kd> !vmcoreinfo
VMCOREINFO:
    OSRELEASE=6.5.0-25-generic
    BUILD-ID=8567ad7c7c2f78f3654f6cc90a9e1b3f9c3a4b32
    PAGESIZE=4096
    SYMBOL(init_uts_ns)=ffffded86e11b388
    OFFSET(uts_namespace.name)=0
    SYMBOL(node_online_map)=ffffded86dcceb40
    SYMBOL(swapper_pg_dir)=ffffded86d143000
    SYMBOL(_stext)=ffffded86ace0000
    SYMBOL(vmap_area_list)=ffffded86de48140
    SYMBOL(mem_section)=ffff0f2e1efe4600
    LENGTH(mem_section)=8192
...

使用从 !kdumppagerange 零开始转储文件的第一部分转储。

0: kd> !kdumppagerange 0
    PFNs [0x540e0, 0x55643) -> Descs [0x0, 0x1563): File Offsets [0x307430, 0xeeb37a) 0xbe3f4a bytes across 5475 pages as ZLIB
    PFNs [0x55643, 0x55650) -> Descs [0x1563, 0x1570): File Offsets [0x306430, 0x307430) 0x1000 bytes across 13 duplicate pages as Uncompressed
    PFNs [0x55650, 0x556d6) -> Descs [0x1570, 0x15f6): File Offsets [0xeeb37a, 0xf0c405) 0x2108b bytes across 134 pages as ZLIB
    PFNs [0x556d6, 0x556dc) -> Descs [0x15f6, 0x15fc): File Offsets [0xf0c405, 0xf12405) 0x6000 bytes across 6 pages as Uncompressed
    PFNs [0x556dc, 0x55e98) -> Descs [0x15fc, 0x1db8): File Offsets [0xf12405, 0x1216d1b) 0x304916 bytes across 1980 pages as ZLIB
    PFNs [0x55e98, 0x55ea4) -> Descs [0x1db8, 0x1dc4): File Offsets [0x1216d1b, 0x1222d1b) 0xc000 bytes across 12 pages as Uncompressed
    PFNs [0x55ea4, 0x56542) -> Descs [0x1dc4, 0x2462): File Offsets [0x1222d1b, 0x14ba138) 0x29741d bytes across 1694 pages as ZLIB
    PFNs [0x56542, 0x56543) -> Descs [0x2462, 0x2463): File Offsets [0x306430, 0x307430) 0x1000 bytes across 1 pages as Uncompressed
    PFNs [0x56543, 0x56544) -> Descs [0x2463, 0x2464): File Offsets [0x14ba138, 0x14ba194) 0x5c bytes across 1 pages as ZLIB
    PFNs [0x56544, 0x5654f) -> Descs [0x2464, 0x246f): File Offsets [0x306430, 0x307430) 0x1000 bytes across 11 duplicate pages as Uncompressed

!kdumppagerange 的输出显示各种页面帧 (PFN) 值。 我们可以选择感兴趣的一个,并使用该 !kdumppfn <PFN> 信息显示有关 PFN 及其数据在 KDUMP 中的位置的信息。

0: kd> !kdumppfn 0x540e0
    Page frame 0x540e0 = File offset [0x307430, 0x307b9f) 0x76f bytes as ZLIB...

检查转储文件

k使用命令显示调用堆栈,调查发生崩溃时正在运行的代码。

6: kd> k
 # Child-SP          RetAddr               Call Site
00 ffff0000`0bc3bc90 ffff0000`085161f8     vmlinux!sysrq_handle_crash+0x24 [/usr/src/kernel/drivers/tty\sysrq.c @ 147] 
01 ffff0000`0bc3bca0 ffff0000`08516824     vmlinux!__handle_sysrq+0x88 [/usr/src/kernel/drivers/tty\sysrq.c @ 583] 
02 ffff0000`0bc3bcb0 ffff0000`08308990     vmlinux!write_sysrq_trigger+0xb4 [/usr/src/kernel/drivers/tty\sysrq.c @ 1110] 
03 ffff0000`0bc3bcf0 ffff0000`08290070     vmlinux!proc_reg_write+0x80 [/usr/src/kernel/fs/proc\inode.c @ 245] 
04 ffff0000`0bc3bd10 ffff0000`0829039c     vmlinux!__vfs_write+0x60 [/usr/src/kernel/fs\read_write.c @ 490] 
05 ffff0000`0bc3bd50 ffff0000`08290704     vmlinux!vfs_write+0xac [/usr/src/kernel/fs\read_write.c @ 550] 
06 ffff0000`0bc3be00 ffff0000`082907a4     vmlinux!ksys_write+0x74 [/usr/src/kernel/fs\read_write.c @ 599] 
07 (Inline Function) --------`--------     vmlinux!__do_sys_write+0xc [/usr/src/kernel/fs\read_write.c @ 608] 
08 (Inline Function) --------`--------     vmlinux!__se_sys_write+0xc [/usr/src/kernel/fs\read_write.c @ 608] 
09 ffff0000`0bc3be40 ffff0000`08095904     vmlinux!__arm64_sys_write+0x24 [/usr/src/kernel/fs\read_write.c @ 608] 
0a ffff0000`0bc3be90 ffff0000`080834c8     vmlinux!el0_svc_handler+0x94
0b ffff0000`0bc3beb0 00000000`00000000     vmlinux!el0_svc+0x8

dx使用命令检查转储文件。 例如,使用此命令查看前 30 个进程。

6: kd> dx @$cursession.Processes.Take(30)
@$cursession.Processes.Take(30)                
    [0x0]            : swapper/0 [Switch To]
    [0x1]            : systemd [Switch To]
    [0x2]            : kthreadd [Switch To]
    [0x3]            : rcu_gp [Switch To]
    [0x4]            : rcu_par_gp [Switch To]
    [0x5]            : kworker/0:0 [Switch To]
    [0x6]            : kworker/0:0H [Switch To]
    [0x7]            : kworker/u16:0 [Switch To]
    [0x8]            : mm_percpu_wq [Switch To]
    [0x9]            : ksoftirqd/0 [Switch To]
    [0xa]            : rcu_sched [Switch To]
    [0xb]            : rcu_bh [Switch To]
    [0xc]            : migration/0 [Switch To]
...

单击 DML 链接或使用类似于此链接的命令查看感兴趣的进程的线程。

6: kd> dx @$cursession.Processes[0x1a].Threads
@$cursession.Processes[0x1a].Threads                
    [0x1a]           [Switch To]
6: kd> dx @$cursession.Processes[0x1a].Threads[0x1a]
@$cursession.Processes[0x1a].Threads[0x1a]                 [Switch To]
    KernelObject     [Type: thread_struct]
    Id               : 0x1a
    Stack           
    Registers       
    Environment     
    Analysis        
    WaitChain       
    Scheduling      
    IRPs            
...

提供了每个线程的其他信息,如下所示。

6: kd> dx @$cursession.Processes[0x1a].Threads[0x1a].KernelObject
@$cursession.Processes[0x1a].Threads[0x1a].KernelObject                 [Type: thread_struct]
    [+0x000] cpu_context      [Type: cpu_context]
    [+0x070] uw               [Type: <unnamed-tag>]
    [+0x290] fpsimd_cpu       : 0x100 [Type: unsigned int]
    [+0x298] sve_state        : 0x0 [Type: void *]
    [+0x2a0] sve_vl           : 0x0 [Type: unsigned int]
    [+0x2a4] sve_vl_onexec    : 0x0 [Type: unsigned int]
    [+0x2a8] fault_address    : 0x0 [Type: long unsigned int]
    [+0x2b0] fault_code       : 0x0 [Type: long unsigned int]
    [+0x2b8] debug            [Type: debug_info]
6: kd> dx -s @$cursession.Processes[0x1a].Threads[0x1a].SwitchTo()
Process ffff8008`0f894380 has invalid page directories

使用 LinuxKernel.js 脚本分析 Linux 内核转储

LinuxKernel.js调试器扩展包含一组命令,旨在与 Linux 崩溃实用工具中用于打开和分析 Linux 内核模式崩溃的命令类似。

若要使用该脚本,请先加载该脚本。

0: kd> .scriptload LinuxKernel.js
JavaScript script successfully loaded from 'C:\Users\Bob\AppData\Local\dbg\UI\Fast.20240423.1\amd64\winext\LinuxKernel.js'

有关使用加载脚本的详细信息,请参阅 JavaScript 调试器脚本。

!文件

使用转 !files 储文件中显示有关 Linux 文件结构的信息。 它类似于崩溃文件命令。

6: kd> !files
@$files()                 : Files for process 'sh' (pid 545) root dir = '/' working dir = '/home/root'
    [0x0]            : /dev/ttyS0 [Type: file]
    [0x1]            : /proc/sysrq-trigger [Type: file]
    [0x2]            : /dev/ttyS0 [Type: file]
    [0xa]            : /dev/ttyS0 [Type: file]
    [0xff]           : /dev/ttyS0 [Type: file]

!files 语法:

!files [<arg>]

没有 [<arg>]- 等效于“文件”- 提供当前进程文件列表

[<arg>]:

pid - 为给定进程 ID 提供文件列表

64-bit num - 为给定地址的任务提供文件列表

<task struct [*]> - 按对象为给定任务结构提供文件列表

<process object> - 为进程对象表示的任务提供文件列表

!安装

使用转 !mount 储文件中显示有关 Linux 文件结构的信息。

6: kd> !mount
@$mount()                
    [0x0]            : (rootfs) rootfs at / [Type: mount]
    [0x1]            : (squashfs) /dev/mapper/nested_rootfs at / [Type: mount]
    [0x2]            : (sysfs) sysfs at /sys [Type: mount]
    [0x3]            : (proc) proc at /proc [Type: mount]
    [0x4]            : (devtmpfs) devtmpfs at /dev [Type: mount]
    [0x5]            : (securityfs) securityfs at /kernel/security [Type: mount]

!mount 语法:

没有 [<arg>]- 等效于“mount”命令 - 显示装载的文件系统

[<arg>]:

pid - 为具有给定 pid 的进程命名空间提供装载的文件系统

64-bit num - 为地址提供的task_struct命名空间提供装载的文件系统

<task struct [*]> - 为给定task_struct的命名空间提供装载的文件系统

<process object> - 为进程表示的任务命名空间提供装载的文件系统

!网

使用 “ !net 显示系统网络”列表。

6: kd> !net
@$net()                
    [0x0]            : lo (127.0.0.1) [Type: net_device]
    [0x1]            : enP8p1s0f0np0 (192.168.3.19) [Type: net_device]
    [0x2]            : enP8p1s0f1np0 [Type: net_device]

!net 语法:

!net [<arg>]

没有 [<arg>]- 等效于“net”- 提供系统网络列表

[<arg>]:

pid - 为具有给定 pid 的进程命名空间提供净列表

64-bit num - 为地址提供的task_struct命名空间提供净列表

<task struct [*]> - 为给定task_struct的命名空间提供净列表

<process object> - 为进程表示的任务命名空间提供网络列表

!runq

!runq使用该命令显示有关运行队列中任务的信息。

0: kd> !runq
@$runq()                
    [0x0]            : CPU 0 run queue [current = 'bash' (17ca)]
        Cpu              : 0x0
        RunQueue         [Type: rq]
        CurrentTask      : bash [Type: task_struct]
        RTTasks         
        CfsTasks        
            [0x16b3]         : kworker/0:7 [Type: task_struct]
    [0x1]            : CPU 1 run queue [current = 'swapper/1' (0)]
        Cpu              : 0x1
        RunQueue         [Type: rq]
        CurrentTask      : swapper/1 [Type: task_struct]
        RTTasks         
        CfsTasks   

!runq 语法:

!runq

!runq 没有任何命令参数。

其他内核转储命令

!dev - 显示有关字符和块设备、分配、I/O 端口使用情况、I/O 内存使用情况的设备数据。

!log - 显示内核log_buf内容。

!vm - 显示虚拟内存使用情况的摘要。

!timer - 显示计时器队列条目。

dx 命令和 Linux 对象

dx 命令可用于调查 kdumps。 显示 Sessions 对象以查看可用的各种子对象。

0: kd> dx -r3 Debugger.Sessions[0]
Debugger.Sessions[0]                 : Target Composition Target
    Processes       
        [0x0]            : swapper/0 [Switch To]
            KernelObject     : swapper/0 [Type: task_struct]
            Name             : swapper/0
            Id               : 0x0
            Index            : 0x0
            Threads         
            Modules         
            Environment     
            Direct3D        
            Attributes      
            Devices         
            Io              
            Memory          
            GroupedStacks   
...

cursession Kernel 对象包含可用于查看内核日志的 PrintKLog 对象。

6: kd> dx @$cursession.Kernel.PrintKLog.Take(4)
@$cursession.Kernel.PrintKLog.Take(4)                
    [0x0]            : [     0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd083]
    [0x1]            : [     0.000000] Linux version 4.19.90-microsoft-standard (oe-user@oe-host) (gcc version 8.2.0 (GCC)) #1 SMP Fri Mar 27 14:25:24 UTC 2020..
    [0x2]            : [     0.000002] sched_clock: 64 bits at 125MHz, resolution 8ns, wraps every 4398046511100ns
    [0x3]            : [     0.000003]         17.250901928 MSFT: kernel boot start

此 dx 命令显示用于 .Contains() 在日志中查找特定字符串。

6: kd> dx @$cursession.Kernel.PrintKLog.Where(le => le.ToLower().Contains("oops") || le.ToLower().Contains("crash"))
@$cursession.Kernel.PrintKLog.Where(le => le.ToLower().Contains("oops") || le.ToLower().Contains("crash"))                
    [0x0]            : [     0.000493] crashkernel reserved: 0x00000000dc600000 - 0x00000000fc600000 (512 MB)
    [0x1]            : [     0.078790] Kernel command line: console=ttyS0,115200n8 earlycon=uart8250,mmio32,0x68A10000 crashkernel=512M enforcing=0 ipe.enforce=0
    [0x2]            : [    26.621228] sysrq: SysRq : Trigger a crash
    [0x3]            : [    26.621254] Internal error: Oops: 96000044 [#1] SMP
    [0x4]            : [    26.656655] pc : sysrq_handle_crash+0x24/0x30
    [0x5]            : [    26.753494]  sysrq_handle_crash+0x24/0x30
    [0x6]            : [    26.801441] Starting crashdump kernel...8J»=.

用于 .Reverse() 显示记录的最后一个事件。

2: kd> dx @$cursession.Kernel.PrintKLog.Reverse().Take(5).Reverse()
@$cursession.Kernel.PrintKLog.Reverse().Take(5).Reverse()
   [0x0]           : [3147944.378367]  kthread+0x118/0x2a4
   [0x1]           : [3147944.381876]  ret_from_fork+0x10/0x18
   [0x2]           : [3147944.385747] Code: 78002507 36000042 39000107 d65f03c0 (cb0803e4)
   [0x3]           : [3147944.392221] SMP: stopping secondary CPUs
   [0x4]           : [3147944.397539] Starting crashdump kernel...

有关将 LINQ 查询与 dx 命令配合使用的详细信息,请参阅 将 LINQ 与调试器对象配合使用。

Linux 诊断扩展 - ELFBinComposition.dll

ELFBinComposition.dll中提供了以下 Linux 转储文件诊断扩展。

转储文件命令

这些命令可用于大多数转储文件。

!dumpdebug - 显示正在调试的核心转储的诊断。 这包括各种其他命令的输出。

!ntprstatus - 显示正在调试的核心转储中的NT_PRSTATUS记录。

!vmcoreinfo - 显示正在调试的内核核心转储(KDUMP)中的 VMCOREINFO 表。

ELF 转储命令

这些命令只能用于 ELF 核心转储文件。

!corephdrs - 显示正在调试的核心转储的程序标头表。

!ntprpsinfo - 显示正在调试的核心转储中的NT_PRPSINFO数据。

!ntfile - 显示正在调试的核心转储中的NT_FILE数据。

!ntauxv - 显示正在调试的核心转储中的NT_AUXV数据。

内核故障转储文件命令

这些命令只能在内核核心转储 (KDUMP) 文件上使用。

!kdumpdescs - 在 KDUMP 中显示页面范围和页面描述符的列表。

!kdumppagerange <n> - 显示 KDUMP 中第 n 个页面分组的信息。

!kdumppfn <pfn> - 显示有关页面框架 <pfn> 及其数据在 KDUMP 中的位置的信息。

其他诊断命令

!cppex - 使用 libstdc++的内部结构和 DWARF 符号显示有关当前正在进行的(未捕获和“just”捕获)C++异常的信息。

!cppfilt [-n] <mangled name> - 将一个C++混乱的名称解开,就好像它通过 c++filt 工具运行一样。 有关 C==filtr 工具的详细信息,请参阅 c++filt(1) — Linux 手册页

!rustdemangle <mangled name> - 解开 Rust 混乱的名称。 有关 rust 符号名称混乱的详细信息,请参阅 Rust 符号管理 - RFC 2603

另请参阅

Linux 符号和源

Linux 实时远程进程调试