oops问题定位记录

文章目录

  • 一、前置条件:编译开启调试符号(-g)
    • [1.1 核心编译配置](#1.1 核心编译配置)
    • [1.2 编译产物要求](#1.2 编译产物要求)
  • [二、崩溃现场:提取 Oops 关键信息](#二、崩溃现场:提取 Oops 关键信息)
  • [三、核心工具 1:addr2line 地址转源码行](#三、核心工具 1:addr2line 地址转源码行)
    • [3.1 命令格式](#3.1 命令格式)
    • [3.2 实操示例](#3.2 实操示例)
    • [3.3 输出结果](#3.3 输出结果)
  • [四、兜底工具 2:objdump 反汇编验证](#四、兜底工具 2:objdump 反汇编验证)
    • [4.1 反汇编命令](#4.1 反汇编命令)
    • [4.2 查找崩溃位置](#4.2 查找崩溃位置)
  • 五、完整标准化流程(总结)
  • 六、常用命令速查表
  • 七、注意事项

一、前置条件:编译开启调试符号(-g)

1.1 核心编译配置

编译内核或内核模块时,必须添加 GCC 调试参数,生成符号表和行号信息:

makefile 复制代码
# Makefile 中添加编译参数
CFLAGS += -g    # 生成调试信息(必备)
CFLAGS += -O0   # 关闭编译器优化(推荐,避免行号错位)

1.2 编译产物要求

必须保留带调试符号的文件:

  • 内核:vmlinux(不可压缩的内核镜像,非bzImage)
  • 驱动模块:xxx.ko(未 strip 的原始模块)

二、崩溃现场:提取 Oops 关键信息

系统触发 Oops 后,从 dmesg / 串口日志中获取崩溃地址,核心关注 RIP 字段:

示例 Oops 日志

log 复制代码
RIP: 0010:test_func+0x28/0x80 [my_drv]

关键信息提取

字段 含义
test_func 崩溃函数名
0x28 函数内偏移量(核心)
0x80 函数总大小
my_drv 崩溃所在模块

三、核心工具 1:addr2line 地址转源码行

addr2line 是最快捷的定位工具,直接将偏移量转换为源码文件 + 行号。

3.1 命令格式

bash 复制代码
# 内核崩溃:使用 vmlinux
addr2line -e vmlinux [偏移地址]

# 模块崩溃:使用 xxx.ko
addr2line -e 模块名.ko [偏移地址]

3.2 实操示例

bash 复制代码
# 定位 my_drv.ko 中 相对 test_func(可以看objdump或者编译出的map文件)假如为 0xfffffe80 偏移 0x28 的代码
addr2line -e my_drv.ko 0xfffffe80 + 0x28

3.3 输出结果

plaintext 复制代码
/home/test/drv/my_drv.c:125

✅ 直接定位:my_drv.c 文件 第 125 行 为崩溃代码。

四、兜底工具 2:objdump 反汇编验证

当 addr2line 定位不准时,通过 objdump 反汇编,结合汇编 + 源码交叉验证。

4.1 反汇编命令

bash 复制代码
# 反汇编(带源码混合显示),输出到文件
objdump -dS my_drv.ko > drv_dump.txt
  • -d:反汇编代码段
  • -S:混合显示源码(依赖-g调试符号)

4.2 查找崩溃位置

  1. 打开 drv_dump.txt
  2. 搜索崩溃函数名(test_func)
  3. 找到偏移 0x28 对应的汇编 / 源码行
  4. 直接锁定崩溃逻辑

五、完整标准化流程(总结)

  1. 编译:内核 / 模块添加 -g -O0,保留调试符号;
  2. 抓日志:获取 Oops 日志,提取 函数+偏移量;
  3. 快速定位:使用 addr2line 直接映射源码行;
  4. 深度验证:使用 objdump 反汇编,确认汇编与源码对应关系;
  5. 修复问题:根据定位的代码行分析空指针、内存越界等崩溃根因。

六、常用命令速查表

操作场景 命令示例
模块地址转行号 addr2line -e test.ko 0x28
内核地址转行号 addr2line -e vmlinux 0xffffffff86123456
模块反汇编(带源码) objdump -dS test.ko > dump.log
查看 Oops 日志 `dmesg -T

七、注意事项

  • 必须使用未 strip 的 vmlinux/.ko 文件,strip 会删除调试符号;
  • 编译优化(-O1/-O2)会导致行号错乱,调试时建议用 -O0;
  • 偏移量直接使用 Oops 日志中的数值,无需额外计算
相关推荐
C^h2 小时前
RTthread中的内存池理解
linux·数据库·c++·算法·嵌入式
司南-70492 小时前
claude初探- 国内镜像安装linux版claude
linux·运维·服务器·人工智能·后端
为美好的生活献上中指2 小时前
*Java 沉淀重走长征路*之——《Linux 从入门到企业实战:一套六步法,带你打通运维与开发的任督二脉》
java·linux·运维·开发语言·阿里云·华为云·linux命令
the sun342 小时前
从Ubuntu迁移到QEMU驱动开发
linux·驱动开发·ubuntu
犽戾武2 小时前
机械臂 VR 遥操作调试日志记录
linux·服务器·网络
SPC的存折2 小时前
1、Ansible之Ansible安装与入门
linux·数据库·ansible
枳实-叶2 小时前
嵌入式 Linux 下 ALSA 音频采集与 PCM 播放流程详解
linux·音视频·pcm
桦02 小时前
【C复习】
c语言·开发语言
Magic--2 小时前
Linux静态库与共享库(动态库)详解
linux·运维·服务器