异常debug之GNU工具使用
来源:互联网 发布:vb控件随窗体变化 编辑:程序博客网 时间:2024/05/20 22:02
先看看前面写的例子test.c:
1 #include <stdio.h> 2 3 void func4() 4 { 5 char *p = NULL; 6 *p = 0x5;//出错地方; 7 } 8 9 void func3() 10 { 11 int var4 = 4; 12 } 13 14 15 void func2() 16 { 17 int var3 = 3; 18 func3(); 19 func4(); 20 } 21 22 void func1() 23 { 24 int var1,var2; 25 var1 = 2; 26 } 27 28 void main() 29 { 30 int var0 = 1; 31 func1(); 32 func2(); 33 return; 34 } 35
反汇编出来的代码test.S:
00000738 <func4>: 738: b081 sub sp, #4 73a: 2000 movs r0, #0 73c: 9000 str r0, [sp, #0] 73e: 2105 movs r1, #5 740: 7001 strb r1, [r0, #0] 742: b001 add sp, #4 744: 4770 bx lr00000746 <func3>: 746: b081 sub sp, #4 748: 2004 movs r0, #4 74a: 9000 str r0, [sp, #0] 74c: b001 add sp, #4 74e: 4770 bx lr00000750 <func2>: 750: b580 push {r7, lr} 752: b082 sub sp, #8 754: 2003 movs r0, #3 756: 9001 str r0, [sp, #4] 758: f7ff fff5 bl 746 <func3> 75c: f7ff ffec bl 738 <func4> 760: b002 add sp, #8 762: bd80 pop {r7, pc}00000764 <func1>: 764: b082 sub sp, #8 766: 2002 movs r0, #2 768: 9001 str r0, [sp, #4] 76a: b002 add sp, #8 76c: 4770 bx lr0000076e <main>: 76e: b580 push {r7, lr} 770: b082 sub sp, #8 772: 2001 movs r0, #1 774: 9001 str r0, [sp, #4] 776: f7ff fff5 bl 764 <func1> 77a: f7ff ffe9 bl 750 <func2> 77e: b002 add sp, #8 780: bd80 pop {r7, pc}
发生问题的backtrace:
Backtrace: #00 pc 00000740 /system/bin/test #01 pc 0000075d /system/bin/test #02 pc 0000077b /system/bin/test #03 pc 0001708c /system/lib/libc.so (__libc_init+84) #04 pc 00000660 /system/bin/test
(1)addr2line
将地址转换为地址所在的文件及行数:
$ ./arm-linux-androideabi-addr2line -e symbols/test -f 00000740func4/proc/self/cwd/vendor/libtest/test.c:6
所以可以定位test.c第6行出现问题;
(2)nm
列出该文件的符号(函数,变量,文件等),包含名字、地址、大小;
-D, –dynamic: 只显示动态符号;
-g, –extern-only: 只显示外部符号;
-u, –undefined-only: 只显示未定义的符号;
-C, –demangle[=STYLE]: 反重整符号为可读方式自动识别格式;
-l, –line-numbers:多显示符号所在文件和行数;
$ ./arm-linux-androideabi-nm -C -l -g symbols/test U abort U __aeabi_memclr8 U __aeabi_memcpy00004000 A __bss_start U __cxa_atexit U dladdr00004000 A _edata00004005 A _end00003e3c T __FINI_ARRAY__ U fprintf00000764 T func1 /proc/self/cwd/vendor/libtest/test.c:2200000750 T func2 /proc/self/cwd/vendor/libtest/test.c:1500000746 T func3 /proc/self/cwd/vendor/libtest/test.c:900000738 T func4 /proc/self/cwd/vendor/libtest/test.c:3 U __gnu_Unwind_Find_exidx00003e34 T __INIT_ARRAY__ U __libc_init0000076e T main /proc/self/cwd/vendor/external/libtest/test.c:2800003e2c D __PREINIT_ARRAY__ U __register_atfork U __snprintf_chk U __stack_chk_fail U __stack_chk_guard U stderr
(3)objdump
查看对象文件(.so/.a或应用程序)的内容信息;
-a, –archive-headers: 显示库(*.a)成员信息
-f, –file-headers:显示obj中每个文件的整体头部摘要信息
-h, –[section-]headers:显示目标文件各个section的头部摘要信息
-x, –all-headers: 显示所有头部摘要信息
-d, –disassemble:反汇编代码段
-D, –disassemble-all: 反汇编所有段
-S, –source:反汇编出源代码,额外有debug信息,隐含-d,如果编译时有-g,效果
更明显
-t, –syms: 显示符号表
-r, –reloc: 显示重定位记录
-C, –demangle[=STYLE]: 反重整符号为可读方式
$ ./arm-linux-androideabi-objdump -f symbols/testsymbols/test: file format elf32-littlearmarchitecture: arm, flags 0x00000150:HAS_SYMS, DYNAMIC, D_PAGEDstart address 0x00000600
(4)readelf
看elf文件(.so/.a或应用程序)的内容信息;
-a, –all: 显示所有可显示的内容
-h –file-header: 显示ELF文件头
-l –segments: 显示程序头组
-S –sections: 显示节头组
-t: 显示节头细节
-e –headers: 等效于-h -l -S
-s –syms: 显示符号表
-n –notes: 显示内核说明
-r –relocs: 显示重定位信息
-u –unwind: 显示解栈信息
-d –dynamic: 显示动态节
-p –string-dump=
./arm-linux-androideabi-readelf -h symbols/test ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: DYN (Shared object file) Machine: ARM Version: 0x1 Entry point address: 0x600 Start of program headers: 52 (bytes into file) Start of section headers: 96780 (bytes into file) Flags: 0x5000200, Version5 EABI, soft-float ABI Size of this header: 52 (bytes) Size of program headers: 32 (bytes) Number of program headers: 9 Size of section headers: 40 (bytes) Number of section headers: 39 Section header string table index: 38
(5)c++filt
反重整C++符号为可读方式;
$ ./arm-linux-androideabi-c++filt _ZN20android_audio_legacy22AudioPolicyManagerBase17setSystemPropertyEPKcS2android_audio_legacy::AudioPolicyManagerBase::setSystemProperty(char const*, char const*)
(5)gdb
gdb调试在前获取带有符号的bin文件,从AEE log当中获取的coredump来调试,这里主要讲静态调试,当发生coredump的时候,通过带有符号信息的bin文件和coredump来分析问题;
$ ./arm-linux-androideabi-gdb symbols/test PROCESS_COREDUMP(gdb) set solib-search-path out/target/product/xxx/symbols/system/lib/(gdb) set solib-absolute-prefix out/target/product/xxx/symbols/
这样设置之后就可以通过gdb调试这个程序了;
(gdb) bt //堆栈信息#0 0xaaaaa740 in func4 () at vendor/libtest/test.c:6 //当前栈;#1 0xaaaaa760 in func2 () at vendor/libtest/test.c:19#2 0xaaaaa77e in main () at vendor/libtest/test.c:32
info f:打印出更为详细的当前栈层的信息(目前的函数是由什么样的程序语言写成的、函数参数地址及值、局部变量的地址等等):
(gdb) frame 0#0 0xaaaaa740 in func4 () at vendor/libtest/test.c:66 in vendor/libtest/test.c(gdb) info frameStack level 0, frame at 0xfffef9d0: pc = 0xaaaaa740 in func4 (vendor/libtest/test.c:6); saved pc 0xaaaaa760 called by frame at 0xfffef9e0 source language c. Arglist at 0xfffef9cc, args: Locals at 0xfffef9cc, Previous frame's sp is 0xfffef9d0(gdb) frame 1#1 0xaaaaa760 in func2 () at vendor/libtest/test.c:1919 in vendor/libtest/test.c(gdb) info frameStack level 1, frame at 0xfffef9e0: pc = 0xaaaaa760 in func2 (vendor/libtest/test.c:19); saved pc 0xaaaaa77e called by frame at 0xfffef9f0, caller of frame at 0xfffef9d0 source language c. Arglist at 0xfffef9d0, args: Locals at 0xfffef9d0, Previous frame's sp is 0xfffef9e0 Saved registers: r7 at 0xfffef9d8, lr at 0xfffef9dc
info args:打印出当前函数的参数名及其值。info locals:打印出当前函数中所有局部变量及其值。
(gdb) info localsp = 0
info registers:打印出所有寄存器的值;
//frame 0(gdb) info registersr0 0x0 0r1 0x5 5r2 0xfffefa2c 4294900268r3 0x0 0r4 0xaaaaa76f 2863310703r5 0xfffefa24 4294900260r6 0x1 1r7 0xfffefa2c 4294900268r8 0x0 0r9 0x0 0r10 0x0 0r11 0xfffefa00 4294900224r12 0xf759b85c 4149852252sp 0xfffef9d0 0xfffef9d0lr 0xaaaaa761 -1431656607pc 0xaaaaa760 0xaaaaa760 <func2+16>cpsr 0x70030 458800//frame 1(gdb) info registersr0 0x0 0r1 0x5 5r2 0xfffefa2c 4294900268r3 0x0 0r4 0xaaaaa76f 2863310703r5 0xfffefa24 4294900260r6 0x1 1r7 0xfffefa2c 4294900268r8 0x0 0r9 0x0 0r10 0x0 0r11 0xfffefa00 4294900224r12 0xf759b85c 4149852252sp 0xfffef9cc 0xfffef9cclr 0xaaaaa761 -1431656607pc 0xaaaaa740 0xaaaaa740 <func4+8>cpsr 0x70030 458800
根据上面的信息可以大概画出当前栈的情况:
查看存储器状态:
(gdb) p a //定义了一个数组:a[3]$1 = {5, 5, 5}(gdb) p &a$2 = (int (*)[3]) 0xfffef9d8(gdb) p &a[2]$4 = (int *) 0xfffef9e0(gdb) p &a[1]$5 = (int *) 0xfffef9dc(gdb) p &a[0]$6 = (int *) 0xfffef9d8(gdb) x/5wx 0xfffef9d8 //显示5个单元,w四字节一个单元,x十六进制显示0xfffef9d8: 0x00000005 0x00000005 0x00000005 0x000000050xfffef9e8: 0xfffefa2c/*b表示单字节,h表示双字节,w表示四字节,g表示八字节*//*x 按十六进制格式显示变量。d 按十进制格式显示变量。u 按十六进制格式显示无符号整型。o 按八进制格式显示变量。t 按二进制格式显示变量。a 按十六进制格式显示变量。c 按字符格式显示变量。f 按浮点数格式显示变量。*/
- 异常debug之GNU工具使用
- 使用GNU工具链
- GNU binutils工具使用
- GNU binutils工具使用
- GNU binutils工具使用
- 使用GNU工具链
- GNU Binutils工具readelf之Python实现
- 使用GNU工具链的优势
- GNU ARM命令行工具基本使用入门
- 【C语言】编程工具--GNU的使用
- GNU工具链的使用(一)
- GNU工具链的使用(三)
- window 下使用GNU工具的方法
- dos调试工具之debug
- GNU GDB Debug
- [Debug]GNU tools
- GNU Debug Link
- 工具使用常见异常
- jQuery的ajax学习(一)表单序列化
- 关于Unix哲学
- 排序算法(一)——冒泡排序及改进
- 关于nginx集群配置问题
- Hibernate中HQL占位符的一点使用技巧
- 异常debug之GNU工具使用
- 面试题15解析-守护线程 / JAVA多线程问题及其补充
- MediaPlayer+SurfaceHolder播放工具类
- Android在apk更新的时候数据库改变的(只限于在数据库末尾添加新字段)
- 快速排序算法分析
- java的抽象类和接口
- 494. Target Sum Medium
- 使用Jmeter进行http接口测试
- Aspera从NCBI下载基因组数据