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
總結
以上是生活随笔為你收集整理的vmlinux 反汇编_ARM Linux内核驱动异常定位方法分析--反汇编方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 成者会议星会不会太贵啊?
- 下一篇: 在上海嘉定什么地方有卖碧生源常润茶的?