> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs-staging.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 内核调试器 (KGDB)

KGDB（Kernel GNU Debugger）为正在运行的 Qualcomm<sup>®</sup> Linux 内核
提供实时的源码级调试。运行 GDB 的主机通过串口连接到目标设备，可以设置
断点、检查寄存器并单步执行内核代码，包括动态加载的模块。

## **支持的目标平台**

KGDB 需要一个专用串口，且该串口不能与内核日志控制台共用。以下目标平台已在 Qualcomm Linux 上完成 KGDB 验证：

**表：各目标平台的 KGDB 支持情况**

| **SoC** | **开发套件**                                              | **KGDB I/O 端口** | **状态** |
| :------ | :---------------------------------------------------- | :-------------- | :----- |
| QCS6490 | Dragonwing<sup>™</sup> RB3 Gen 2 Core Development Kit | `ttyMSM0`       | 支持     |
| QCS5430 | Dragonwing<sup>™</sup> RB3 Gen 2 Core Development Kit | `ttyMSM0`       | 支持     |
| IQ-9075 | Dragonwing<sup>™</sup> IQ-9075 EVK                    | `ttyMSM0`       | 支持     |
| IQ-8275 | Dragonwing<sup>™</sup> IQ-8275 EVK                    | `ttyMSM0`       | 支持     |
| IQ-615  | Dragonwing<sup>™</sup> IQ-615                         | `ttyMSM0`       | 支持     |

<Note>
  在所有受支持的目标平台上，开发套件都通过调试接头将 `ttyMSM0` 作为 Qualcomm GENI UART 暴露出来。在开始会话之前，请先确认该端口在您的开发板上可用：

  ```bash theme={null}
  ls /dev/ttyMSM*
  dmesg | grep -i "ttyMSM.*enabled"
  ```
</Note>

## **所需的内核配置**

启用以下 Kconfig 选项并重新构建内核：

```text theme={null}
CONFIG_FRAME_POINTER=y
CONFIG_KGDB=y
CONFIG_KGDB_SERIAL_CONSOLE=y
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_CONSOLE_POLL=y
CONFIG_MAGIC_SYSRQ=y
```

在运行中的系统上验证：

```bash theme={null}
zcat /proc/config.gz | grep -E "CONFIG_KGDB|CONFIG_MAGIC_SYSRQ|CONFIG_FRAME_POINTER"
```

## **串口设置**

KGDB 使用 `kgdboc`（KGDB over console）驱动通过串口通信。

### 内核命令行参数

将以下内容添加到
`meta-qcom/conf/machine/include/qcom-<SoC>.conf` 中的
`KERNEL_CMDLINE_EXTRA`：

```text theme={null}
kgdboc=ttyMSM0,115200n8 kgdbwait nokaslr
```

| **参数**                    | **效果**                                                 |
| :------------------------ | :----------------------------------------------------- |
| `kgdboc=ttyMSM0,115200n8` | 将 `ttyMSM0` 以 115200 波特注册为 KGDB I/O 通道                 |
| `kgdbwait`                | 在启动期间暂停内核，等待 GDB 连接后再继续。如果您希望之后通过 SysRq 连接 GDB，可省略此参数。 |
| `nokaslr`                 | 禁用内核地址空间布局随机化。GDB 符号匹配需要此参数。                           |

### 禁用看门狗

如果内核停止响应，Qualcomm SoC 看门狗会重置设备。在开始 KGDB 会话前
禁用它，以防止意外重置：

```bash theme={null}
echo 1 > /sys/bus/platform/devices/hypervisor:qcom,gh-watchdog/disable
```

## **进入调试模式**

选择以下方法之一来暂停内核并激活 KGDB stub。

### 方法 1：kgdbwait（启动时）

当内核命令行中包含 `kgdbwait` 时，内核会在启动期间停止，并在串口
控制台上打印以下消息：

```text theme={null}
[    0.239669] printk: console [ttyMSM0] enabled
[    1.541411] KGDB: Registered I/O driver kgdboc
[    2.224804] KGDB: Waiting for connection from remote gdb...
```

在内核继续之前从主机连接 GDB。

### 方法 2：Magic SysRq（运行时）

在目标设备的 shell 中：

```bash theme={null}
echo g > /proc/sysrq-trigger
```

内核会立即挂起并等待 GDB。

### 方法 3：编译时断点

在驱动源码中插入硬断点：

```c theme={null}
#include <linux/kgdb.h>
kgdb_breakpoint();   /* kernel breaks here when this line is reached */
```

重新构建并烧写内核。当代码路径执行到该行时，断点会触发。

### 方法 4：内核 panic（异常驱动）

当发生未处理的异常或 panic 时，内核会自动进入 KGDB 模式。要为测试
故意触发一次崩溃：

```bash theme={null}
echo c > /proc/sysrq-trigger   # kernel panic → enters KGDB
```

## **从主机连接 GDB**

在主机上安装 `gdb-multiarch`：

```bash theme={null}
# Debian / Ubuntu
sudo apt install gdb-multiarch

# MSYS2 (Windows)
pacman -S mingw-w64-x86_64-gdb-multiarch
```

### Linux 主机

```bash theme={null}
gdb-multiarch -b 115200 <path_to_vmlinux>
(gdb) target remote /dev/ttyUSB0
```

### Windows 主机

在 Windows 上，请在设备管理器中将 COM 端口号设置为大于 16，并使用
`\\.\comN` 路径语法：

```text theme={null}
gdb-multiarch.exe -b 115200 <path_to_vmlinux>
(gdb) target remote \\.\com17
```

连接后的预期输出：

```text theme={null}
Remote debugging using \\.\com17
[Switching to Thread -2]
arch_kgdb_breakpoint () at arch/arm64/include/asm/kgdb.h:21
```

## **GDB 调试会话**

### 常用 GDB 命令

**表：GDB 命令参考**

| **命令**                | **描述**                        |
| :-------------------- | :---------------------------- |
| `bt`                  | 打印当前调用栈的回溯                    |
| `break <function>`    | 在函数入口处设置断点                    |
| `break <file>:<line>` | 在特定源码行设置断点                    |
| `info break`          | 列出当前所有断点                      |
| `info reg`            | 显示所有 CPU 寄存器                  |
| `x/<n>x <addr>`       | 以十六进制查看地址 `addr` 处的 `n` 个字的内存 |
| `p <expression>`      | 打印 C 表达式或变量的值                 |
| `s`                   | 单步执行一行源码（进入函数调用）              |
| `n`                   | 执行下一行源码（跳过函数调用）               |
| `c`                   | 继续执行直到下一个断点或中断                |
| `finish`              | 运行直到当前函数返回                    |
| `detach`              | 从目标分离（内核继续运行）                 |

### 加载模块符号

要调试动态加载的内核模块，请从目标设备获取 `.text` 段地址：

```bash theme={null}
# On the target device
cat /sys/module/<module_name>/sections/.text
# Example output: 0xffff800008800000
```

然后在 GDB 中加载符号文件：

```gdb theme={null}
(gdb) add-symbol-file <path_to_module.ko> 0xffff800008800000
```

示例：

```gdb theme={null}
(gdb) add-symbol-file drivers/net/ethernet/my_driver.ko 0xffff800008800000
(gdb) break my_driver_probe
(gdb) c
```

有关完整的上游 KGDB 文档，请参阅
[Debugging kernel and modules via gdb](https://docs.kernel.org/process/debugging/gdb-kernel-debugging.html)。
