# 使用 Kdb/Kgdb 调试内核

## Kdb/Kgdb 概述

Kdb 是 Linux 内核的调试工具，旨在帮助开发者在没有完整操作系统的情况下，直接在内核模式下进行调试。它通常用于处理内核崩溃后的情况，或是内核运行时出现问题时进行调试。下面是 Kdb 的发展历史：

- 2001年：Kdb 的初步版本由 Kurt Garloff 开发。Kdb 是为 Linux 内核提供的一种简单的内核调试工具。它的设计目标是提供一种不依赖于外部系统的调试方法，能够直接在控制台上与内核交互。
- 2000年代初期：Kdb 成为 Linux 内核开发者调试的一个重要工具，它可以在系统崩溃或内核问题发生时帮助开发者诊断和修复问题。Kdb 运行在内核模式下，因此即使操作系统崩溃或停止响应，开发者仍能通过串口或控制台进行调试。
- 2000年代中期：随着内核功能的不断增加，Kdb 开始集成到更多的内核版本中。它可以在内核启动时启用，提供更强大的调试支持。
- 目前：Kdb 依然是内核开发中常用的工具，特别是在低级故障排查和崩溃后分析中。它通常用于更简单、即时的内核调试，但由于功能上比 GDB 更为简单，开发者往往还需要配合其他工具来进行更复杂的调试。

Kgdb 旨在用作 Linux 内核的源代码级调试器。它与 gdb 一起用于调试 Linux 内核。期望 gdb 可用于“侵入”内核以检查内存，变量并查看调用堆栈信息，类似于应用程序开发人员使用 gdb 调试应用程序的方式。可以在内核代码中放置断点并执行一些有限的执行步骤。下面是 Kgdb 的发展历史：

- 2001年：KGDB 的初步工作由 Jason Wessel 提出和实现。KGDB 是基于 GDB 实现的，它通过串行端口、以太网或其他通信接口与目标内核进行通信，使得开发者可以像调试用户空间程序一样调试内核。
- 2002年：KGDB 在 Linux 2.6 内核中开始引起广泛关注。它使得开发者能够在用户空间使用 GDB 调试内核空间代码，极大提高了调试的灵活性。与 KDB 相比，KGDB 支持更复杂的调试操作，如设置断点、单步执行等，类似于调试用户空间程序的方式。
- 2000年代后期：KGDB 支持的功能逐渐增多，包括支持多种硬件平台（如 x86、ARM 等）和更高效的远程调试功能。
- 2010年代：KGDB 与其他调试工具（如 QEMU 等）结合使用，支持通过虚拟化平台进行内核调试。它的调试方式更加灵活，可以使用远程调试和硬件仿真工具进行更复杂的调试。
- 目前：KGDB 继续得到内核开发者和调试人员的使用，尤其是在内核开发过程中，它与 GDB 和 KDB 配合使用，提供了强大的调试能力。虽然 KGDB 配置较为复杂，但它仍然是 Linux 内核开发者进行内核级别调试的首选工具之一。

## Kdb/kgdb 功能介绍

### Kdb 功能介绍

Kdb 是 Linux 内核内建的调试器，允许开发人员在内核运行时进行调试，通常用于 低级调试，例如崩溃分析、内存检查、查看内核状态等。

**Kdb 的功能与特点：**

1. **内核模式调试**：
KDB 直接运行在内核模式下，不需要外部调试工具或环境。它嵌入在内核中，因此在内核崩溃时，开发者仍然可以通过控制台、串口等与内核交互并进行调试。

2. **触发式调试**：
KDB 可以在内核发生特定事件时自动启动，例如系统崩溃、异常或错误检测时。开发者可以设置断点，查看特定条件下的内核状态。

3. **实时调试**：
KDB 不依赖外部硬件或调试器，开发者可以实时与内核交互，检查内核变量、堆栈、内存等。

4. **支持多种接口**：
KDB 支持通过控制台、串口、甚至直接从调试命令行访问和调试内核，这在没有完整图形界面的环境下非常有用，尤其是嵌入式开发。

5. **调试内核数据结构**：
KDB 可以直接访问和查看内核数据结构，如进程调度、内存管理、文件系统等，有助于发现底层问题。

6. **独立于外部工具**：
与 GDB 等外部工具不同，KDB 不需要额外配置，它是内核的一部分，适合用于嵌入式系统或无法连接外部调试工具的场合。

**Kdb 的主要用途：**

- 内核崩溃时的调试：当内核发生崩溃时，KDB 可以自动触发并启动调试会话，开发者可以查看崩溃现场，检查内存、寄存器、调用栈等。
- 低级调试：KDB 能直接访问内核数据结构，适合用于低级调试，特别是在无法使用外部调试器时。
- 实时系统调试：在实时操作系统中，KDB 能即时响应系统状态并进行调试，帮助快速定位问题。

### Kgdb 功能介绍

Kgdb 是一个让开发者能够通过 GDB 来调试内核代码的工具。它允许使用 GDB 对内核进行调试，特别是当内核运行在某个目标设备上时，开发者可以通过串口或网络与目标设备进行调试。Kgdb 本质上是内核对 GDB 的支持，是 GDB 和内核之间的一个桥梁。

**Kgdb 的功能与特点**：

1. **通过 GDB 调试内核**：
   - Kgdb 允许开发者在用户空间使用 GDB 调试内核代码。这意味着你可以使用 GDB 提供的强大调试功能（如断点、单步执行、堆栈跟踪等）来调试内核代码。

2. **与 GDB 的集成**：
   - Kgdb 与 GDB 集成，通过串口、网络或其他通信方式将调试会话与内核调试目标连接起来。用户可以使用 GDB 的命令在内核上设置断点、单步执行、查看变量等。

3. **远程调试**：
   - Kgdb 允许远程调试内核。内核通过串口、网络等通道与 GDB 主机进行通信，这对于远程调试硬件设备上的内核非常有用。

4. **支持多种调试功能**：
   - 使用 GDB 时，开发者可以设置断点、单步执行、检查内存、查看寄存器内容、调试内核模块等。GDB 提供了非常强大的调试功能，可以轻松进行复杂的内核调试。

5. **调试内核崩溃**：
   - Kgdb 也可以用于内核崩溃的调试。开发者可以在崩溃时通过 GDB 进行远程调试，检查崩溃现场、查看调用栈、打印内存内容等。

6. **与 KDB 配合使用**：
   - Kgdb 和 KDB 并不是互相排斥的，实际上，它们可以一起使用。KDB 允许开发者在不依赖外部工具的情况下进行内核调试，而 Kgdb 允许通过 GDB 进行更详细和复杂的调试。

**Kgdb 的主要用途**：

- **远程调试**：通过串口、以太网等通信方式，Kgdb 可以用于远程调试嵌入式设备或其他目标机器上的内核。这对于开发和维护嵌入式系统或其他特殊硬件平台非常有帮助。
- **复杂内核调试**：当内核代码需要进行复杂的调试时，开发者可以利用 GDB 的强大功能，如多线程调试、内存分析等，来定位和解决问题。
- **内核模块调试**：开发者可以使用 GDB 调试内核模块，分析模块加载、执行过程中的问题。

### Kdb 与 Kgdb 对比

| 特性/功能         | KDB                                | KGDB                                |
|------------------|------------------------------------|-------------------------------------|
| **调试方式**      | 内核内建的调试工具，直接在内核运行时交互 | 通过 GDB 外部调试器与内核进行调试，通常使用串口或网络连接 |
| **使用场景**      | 适用于简单、快速的内核调试，尤其在系统崩溃时启动调试 | 适用于复杂的内核调试，特别是远程调试或需要 GDB 功能时 |
| **调试功能**      | 提供基本的调试命令，如查看堆栈、寄存器、内存等 | 提供 GDB 的全部调试功能，如断点、单步执行、内存分析等 |
| **调试复杂度**    | 功能较简单，适合低级调试，定位基本问题 | 功能强大，适合进行复杂调试任务 |
| **调试设备**      | 无需外部设备，仅通过控制台、串口等与内核交互 | 依赖 GDB 和外部通信设备（串口、网络等） |
| **调试实时性**    | 提供即时调试，尤其在系统崩溃时快速响应 | 由于依赖外部调试器，可能会稍有延迟 |
| **适用性**        | 适用于没有外部调试工具或硬件的环境，如嵌入式设备 | 适用于需要强大调试功能和远程调试的环境 |
| **远程调试支持**  | 不支持远程调试 | 支持远程调试，可以通过串口、网络进行连接 |
| **与 KDB 配合使用** | 可与 KGDB 配合使用，进行简单调试 | 可与 KDB 配合使用，进行更复杂调试 |

## Kdb/Kgdb 具体使用方法

### 开启 kdb/kgdb

X5 内核默认并不支持 Kdb/kgdb，需要对内核做一些修改。

执行 `./bd.sh boot menuconfig`，将 kgdb 相关配置项修改为如下状态：

```Shell
CONFIG_KGDB=y
CONFIG_KGDB_SERIAL_CONSOLE=y
CONFIG_KGDB_KDB=y
CONFIG_KDB_DEFAULT_ENABLE=0x1
```

修改保存后，可以打开 `kernel/arch/arm64/configs/hobot_x5_soc_defconfig` 确保 kgdb 相关的配置项已经正确被配置。

### 板端启动 kdb 调试

板端启动 kdb 调试有两种方式，可以选择在 Uboot 阶段配置启动，也可以在进入内核后再启动。

#### Uboot 阶段启动 kdb

在 UBoot 内通过修改并储存 bootargs 修改内核的 command line 选项，加入（如使用 ttyS0）后启动：

```shell
Hobot# setenv bootargs kgdboc=ttyS0,115200  kgdbwait
Hobot# run bootcmd
```

等待内核启动后，会打印下面日志提示进入 kgdb：

```Shell

Starting kernel ...

[    0.000000] Linux version 6.1.83-DR-PL5.1_V1.0.14 (sxq@DESKTOP-6VORLA0) (aarch64-none-linux-gnu-gcc (Arm GNU Toolchain 11.3.Rel1) 11.3.1 20220712, GNU ld (Arm GNU Toolchain 11.3.Rel1) 2.38.20220708) #1 SMP PREEMPT Wed Dec  4 20:10:42 CST 2024
[    0.000000] Kernel command line: console=ttyS0,115200n8 root=/dev/mmcblk0p9 ro rootwait hobotboot.slot_suffix=_a hobotboot.reason=COLD_BOOT hobotboot.medium=MMC hobotboot.mode=normal hobotboot.ab_switch_reason=normal hobotboot.pmic_type=single-pmic    kgdboc=ttyS0,115200 kgdbwait
[    0.111978] audit: type=2000 audit(0.090:1): state=initialized audit_enabled=0 res=1
[    0.144479] (NULL device *): no horizon,gpio-banks in node /soc/disp_apb/disp_iomuxc@3e0a0054
[    0.182704] SCSI subsystem initialized
[    0.262379] Initialise system trusted keyrings
[    0.294398] Key type asymmetric registered
[    0.294409] Asymmetric key parser 'x509' registered
[    0.393114] KGDB: Waiting for connection from remote gdb...

Entering kdb (current=0xffff0000058a0000, pid 1) on processor 7 due to Keyboard Entry
[7]kdb>
```

#### 内核启动后启动 kdb

在进入内核后再启动 kgdb 的方式如下：

```SHell
# 先卸载 watchdog 驱动（如果存在）
rmmod hobot_watchdog
echo ttyS0 > /sys/module/kgdboc/parameters/kgdboc
echo g > /proc/sysrq-trigger
```

日志如下：

```Shell
root@buildroot:~# echo ttyS0 > /sys/module/kgdboc/parameters/kgdboc
root@buildroot:~# echo g > /proc/sysrq-trigger

Entering kdb (current=0xffff0000cca42b80, pid 1003) on processor 4 due to Keyboard Entry
[4]kdb>
```

<font color=red>注意：</font>
在 X5 BSP 的 debug 版本中，Watchdog 设备默认被注册，但是看门狗计时器并没有使能，所以不需要执行卸载 Watchdog 操作。

### Kdb 调试命令介绍

在 Kdb 命令终端中输入 `help` 命令即可显示出 Kdb 的命令列表：

```Shell
[7]kdb> help
Command         Usage                Description
----------------------------------------------------------
md              <vaddr>             Display Memory Contents, also mdWcN, e.g. md8c1
mdr             <vaddr> <bytes>     Display Raw Memory
mdp             <paddr> <bytes>     Display Physical Memory
mds             <vaddr>             Display Memory Symbolically
mm              <vaddr> <contents>  Modify Memory Contents
go              [<vaddr>]           Continue Execution
rd                                  Display Registers
rm              <reg> <contents>    Modify Registers
ef              <vaddr>             Display exception frame
bt              [<vaddr>]           Stack traceback
btp             <pid>               Display stack for process <pid>
bta             [<state_chars>|A]   Backtrace all processes whose state matches
btc                                 Backtrace current process on each cpu
btt             <vaddr>             Backtrace process given its struct task address
env                                 Show environment variables
set                                 Set environment variables
help                                Display Help Message
?                                   Display Help Message
cpu             <cpunum>            Switch to new cpu
kgdb                                Enter kgdb mode
ps              [<state_chars>|A]   Display active task list
pid             <pidnum>            Switch to another task
reboot                              Reboot the machine immediately
lsmod                               List loaded kernel modules
sr              <key>               Magic SysRq key
dmesg           [lines]             Display syslog buffer
defcmd          name "usage" "help" Define a set of commands, down to endefcmd
kill            <-signal> <pid>     Send a signal to a process
summary                             Summarize the system
per_cpu         <sym> [<bytes>] [<cpu>]
                                    Display per_cpu variables
grephelp                            Display help on | grep
bp              [<vaddr>]           Set/Display breakpoints
bl              [<vaddr>]           Display breakpoints
bc              <bpnum>             Clear Breakpoint
be              <bpnum>             Enable Breakpoint
bd              <bpnum>             Disable Breakpoint
ss                                  Single Step
dumpcommon                          Common kdb debugging
dumpall                             First line debugging
dumpcpu                             Same as dumpall but only tasks on cpus
ftdump          [skip#entries] [cpu]
                                    Dump ftrace log; -skip dumps last #entries
```

下面简单介绍这些命令：

- **内存相关命令**

| **命令** | **参数**               | **描述**                                                                                   |
|----------|------------------------|--------------------------------------------------------------------------------------------|
| `md`     | `<vaddr>`              | 显示内存内容，`<vaddr>` 为虚拟地址，支持 `WcN` 参数来控制显示格式和块大小（例如 `md8c1`）。        |
| `mdr`    | `<vaddr> <bytes>`      | 以原始格式显示从 `<vaddr>` 地址开始的 `<bytes>` 字节内存。                                     |
| `mdp`    | `<paddr> <bytes>`      | 显示物理内存内容，从 `<paddr>` 地址开始显示指定字节数。                                      |
| `mds`    | `<vaddr>`              | 符号化显示从虚拟地址 `<vaddr>` 开始的内存内容。                                              |
| `mm`     | `<vaddr> <contents>`    | 修改内存内容，将虚拟地址 `<vaddr>` 处的内存修改为指定的内容 `<contents>`。                     |

- **执行控制命令**

| **命令** | **参数**               | **描述**                                                                                   |
|----------|------------------------|--------------------------------------------------------------------------------------------|
| `go`     | `[<vaddr>]`            | 继续程序执行。如果指定了虚拟地址 `<vaddr>`，则从该地址开始执行。也可以用来退出 kdb 界面回到内核命令行状态。 |
| `bt`     | `[<vaddr>]`            | 显示栈回溯。可以指定 `<vaddr>` 作为起始地址。                                                |
| `bta`    | `[<state_chars>\|A]`    | 回溯所有进程的栈，按进程状态 `<state_chars>` 过滤，`A` 表示所有进程。                        |
| `btc`    |                        | 回溯当前进程在所有CPU上的栈。                                                               |
| `btt`    | `<vaddr>`              | 从指定的结构体地址 `<vaddr>` 开始回溯进程的栈。                                              |
| `ss`     |                        | 进行单步调试。                                                                                |
| `kill`   | `<-signal> <pid>`      | 向指定进程发送信号，`<signal>` 是信号类型，`<pid>` 是进程ID。                                 |
| `pid`    | `<pidnum>`             | 切换到指定的进程ID（`pidnum`）进行调试。                                                     |
| `sr`     | `<key>`                | 触发魔术SysRq键，通常用于紧急操作，如强制重启等内核级操作。                                   |

- **寄存器相关命令**

| **命令** | **参数**               | **描述**                                                                                   |
|----------|------------------------|--------------------------------------------------------------------------------------------|
| `rd`     |                        | 显示当前CPU的寄存器内容。                                                                   |
| `rm`     | `<reg> <contents>`      | 修改寄存器的内容，`<reg>` 为寄存器名称，`<contents>` 为新的值。                              |

- **环境变量命令**

| **命令** | **参数**               | **描述**                                                                                   |
|----------|------------------------|--------------------------------------------------------------------------------------------|
| `env`    |                        | 显示当前的环境变量。                                                                         |
| `set`    |                        | 设置环境变量的值。                                                                           |

- **进程相关命令**

| **命令** | **参数**               | **描述**                                                                                   |
|----------|------------------------|--------------------------------------------------------------------------------------------|
| `ps`     | `[<state_chars>\|A]`     | 显示当前活动任务列表，可以按进程状态 `<state_chars>` 过滤，`A` 表示所有任务。               |
| `lsmod`  |                        | 列出当前加载的内核模块。                                                                   |
| `pid`    | `<pidnum>`             | 切换到指定的进程ID（`pidnum`）进行调试。                                                    |
| `btp`    | `<pid>`                | 显示指定进程ID (`pid`) 的栈信息。                                                           |

- **内核调试命令**

| **命令**  | **参数**                | **描述**                                                                                   |
|-----------|-------------------------|--------------------------------------------------------------------------------------------|
| `dmesg`   | `[lines]`               | 显示内核日志缓冲区的内容，可以指定显示的行数 `lines`。                                       |
| `dumpcommon` |                    | 执行通用的内核调试转储。                                                                     |
| `dumpall` |                         | 执行完整的内存转储调试。                                                                     |
| `dumpcpu` |                         | 仅转储CPU上的任务相关信息。                                                                 |~

- **自定义命令与帮助命令**

| **命令**     | **参数**                | **描述**                                                                                   |
|--------------|-------------------------|--------------------------------------------------------------------------------------------|
| `defcmd`     | `name "usage" "help"`    | 定义一组自定义命令，包含用法说明和帮助文档。                                               |
| `grephelp`   |                         | 显示帮助信息，可以通过管道（`\|`）进行筛选。                                                 |

- **其他命令**

| **命令**   | **参数**                | **描述**                                                                                   |
|------------|-------------------------|--------------------------------------------------------------------------------------------|
| `kgdb`     |                         | 进入KGDB模式，进行低层次的调试。                                                            |
| `summary`  |                         | 显示系统的简要总结信息。                                                                     |
| `per_cpu`  | `<sym> [<bytes>] [<cpu>]`| 显示某个符号（`<sym>`）的每个CPU相关的变量，可以指定字节数 `<bytes>` 和CPU `<cpu>`。      |
| `bl`       |                         | 显示当前的断点信息。                                                                         |
| `bp`       | `<vaddr>`               | 设置断点，在指定虚拟地址处停止执行。                                                       |
| `bc`       | `<bpnum>`               | 清除指定的断点。                                                                             |
| `be`       | `<bpnum>`               | 启用指定的断点。                                                                             |
| `bd`       | `<bpnum>`               | 禁用指定的断点。                                                                             |

下面是一些 Kdb 命令的执行日志：

```Shell
# 显示栈回溯
[7]kdb> bt
Stack traceback for pid 999
0xffff0000c60f0000      999        1  1    7   R  0xffff0000c60f09f0 *bash
CPU: 7 PID: 999 Comm: bash Tainted: P         C O       6.1.83-DR-PL5.1_V1.0.14 #11
Hardware name: D-Robotics X5 EVB LP4 1_B board (DT)
Call trace:
 dump_backtrace+0xd8/0x130
 show_stack+0x18/0x30
 dump_stack_lvl+0x68/0x84
 dump_stack+0x18/0x34
 kdb_dump_stack_on_cpu+0x88/0x90
 kdb_show_stack+0x90/0xa0
 kdb_bt1+0xc4/0x140
 kdb_bt+0x328/0x37c
 kdb_parse+0x2c4/0x63c
 kdb_main_loop+0x434/0x7b4
 kdb_stub+0x270/0x444
 kgdb_cpu_enter+0x168/0x66c
 kgdb_handle_exception+0xcc/0x120
 kgdb_compiled_brk_fn+0x28/0x40
 call_break_hook+0x68/0x7c
 brk_handler+0x1c/0x60

# 显示指定虚拟内存内容，如下是显示当前的内核完整版本字符串
[0]kdb> md linux_banner
0xffff800008baae48 65762078756e694c 2e36206e6f697372   Linux version 6.
0xffff800008baae58 2d52442d33382e31 31565f312e354c50   1.83-DR-PL5.1_V1
0xffff800008baae68 78732820302e312e 4f544b5345444071   .1.0 (sxq@DESKTO
0xffff800008baae78 414c524f56362d50 6372616128202930   P-6VORLA0) (aarc
0xffff800008baae88 656e6f6e2d343668 672d78756e696c2d   h64-none-linux-g
0xffff800008baae98 28206363672d756e 20554e47206d7241   nu-gcc (Arm GNU 
0xffff800008baaea8 696168636c6f6f54 522e332e3131206e   Toolchain 11.3.R
0xffff800008baaeb8 2e31312029316c65 3232303220312e33   el1) 11.3.1 2022

# 显示当前CPU的寄存器内容
[7]kdb> rd
x0: ffff800009268000  x1: 0000000000000001  x2: ffff800009268558
x3: 0000000000000000  x4: ffff0000ff746b60  x5: ffff0000ff746b60
x6: 0000000000000000  x7: ffff800009184748  x8: 00000000ffffefff
x9: ffff80000912c748  x10: ffff800009184748  x11: 00000000000002fa
x12: 00000000000008ee  x13: ffff80000912c748  x14: 0000000000000000
x15: fffffffffffed7d8  x16: 0000000000000000  x17: 0000000000000000
x18: 0000000000000018  x19: 0000000000000067  x20: ffff80000912c000
x21: ffff80000911a000  x22: 0000000000000006  x23: 0000000000000000
x24: 0000000000000000  x25: ffff800008af8f40  x26: 0000000000000000
x27: 0000000000000000  x28: ffff0000c60f0000  x29: ffff800019563c80
x30: ffff800008116184  sp: ffff800019563c80  pc: ffff8000081160ec
pstate: 60400009  v0: ??  v1: ??  v2: ??  v3: ??  v4: ??  v5: ??  v6: ??  v7: ??
v8: ??  v9: ??  v10: ??  v11: ??  v12: ??  v13: ??  v14: ??  v15: ??  v16: ??
v17: ??  v18: ??  v19: ??  v20: ??  v21: ??  v22: ??  v23: ??  v24: ??  v25: ??
v26: ??  v27: ??  v28: ??  v29: ??  v30: ??  v31: ??  fpsr: 00000000
fpcr: 00000000
```

### Kgdb 远程连接单板调试

板端进入 Kdb 操作界面后，可执行 `kgdb` 命令，等待主机 gdb 远程连接：

```Shell
kdb> kgdb
Entering please attach debugger or use $D#44+ or $3#33
```

在提示等待连接时，关闭串口终端（避免占用串口）。之后在主机上使用 X5 BSP 所使用的编译工具链 `opt/arm-gnu-toolchain-11.3.rel1-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-gdb`，加载内核 vmlinux（X5 BSP 源码中的路径是 out/build/kernel/vmlinux）。为了方便调用，建议在 `.bashrc` 中创建别名：

```Shell
alias arm_gdb='/opt/arm-gnu-toolchain-11.3.rel1-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-gdb'
```

然后，通过主机串口（如 /dev/ttyUSB0）连接目标机（若设备有权限要求，加 `sudo`）：

```Shell
arm_gdb out/build/kernel/vmlinux
(gdb) set serial baud 115200
(gdb) target remote /dev/ttyUSB0
```

连接上后，即可使用 gdb 命令进行调试。

关于 Kdb/Kgdb 的更多使用方法可以参考 [Using kgdb, kdb and the kernel debugger internals](https://www.kernel.org/doc/html/next/process/debugging/kgdb.html)。

## 常见问题

### Kdb 常见问题

1. **无法连接调试终端**：
如果 Kdb 是通过串口或其他终端设备与外部交互，设备配置不正确（例如波特率设置错误）可能导致无法连接。

2. **调试信息不全**：
Kdb 提供的调试信息相对较少，可能无法提供足够的上下文信息，尤其是复杂崩溃时。此时可能需要结合其他调试工具，如 kgdb 或 crash 工具。

3. **Kdb 无法响应输入**：
当系统崩溃或卡死时，Kdb 可能无法正常响应输入。可能是由于控制台或串口设备配置问题，或内核在崩溃前未能正确初始化调试端口。

### Kgdb 常见问题

1. **GDB 无法连接到内核**：
可能是因为内核没有正确配置以启用 Kgdb，或者外部设备（如串口或网络）连接不稳定。确保内核启用了 CONFIG_KGDB，并且通信端口和 GDB 配置正确。

2. **内核调试信息不完整**：
调试符号可能未包含在内核映像中，导致调试信息不足。需要确保内核配置了调试符号（如 CONFIG_DEBUG_INFO）。

3. **GDB 与内核版本不匹配**：
GDB 版本可能与内核的调试接口不兼容，导致调试时出现崩溃或连接问题。需要使用与内核版本匹配的 GDB。

4. **调试器与内核之间的通信延迟**：
Kgdb 通过串口或网络进行远程调试时，可能会遇到较大的延迟，尤其是在高负载系统中。调试过程中可能会出现响应缓慢或超时问题。