[MTK] 异常发生后如何将log里对应的地址转换为所在的文件和行号?
文摘 Kernel MediaTek 2020-12-8 阅读:10408[DESCRIPTION]
在发生各种异常时,通常从log看到的是各种地址和数据,这些信息基本无法阅读,分析也很困难。
我们需要将这种人类无法阅读的信息转换成容易理解的信息。比如将函数地址转换成所在的文件和行号。
在log里恰恰含有大量这种地址信息。因此转换为所在文件和行号有助于我们分析问题。
[SOLUTION]
这个转换需要借助一个GNU工具:arm-linux-androideabi-addr2line(ARM 32位版本)或aarch64-linux-android-addr2line(ARM 64位版本)
工具位置(具体以实际目录位置为准):
ARM 32位版本:prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-addr2line
ARM 64位版本:prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-addr2line
使用方法:
arm-linux-androideabi-addr2line -Cfe $symbol_file 0xyyyyyyyy
其中的0xyyyyyyyy是从log提取的地址。$symbol_file为地址所在的符号文件,该文件包含调试信息。
该工具需要搭配对应的符号文件才行,那这个符号文件是什么呢?这要看你要查询的地址是属于哪个符号文件的了。
举例:log里的地址是lk的,那lk对应的符号文件是:out/target/product/$proj/obj/bootloader_obj/build-$proj/lk
如果是kernel的,对应的符号文件是:out/target/product/$proj/obj/kernel_obj/vmlinux(老版本的位置在kernel/out/vmlinux)
如果是preloader的,对应的符号文件是:out/target/product/$proj/obj/preloader_obj/bin/preloader_$proj.elf
实例1:
有一次在lk里发生了重启,抓取uart log如下:
kedump add: SYS_MINI_RDUMP[0] 1000/1000@a00
[1460] data abort, halting
[1460] r0 0x41e49ec8 r1 0x41e31b03 r2 0x41e49ed7 r3 0x00000000
[1460] r4 0x43ff0000 r5 0x43ff0bae r6 0x41e31b04 r7 0x43ff0bd6
[1460] r8 0x41e31ad4 r9 0x00000014 r10 0x00001a00 r11 0x00000000
[1460] r12 0x00000061 usp 0x00000000 ulr 0x00000000 pc 0x41e1b918
[1460] spsr 0x00000173
/ 之后就重启了 /
我们需要知道在什么地方发生异常了,PC是当时发生异常的地址。拿到对应的lk,用如下命令转换:
arm-linux-androideabi-addr2line -Cfe lk 0x41e1b918
kedump_to_expdb
bootable/bootloader/lk/app/mt_boot/aee_KEDump.c:219
很明显就可以看到是aee_KEDump.c的219行出问题了,赶紧查看代码分析吧。
实例2:
在kernel发生了panic,抓取kernel log(db里的SYS_KENREL_LOG)如下:
[17600.585313]<1>-(1)[1602:wpa_supplicant]PC is at sock_rfree+0x20/0x38
[17600.585327]<1>-(1)[1602:wpa_supplicant]LR is at netlink_skb_destructor+0x14/0x1c
......
[17600.590428]<1>-(1)[1602:wpa_supplicant]Call trace:
[17600.590442]<1>-(1)[1602:wpa_supplicant][<ffffffc000832784>] sock_rfree+0x20/0x38
[17600.590458]<1>-(1)[1602:wpa_supplicant][<ffffffc000836cb0>] skb_release_head_state+0x5c/0xe4
异常发生在sock_rfree()函数里,但是不知道哪一行异常了,异常的地址是ffffffc000832784,拿到对应的vmlinux,转换:
aarch64-linux-android-addr2line -Cfe vmlinux 0xffffffc000832784
sk_mem_uncharge
kernel-3.10/include/net/sock.h:1415
问题在sock.h的1415行异常,需要进一步分析。
注意:
- 这个符号文件必须是和烧录的image一起生成的,如果被重新编译过生成的,那么log里的地址和符号文件可能对应的不上,工具可能输出错误的结果。
- 如果不确定符号文件是32位还是64位,则直接使用64位版本。