0

0

Linux 内核调试:指令追踪大法

心靈之曲

心靈之曲

发布时间:2025-01-07 20:23:41

|

399人浏览过

|

来源于良许Linux教程网

转载

1. 错误异常

Linux 内核调试:指令追踪大法
  • epc : 0x802cb3bc
  • ra : 0x802cb3a8

2. 调试方法

2.1.反编译vmlinux

mips-linux-gnu-objdump -d vmlinux > dump.s

2.2. 打开dump.s,找到你要找的epc值

802cb3b4:       8e020004        lw      v0,4(s0)
802cb3b8:       24420800        addiu   v0,v0,2048
802cb3bc:       ac620000        sw      v0,0(v1)  # 这里是异常
802cb3c0:       0000000f        sync    
802cb3c4:       8e050588        lw      a1,1416(s0)
802cb3c8:       3c04804d        lui     a0,0x804d

.3. 向上找找这行指令在哪个函数?

802cb298 :
802cb298:       27bdffe0        addiu   sp,sp,-32
802cb29c:       afb10018        sw      s1,24(sp)
802cb2a0:       afb00014        sw      s0,20(sp)
802cb2a4:       afbf001c        sw      ra,28(sp)

2.4.找到它在哪个文件

此接口位于:drivers/usb/dwc2/gadget.c

2.5. touch一下这个c文件

touch drivers/usb/dwc2/gadget.c

这步是为了摸一下它,好让此文件在不改动的情况下重新编译一次,这样做的目的是,获取详细反汇编信息。

2.6. make V=1,取此文件的编译命令

make uImage V=1 -j16 > aaa.txt

打开 aaa,txt

Linux 内核调试:指令追踪大法

2.7.单独编译此文件

在命令行粘贴此命令(一个字符都不能少),后面加上(空格)**–save-temps -g**,回车,发现当前路径下多了俩文件:gadget.i gadget.s。前者是预编译文件,后者也是我们需要的——汇编文件

Linux 内核调试:指令追踪大法Linux 内核调试:指令追踪大法

2.8.打开.s文件找到之前要找的的点

  • 根据之前定位的函数:dwc2_hsotg_core_init_disconnected
dwc2_hsotg_core_init_disconnected:
        .frame  $sp,32,$31              # vars= 0, regs= 3/0, args= 16, gp= 0
        .mask   0x80030000,-4                                   
        .fmask  0x00000000,0
$LVL835 = .
        addiu   $sp,$sp,-32
        .cfi_def_cfa_offset 32
        sw      $17,24($sp)
        sw      $16,20($sp)
        sw      $31,28($sp)
        .cfi_offset 17, -8
        .cfi_offset 16, -12
        .cfi_offset 31, -4
        .loc 1 3337 0
        move    $17,$5
        .loc 1 3342 0
        lw      $5,1348($4)
  • 对比内核 dump.s
802cb298 :
802cb298:       27bdffe0        addiu   sp,sp,-32
802cb29c:       afb10018        sw      s1,24(sp) 

#是否发现这两处的指令是对应的?这时当然的。 之后就可以寻找**0x802cb3bc**这个点在gadget.s中的位置,切记,前后一定要严格对应,要不就找错了,如,在dump.s中,这点在这:

...
802cb398:       8e050588        lw      a1,1416(s0)
802cb39c:       3c04804d        lui     a0,0x804d
802cb3a0:       0c02958b        jal     800a562c 
802cb3a4:       2484f41c        addiu   a0,a0,-3044
802cb3a8:       8e020588        lw      v0,1416(s0)
802cb3ac:       10400009        beqz    v0,802cb3d4 
802cb3b0:       3c030080        lui     v1,0x80
802cb3b4:       8e020004        lw      v0,4(s0)
802cb3b8:       24420800        addiu   v0,v0,2048
802cb3bc:       ac620000        sw      v0,0(v1)  // 真正的异常
802cb3c0:       0000000f        sync
802cb3c4:       8e050588        lw      a1,1416(s0)
802cb3c8:       3c04804d        lui     a0,0x804d
802cb3cc:       0c02958b        jal     800a562c 

对应gadget.s 异常如下:

#NO_APP
$LBE2718 = .
 .loc 1 3394 0
 lw $5,1416($16)
 lui $4,%hi($LC40)
 .set noreorder
 .set nomacro
 jal printk
 addiu $4,$4,%lo($LC40)
 .set macro
 .set reorder

$LVL843 = .
 .loc 1 3395 0
 lw $2,1416($16)
 .set noreorder
 .set nomacro
 beq $2,$0,$L982
 li $3,8388608   # 0x800000
 .set macro
 .set reorder

 .loc 1 3396 0
 lw $2,4($16)
 addiu $2,$2,2048
$LBB2722 = .
$LBB2723 = .
$LBB2724 = .
$LBB2725 = .
 .loc 2 429 0
 sw $2,0($3)  // epc 0x0x802cb3bc 异常

快速找到它的秘诀是,看到 sw v0,0(v1),就搜sw 3),然后再看看上下指令是否对应。找到这处,做个标记。

寄存器辅助记忆:

Linux 内核调试:指令追踪大法

2.9. 找到c文件中的对应地方

$LBB2722 = .
$LBB2723 = .
$LBB2724 = .
$LBB2725 = .
 .loc 2 429 0
 sw $2,0($3)  // epc 0x0x802cb3bc 异常
 $L1008:
$LBE2725 = .
$LBE2724 = .
$LBE2723 = .
$LBE2722 = .
$LBB2726 = .
$LBB2727 = .
 .loc 3 79 0

注意他前面的.loc 2 429 0,这就是他的藏身所在。

Outwrite
Outwrite

AI写作浏览器插件,将您的想法变成有力的句子

下载
  • .loc 1 意思是第一个文件,可以从gadget.s中搜索file 1,如:
.file 2 "./arch/mips/include/asm/io.h" 
  • 429:行号 这就是它在的文件。打开它,找到 429

结合下文的.loc 3 79 0。

.file 3 "drivers/usb/dwc2/core.h"
  • 79: 行号 最终位置:
dwc2_hsotg_core_init_disconnected  // drivers/usb/dwc2/gadget.c
   dwc2_writel(hsotg->regs + DCFG, DCFG_DESCDMA_EN); 
       __raw_writel(value, addr);     // drivers/usb/dwc2/core.h +79        
       

可以看作最后出错的指令 **sw v0,0(v1)**, 结合代码大致定位到操作DCFG 寄存器出错。

对于硬件寄存器,尽量按位操作,也就是只操作特定比特位,否则会引入未知风险

3. 总结

  • 保存错误现场(epc/ra地址)
  • 反汇编内核:objdump -d vmlinux > dump.s
  • 根据dump.s 找到指定 epc 值
  • 根据epc 值 确定发生异常的函数
  • 根据函数名确定发生异常的文件
  • 重新编译发生异常的文件,得到详细汇编和预处理信息(**–save-temps -g**)
  • 根据epc 确定异常位置。
  • 根据异常位置,定位文件名及行号。一般经过这几步就可以精确定位错误发生地方了。

对于发生异常的函数名定位,有的时候根据经验可以直接通过内核trace dump 信息找到。或者根据epc 直接在 system.map 也可以定位。

对于内核反汇编和重新编译异常文件,依赖于读者对汇编指令的理解。特别是对比 dump.s 和 gadget.s ,如果快速定位和找对很关键。

相关专题

更多
硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

980

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

39

2025.10.17

golang map内存释放
golang map内存释放

本专题整合了golang map内存相关教程,阅读专题下面的文章了解更多相关内容。

73

2025.09.05

golang map相关教程
golang map相关教程

本专题整合了golang map相关教程,阅读专题下面的文章了解更多详细内容。

23

2025.11.16

golang map原理
golang map原理

本专题整合了golang map相关内容,阅读专题下面的文章了解更多详细内容。

36

2025.11.17

java判断map相关教程
java判断map相关教程

本专题整合了java判断map相关教程,阅读专题下面的文章了解更多详细内容。

31

2025.11.27

磁盘配额是什么
磁盘配额是什么

磁盘配额是计算机中指定磁盘的储存限制,就是管理员可以为用户所能使用的磁盘空间进行配额限制,每一用户只能使用最大配额范围内的磁盘空间。php中文网为大家提供各种磁盘配额相关的内容,教程,供大家免费下载安装。

1343

2023.06.21

如何安装LINUX
如何安装LINUX

本站专题提供如何安装LINUX的相关教程文章,还有相关的下载、课程,大家可以免费体验。

698

2023.06.29

虚拟号码教程汇总
虚拟号码教程汇总

本专题整合了虚拟号码接收验证码相关教程,阅读下面的文章了解更多详细操作。

25

2025.12.25

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 6万人学习

Git 教程
Git 教程

共21课时 | 2.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号