vmlinux 反汇编_ARM Linux内核驱动异常定位方法分析--反汇编方式

通常认为,产生异常的地址是lr寄存器的值,从上面的异常信息可以看到[lr]的值是c01a4e30。

接下来,我们可以通过内核镜像文件反汇编来找到这个地址。内核编译完成后,会在内核代码根目录下生成vmlinux文件,我们可以通过以下命令来反汇编:

arm-none-eabi-objdump -Dz -S vmlinux >linux.dump

值得注意的是,arm-none-eabi-objdump的参数-S表示尽可能的把原来的代码和反汇编出来的代码一起呈现出来,-S参数需要结合arm-linux-gcc编译参数-g,才能达到反汇编时同时输出原来的代码。所以,我在linux内核代码根目录的Makefile中增加-g编译参数:

KBUILD_CFLAGS := -g -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \

-fno-strict-aliasing -fno-common \

-Werror-implicit-function-declaration \

-Wno-format-security \

-fno-delete-null-pointer-checks

修改Makefile后,重新编译内核,在根目录中生成的vmlinux文件就会包含了原来的代码信息,因此,该文件的大小也比原来大一倍!

最后执行“arm-none-eabi-objdump -Dz-S vmlinux >linux.dump”,由于加入了-g编译参数,执行这个反汇编命令需要很长时间(本人在虚拟机上执行,花了近6个小时!),反汇编出来的linux.dump文件也比原来的44MB增大到惊人的503MB。

接下来可以用UltraEdit打开linux.dump文件,查找“c01a4e30”字符串。

最后定位到的信息是:

/*

* tasklet handling tty stuff outside the interrupt handler.

*/

static void atmel_tasklet_func(unsigned long data)

{

c01a4e20: e92d45f0 push {r4, r5, r6, r7, r8, sl, lr}

c01a4e24: e24dd01c sub sp, sp, #28 ; 0x1c

c01a4e28: e1a04000 mov r4, r0

/* The interrupt handler does not take the lock */

spin_lock(&port->lock);

if (atmel_use_pdc_tx(port))

atmel_tx_pdc(port);

else if (atmel_use_dma_tx(port))

c01a4e2c: ebfffda1 bl c01a44b8

c01a4e30: e3500000 cmp r0, #0 ; 0x0

c01a4e34: e5943034 ldr r3, [r4, #52]

c01a4e38: 0a00007b beq c01a502c

可以看出来,异常的产生位于atmel_tasklet_func函数的 else if (atmel_use_dma_tx(port))一行。

估计atmel_use_dma_tx(port)的“port”参数为空指针所致!

最后,我把串口的DMA功能去掉,改为直接传送,这样做虽然效率低了点,但产生异常的现象消失了。

关键字:ARM atmel SAM9x25 Linux内核驱动异常 调试 反汇编 objdump


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部