RISCV Linux kernel 启动代码分析之五:一个小技巧实现在MMU使能后继续使用GDB调试

文摘   2024-11-17 08:01   湖南  

一. 前言

我们在前面分析head.S时借助了GDB进行仿真分析。在使能MMU前,链接地址和运行地址虽然不一样,但是此时没有使能MMU可以直接访问物理地址,我们此时可以使用GDB进行单步等各种调试,链接地址和运行有一个固定偏差所以也可以直接对照反汇编代码。

应对此时的链接地址和运行地址不一致导致的无法使用vmlinux的符号,无法在GDB中同时对应源码和汇编,我们可以使用add-symbol-file加载指定段地址,其实本来前面也都是汇编代码,也不是很复杂,所以也没必要一定要一起layout split对应源码和汇编一起看。单独查看反汇编的s文件也是没问题的,所以这里不处理也没关系。

我们重点关注后面使能mmuc代码执行过程,后面才是比较复杂的逻辑,我们希望能继续使用gdb调试。现在问题是在使能MMU后会切换到虚拟地址运行,在使能MMUGDB又访问不了链接地址即虚拟地址,导致无法打断点让CPU在使能MMU后的虚拟地址处停住。所以直接单步运行到使能MMU处后就会无法继续仿真调试。

本文就分享一个小的技巧,来实现让CPU停在使能MMU之后,好让GDB能接着继续仿真调试。

一. 解决方法

既然无法使用断点停在使能MMU后的地方,那我们是不是能换个思路在代码里人为的停住呢?就按照这个思路我们直接在使能MMU后继续运行的地址,我们前面relocate分析的切换位置加个死循环即可。

我们找到如下位置添加一行代码,

bnez a0,1b在此处死循环

这样我们c全速运行即可直接运行到该处,此时a0不为0,在此死循环,此时已经使能MMU,运行在虚拟地址与链接地址一致了。我们使用GDB停止在此处,再修改a0的值跳过这个死循环即可。后面开始就是使用虚拟地址和链接地址一致,此时加载的Vmlinux符号就可以使用了,可以直接layout split源码和汇编对照了,且各个附后地址都是对的了,不需要再人工去偏移了。

输出汇编

riscv64-unknown-linux-gnu-objdump -l -S output/vmlinux > a.s

找到添加的这条指令的位置

c全速运行,

然后ctrl+c取消全速运行

看到会卡在该处死循环

layout split打开源码和汇编代码

此时看到由于使用虚拟地址和链接地址对应,此时就可以源码和汇编对应了。

查看此时a0不为0,所以会在这里死循环

(gdb) i r a0a0             0xffffffe0000010ce       -137438949170(gdb)

我们手动将a0改0

(gdb) set $a0=0(gdb)

此时就可以单步运行接着往下走了

此时就可以愉快的仿真调试了。









嵌入式Lee
嵌入式软硬件技术:RTOS,GUI,FS,协议栈,ARM,总线,嵌入式C,开发环境 and blablaba....多年经验分享,非硬货不发,带你扒开每一个技术背后的根本原理。
 最新文章