嵌入式编程中会遇到各种crash的问题。 对于这样的问题,有两种调试方法: addr2line 和 gdb。
//1.1.cpp
#include <iostream> using namespace std;
bool IsUnique() { int k = 0, m = 0; k = k/m; //这里会crash
return true; }
int main() { cout << IsUnique() << endl; return 0; }
[sundh@SSDEV005 ~]$g++ -o 1.1 1.1.cpp
[sundh@SSDEV005 ~]$gdb 1.1
(gdb) r
Starting program: /home/sundh/1.1
warning: no loadable sections found in added symbol-file system-supplied DSO at 0x2aaaaaaab000
Program received signal SIGFPE, Arithmetic exception.
0x00000000004007c2 in IsUnique() ()
(gdb) bt
#0 0x00000000004007c2 in IsUnique() ()
#1 0x0000000000400845 in main ()
(gdb)
// 可见,可执行程序不加-g编译,gdb也是可以打出函数堆栈信息的。
[sundh@SSDEV005 ~]$ addr2line -Cfe 1.1 0x00000000004007c2 0x0000000000400845
IsUnique()
??:0
main
??:0
//可见,可执行程序不加-g编译,addr2line 也是可以打出函数堆栈信息的。
[sundh@SSDEV005 ~]$g++ -g -o 1.1 1.1.cpp
[sundh@SSDEV005 ~]$gdb 1.1
(gdb) r
Starting program: /home/sundh/1.1
warning: no loadable sections found in added symbol-file system-supplied DSO at 0x2aaaaaaab000
Program received signal SIGFPE, Arithmetic exception.
0x00000000004007c2 in IsUnique () at 1.1.cpp:7
7 k = k/m;
(gdb) bt
#0 0x00000000004007c2 in IsUnique () at 1.1.cpp:7 //多了文件名和行数
#1 0x0000000000400845 in main () at 1.1.cpp:14
(gdb)
[sundh@SSDEV005 ~]$ addr2line -Cfe 1.1 0x00000000004007c2 0x0000000000400845
IsUnique()
/home/sundh/1.1.cpp:7 //多了文件名和行数
main
/home/sundh/1.1.cpp:14
[sundh@SSDEV005 ~]$ nm 1.1
0000000000600b00 d _DYNAMIC
0000000000600cc8 d _GLOBAL_OFFSET_TABLE_
000000000040080e t _GLOBAL__I__Z8IsUniquev
00000000004007a8 T IsUnique()
000000000040083c T main
总结, 编译时加 -g, 生成的可执行程序里面会有调试信息(所谓调试信息就是 代码文件名[行数] 和地址 的一个对应关系的信息, 而且这个信息在可执行程序的尾端)。 如果不加-g,也是可以用gdb 和 addr2line进行crash分析的,只能显示 函数名。
因为#0 0x00000000004007c2 in IsUnique() () #1 0x0000000000400845 in main () 加不加-g,这两个函数的地址都一样, 说明加-g时候,调试信息在可执行程序的尾端。
[sundh@SSDEV005 ~]$ gdb 1.1 GNU gdb (GDB) Red Hat Enterprise Linux (7.0.1-32.el5) Copyright (C) 2009 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-redhat-linux-gnu". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /home/sundh/1.1...(no debugging symbols found)...done. (gdb) r Starting program: /home/sundh/1.1 warning: no loadable sections found in added symbol-file system-supplied DSO at 0x2aaaaaaab000
Program received signal SIGFPE, Arithmetic exception. 0x00000000004007c2 in __gxx_personality_v0 () (gdb) bt #0 0x00000000004007c2 in __gxx_personality_v0 () #1 0x0000000000400845 in __gxx_personality_v0 () #2 0x000000337321d994 in __libc_start_main () from /lib64/libc.so.6 #3 0x00000000004006f9 in __gxx_personality_v0 () #4 0x00007fffffffe8c8 in ?? () #5 0x0000000000000000 in ?? () (gdb)quit
[sundh@SSDEV005 ~]$ strip 1.1 [sundh@SSDEV005 ~]$ addr2line -Cfe 1.1 0x00000000004007c2 0x0000000000400845 ?? ??:0 ?? ??:0
[sundh@SSDEV005 ~]$ nm 1.1 nm: 1.1: no symbols
可见,gdb 和 addr2line 是不能调试经过strip处理后的可执行程序的。
还有一种验证方式:使用 nm 命令, 经过strip处理后的可执行程序,是没有保存 函数名与地址的对应关系信息。
addr2line 和 gdb 都可以进行crash的分析。 根据不同的情况,使用不同命令进行分析。
如果有core 文件,那使用gdb调试就很方便(gdb也能实现地址转化为函数名的功能)。
但是如果没有core文件,只有一份crash log,那就只能使用 addr2line 进行分析。
//crash log 文件都包含以下信息:
//寄存器堆栈信息
[ 2][ 18.572091] Pid: 678, comm: minismarthub
[ 2][ 18.577125] CPU: 2 Tainted: P O (3.8.13 #1)
[ 2][ 18.582943] PC is at 0x150ac58
[ 2][ 18.586367] LR is at 0xa96a3460
[ 2][ 18.589892] pc : [<0150ac58>] lr : [<a96a3460>] psr: 60000010
[ 2][ 18.589892] sp : 9aa7eb48 ip : 0150ac50 fp : 9aa7eb64
[ 2][ 18.602218] r10: 00000000 r9 : 00004ae0 r8 : 00000001
[ 2][ 18.607854] r7 : a055d478 r6 : a055d6a4 r5 : a96f85d4 r4 : 00000b64
[ 2][ 18.614815] r3 : 0000272b r2 : ffffffff r1 : 00000001 r0 : 00000b64
//dump map 信息
[ 2][ 18.747704] -----------------------------------------------------------
[ 2][ 18.754763] * dump maps on pid (678 - minismarthub)
[ 2][ 18.760043] -----------------------------------------------------------
[ 2][ 18.767100] 00008000-0a260000 r-xp 00000000 b3:10 22623 /mtd_exe/exeAPP
[ 2][ 18.774567] 0a260000-0a6d2000 rwxp 0a258000 b3:10 22623 /mtd_exe/exeAPP
[ 2][ 18.782053] 0a6d2000-0a9e3000 rwxp 00000000 00:00 0
[ 2][ 18.788218] 0be59000-0bf43000 rwxp 00000000 00:00 0 [heap]
[ 2][ 18.794912] 9a040000-9a041000 ---p 00000000 00:00 0
[ 2][ 18.801076] 9a041000-9a080000 rwxp 00000000 00:00 0 [tstack: CHomePanelDataM: 712]
[ 2][ 18.809884] 9a080000-9a081000 ---p 00000000 00:00 0
[ 2][ 18.816048] 9a081000-9a0c0000 rwxp 00000000 00:00 0 [tstack: CHomeDisclaimer: 711]
[ 2][ 18.824856] 9a0c0000-9a0c1000 ---p 00000000 00:00 0
[ 2][ 18.831021] 9a0c1000-9a100000 rwxp 00000000 00:00 0 [tstack: CHomeNoticeServ: 710]
[ 2][ 18.839829] 9a100000-9a12a000 rwxp 00000000 00:00 0
[ 2][ 18.845993] 9a12a000-9a200000 ---p 00000000 00:00 0
[ 2][ 18.852159] 9a203000-9a204000 ---p 00000000 00:00 0
[ 2][ 18.858323] 9a204000-9a243000 rwxp 00000000 00:00 0 [tstack: CHomeHubSiteInf: 709]
[ 2][ 18.867131] 9a243000-9a244000 ---p 00000000 00:00 0
[ 2][ 18.873296] 9a244000-9a283000 rwxp 00000000 00:00 0 [tstack: appcmhome: 707]
[ 2][ 18.881576] 9a283000-9a4f4000 r-xp 00000000 b3:10 25108 /mtd_exe/TTS/Lib/libSMT_lang_pl.so
[ 2][ 18.890735] 9a4f4000-9a4fb000 ---p 00271000 b3:10 25108 /mtd_exe/TTS/Lib/libSMT_lang_pl.so
[ 2][ 18.899894] 9a4fb000-9a500000 rwxp 00270000 b3:10 25108 /mtd_exe/TTS/Lib/libSMT_lang_pl.so
[ 2][ 21.700779] a963f000-a977c000 r-xp 00000000 b3:0f 495 /mtd_rwarea/libMiniSmartHubApp.so // libMiniSmartHubApp.so代码所分配的地址,注意起始地址a963f000
[ 2][ 21.709850] a977c000-a9784000 ---p 0013d000 b3:0f 495 /mtd_rwarea/libMiniSmartHubApp.so
[ 2][ 21.718922] a9784000-a978f000 rwxp 0013d000 b3:0f 495 /mtd_rwarea/libMiniSmartHubApp.so
//用户堆栈信息
[ 2][ 23.402020] task stack info : pid(678) stack area (0x9aa41000 ~ 0x9aa80000)
[ 2][ 23.409421] -----------------------------------------------------------
[ 2][ 23.416453] * dump user stack
[ 2][ 23.419781] -----------------------------------------------------------
[ 2][ 23.426844] pid(678) stack vma (0x9aa41000 ~ 0x9aa80000)
[ 2][ 23.432571] User Stack: (0x9aa7eb48 to 0x9aa7ef68)
[ 2][ 23.437762] eb40: 9aa7eb64 a96a3460 0000066c 00000001 9b66bcb8 00004b19
[ 2][ 23.446392] eb60: 9aa7eb84 a969a34c 00000000 b638d51c 9b66bcb8 00000001 a0558c10 00004b19
[ 2][ 23.455020] eb80: 9aa7eb9c a96928e0 000000e6 027c0938 a0558c10 9aa7ec04 9aa7ebc4 01ecd9cc
[ 2][ 23.463650] eba0: a0558c10 a7be2f80 a7be305c 9aa7ec04 a0558c10 00004ae0 a055d478 00000001
[ 2][ 23.472283] ebc0: 9aa7ebe4 01ecf278 0150a10c a055d478 9aa7ebe4 a055d478 9aa7ec04 9aa7f430
[ 2][ 23.480916] ebe0: 9aa7ebfc 01ed1828 00000000 a0558c10 a055d6a0 9aa7f430 9aa7ec44 01ecd824
[ 2][ 23.489550] ec00: a055d6a0 00000000 a055d478 00000000 0000004a 00004ae0 9aa7f430 0150fd70
[ 2][ 23.498190] ec20: 9aa7ec34 00000000 a7be2fbc a0558c10 a7bf4d78 00000001 0000053c 00000001
[ 2][ 23.506818] ec40: 9aa7ec4c 01ecd938 9aa7ec94 01ecf910 a7bf4d78 00000002 00000002 00000001
[ 2][ 23.515457] ec60: 00000002 0150fd70 00000003 00000002 a7b79788 a055e1b8 9aa7ed54 a0558c10
[ 2][ 23.524073] ec80: 00000002 a7bf4d78 00000001 0000053c 9aa7eccc 01ecce0c 00000001 00000000
[ 2][ 23.532706] eca0: aaa63bf8 9aa7ecb0 04c151fc 9aa7ed54 a0558c10 00000000 00000152 a0558c2c
[ 2][ 23.541336] ecc0: 0000000c 00000000 9aa7ed2c 01ed2a58 a0558c58 00000000 a0558c48 9aa7ed54
[ 2][ 23.549962] ece0: a055d478 000002a3 00000002 9aa7f430 000002a3 0150fd70 9aa7ed54 a055d478
[ 2][ 23.558598] ed00: 000002a3 a0558c44 9aa7ed4c 01506328 0495635c 9aa7ed54 a0558c10 9aabe7f4
[ 2][ 23.567225] ed20: 00000152 a0558c2c 9aa7ed4c 01ecf0a8 a0558c34 9aabe7f4 00000152 a055d478
[ 2][ 23.575861] ed40: a0558c34 9aabe7f4 9aa7ed84 0150af08 00000000 9aabe51c a055d478 000002a3
[ 2][ 23.584489] ed60: 00000043 a055e1b8 a055d478 000002a3 0000004c 00000000 a0558c2c a0558c10
[ 2][ 23.593123] ed80: 9aa7ed94 0150ae00 0150adac a0558c10 9aa7edac 0150fe6c 00000000 00000000
[ 2][ 23.601750] eda0: 9aa7f498 00000000 9aa7ef6c aaa5e0f8 9aa7f648 9aa7f430 00000000 00000000
[ 2][ 23.610382] edc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.619027] ede0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.627646] ee00: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.636278] ee20: 00000000 00000000 00000000 00000000 00000000 00000000 9aa7f498 00000000
[ 2][ 23.644910] ee40: 9aabe7f4 00000152 a0558c2c 0000000c 00000000 9aa7ef6c 9aa7edb0 aaa5e0c8
[ 2][ 23.653538] ee60: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.662168] ee80: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.670802] eea0: 80000010 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.679427] eec0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.688058] eee0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.696690] ef00: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.705327] ef20: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.713954] ef40: 00000000 00000000 00000000 00000000 9aa7f498 00000000 9aabe7f4 00000078
[ 2][ 23.722600] ef60: a0558c2c 00000000 9aabe83c
[ 2][ 23.727253] -----------------------------------------------------------
$: arm-v7a15v4r3-linux-gnueabi-addr2line -Cfe exeAPP 0x0150ac58 0xa96a3460 // exeAPP 是可执行程序,
PCHandler::FlagCreate() // 0x0150ac58 对应的函数, 后面的是相应文件路径
/home1/jsun.song/TV400_REL/VDLINUX/VDLinux_RND/2013PRJ/13_VDCSP_Prj/INT/Src/HQ_TV_4_0/BP_CSP/CSP-4.0/CSP/Src/PCTask.cpp:660
?? // 0xa96a3460 对应的函数,是某个so里面的函数,所以信息打不出来。
??:0
这里出现了一个问题, so动态库里面的crash,该怎么办?
如果crash在一个so里面,那addr2line不能直接给出代码行。因为我们都知道,so里面的地址在可执行文件装载的时候,是可以被 reallocate的。所以要找出对应 函数名 的话,就要给 addr2line一个基地址和偏移量,或者根据可执行程序的dump map信息,自己将这个地址转化成相对于so基地址的一个偏移地址才行。
总结:
寄存器 存储的地址 和 dump map表上面提到了, 我们知道 PC/0x0150ac58 和 LR/0xa96a3460 存储的是 crash之前调用的函数地址(可以参考:http://blog.csdn.net/sunny04/article/details/40456259)。 LR/0xa96a3460 这个地址是在[ 2][ 21.700779] a963f000-a977c000 r-xp 00000000 b3:0f 495 /mtd_rwarea/libMiniSmartHubApp.so 这个区间里面,说明是libMiniSmartHubApp.so这个动态库里面函数引起的crash。
0xa96a3460-0xa963f000 = 0x64460 这说明 LR/0xa96a3460 相对于libMiniSmartHubApp.so 起始位置0X00000000的偏移地址为 0x64460
$: arm-v7a15v4r3-linux-gnueabi-addr2line -Cfe libMiniSmartHubApp.so 0x64460
CMNMiniHubView::StartViewTimer()
/home/sundh/GolfP/AP_MM/AP_MiniSmartHub/Src/MNMiniHubView.cpp:1689
sundh@SSDEV016:$ arm-v7a15v4r3-linux-gnueabi-gdb exeAPP ~/Coredump.exeAPP.minismarthub.681 //exeApp 为可执行程序,Coredump.exeAPP.minismarthub.681 为core文件
(gdb) bt
#0 0x0150ac58 in PCHandler::FlagCreate (this=<optimized out>) at CSP/Src/PCTask.cpp:660
#1 0xa96a3460 in ?? ()
#2 0xa96a3460 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb) set solib-search-path .
#拷贝libMiniSmartHubApp.so 到当前目录下。
Reading symbols from /home/sundh/GolfP_0943/REL/DTV_Samsung/T-GFPDEUC/Build/BIN/SymbolFiles/mtd_exe/libMiniSmartHubApp.so...done.
Loaded symbols for /home/sundh/GolfP_0943/REL/DTV_Samsung/T-GFPDEUC/Build/BIN/SymbolFiles/mtd_exe/libMiniSmartHubApp.so
(gdb) bt
#0 0x0150ac58 in PCHandler::FlagCreate (this=<optimized out>) at CSP/Src/PCTask.cpp:660
#1 0xa96a3460 in CMNMiniHubView::StartViewTimer (this=<optimized out>) at /home/sundh/GolfP/CSP/BP_CSP_Public/CSP-4.0/Inc/PCAlarm.h:102
#2 0xa96bf2c8 in CMNViewMgr::Enable (this=<optimized out>, isEnable=<optimized out>, eSetFocusPosition=<optimized out>) at /home/sundh/GolfP/AP_MM/AP_MiniSmartHub/Src/MNViewMgr.cpp:357
#3 0xa96b7444 in CMiniSmartHubApp::t_OnHighlighted (this=<optimized out>, event=<optimized out>) at /home/sundh/GolfP/AP_MM/AP_MiniSmartHub/Src/MNSmartHubApp.cpp:253
#4 0x01ecd9cc in ALMOND0300::CApplication::OnHighlighted (this=<optimized out>, event=<optimized out>) at /home/zhangsong/GolfP_0943/BP_APP/BP_AppCM/Almond/Src/CApplication.cpp:1162
#5 0x01ecf278 in ALMOND0300::CApplication::t_OnEvent (this=<optimized out>, event=<optimized out>) at /home/zhangsong/GolfP_0943/BP_APP/BP_AppCM/Almond/Src/CApplication.cpp:2382
#6 0x01ed1828 in ALMOND0300::CApplicationBase::t_SendAppEvent (this=<optimized out>, event=<optimized out>) at /home/zhangsong/GolfP_0943/CSP/BP_CSP_Public/CSP-4.0/Inc/PCTask.h:168
#7 0x01ecd824 in ALMOND0300::CApplication::SetHighlight (this=<optimized out>, save=<optimized out>) at /home/zhangsong/GolfP_0943/BP_APP/BP_AppCM/Almond/Src/CApplication.cpp:1551
#8 0x01ecd938 in ALMOND0300::CApplication::t_SupportSetHighlight (this=<optimized out>, option=<optimized out>) at /home/zhangsong/GolfP_0943/BP_APP/BP_AppCM/Almond/Src/CApplication.cpp:1372
#9 0x01ecf910 in ALMOND0300::CApplication::OnActivated (this=<optimized out>, callerName=<optimized out>, userData=<optimized out>, activateInfo=<optimized out>,
bSaveHighlight=<error reading variable: Could not find the frame base for "ALMOND0300::CApplication::OnActivated(char const*, int, STAppActivationInfo*, bool)".>)
at /home/zhangsong/GolfP_0943/BP_APP/BP_AppCM/Almond/Src/CApplication.cpp:925
#10 0x01ecce0c in ALMOND0300::CApplication::OnAppStateChange (this=<optimized out>, event=<optimized out>) at /home/zhangsong/GolfP_0943/BP_APP/BP_AppCM/Almond/Src/CApplication.cpp:3492
#11 0x01ed2a58 in ALMOND0300::CApplicationBase::t_OnEvent (this=<optimized out>, event=<optimized out>) at /home/zhangsong/GolfP_0943/BP_APP/BP_AppCM/Almond/Src/CApplicationBase.cpp:316
#12 0x01ecf0a8 in ALMOND0300::CApplication::t_OnEvent (this=<optimized out>, event=<optimized out>) at /home/zhangsong/GolfP_0943/BP_APP/BP_AppCM/Almond/Src/CApplication.cpp:2360
#13 0x0150af08 in PCTask::ExecuteEvent (this=<optimized out>) at CSP/Inc/PCTask.h:168
#14 0x0150ae00 in PCTask::t_Main (this=<optimized out>) at CSP/Src/PCTask.cpp:780
#15 0x0150fe6c in _Process (param=<optimized out>) at CSP/Src/PCThread.cpp:403
#16 0xaaa840f8 in start_thread (arg=0x9a7bf430) at pthread_create.c:313
#17 0xa88933f8 in __GI_epoll_pwait (epfd=2916, events=0x0, maxevents=-1, timeout=22064556, set=0x0) at ../sysdeps/unix/sysv/linux/epoll_pwait.c:41
#18 0x00000000 in ?? ()
(gdb)
这样就能看到完整的堆栈信息了。
这里聊下额外的话题, 如果寄存器存储的地址是错误的 或者 线程的调用栈被破坏了,而调用栈存放了函数的返回地址,gdb解析函数返回地址(根据地址查找符号表)失败,gdb也没有进行容错处理,只要有一处地址解析失败就无法展开调用栈。然而幸运的是,调用栈往往只是部分被破坏,sp堆栈寄存器中保存的值往往也是正确的,可以通过手工的方法恢复。具体做法如下:
http://blog.csdn.net/sunny04/article/details/40456259 介绍了如何在dump user stack(用户堆栈信息)查找backtrace函数地址。 其实这是查找过程是可以反向的。
[ 2][ 18.594730] PC is at 0x150ac58
[ 2][ 18.598149] LR is at 0xa96c8834
[ 2][ 18.601674] pc : [<0150ac58>] lr : [<a96c8834>] psr: 60000010
[ 2][ 18.601674] sp : 9a7beb48 ip : 0150ac50 fp :
9a7beb64
[ 2][ 18.614006] r10: 00000000 r9 : 00004ae0 r8 : 00000001
[ 2][ 18.619636] r7 : a7bc9ad0 r6 : a7bc9cfc r5 : 00000000 r4 : 00000b64
[ 2][ 18.626593] r3 : 0000272b r2 : ffffffff r1 : 00000000 r0 : 00000b64
[ 2][ 23.380060] -----------------------------------------------------------
[ 2][ 23.387102] * dump user stack
[ 2][ 23.390452] -----------------------------------------------------------
[ 2][ 23.397496] pid(681) stack vma (0x9a781000 ~ 0x9a7c0000)
[ 2][ 23.403220] User Stack: (0x9a7beb48 to 0x9a7bef68)
[ 2][ 23.408422] eb40: 9a7beb64 a96c8834 0000068d 00000001 a7d46878 00004b19
[ 2][ 23.417046] eb60: 9a7beb84 a96bf2c800000000 b63b351c a7d46878 00000001 a7bc5268 00004b19 1. 根据fp :9a7beb64找到a96bf2c8,它前面的9a7beb84就是上一次backtrace函数地址
[ 2][ 23.425679] eb80: 9a7beb9c a96b7444000000ee 027c0938 a7bc5268 9a7bec049a7bebc4
01ecd9cc 2. 根据9a7beb84, 找到a96b7444,它前面的9a7beb9c就是上一次backtrace函数地址
[ 2][ 23.434305] eba0: a7bc5268 a7e65620 a7e656fc 9a7bec04 a7bc5268 00004ae0 a7bc9ad0 00000001 3. 依次类推
[ 2][ 23.442934] ebc0: 9a7bebe4 01ecf278 0150a10c a7bc9ad0 9a7bebe4 a7bc9ad0 9a7bec04 9a7bf430
[ 2][ 23.451569] ebe0: 9a7bebfc 01ed1828 00000000 a7bc5268 a7bc9cf8 9a7bf430 9a7bec44 01ecd824
[ 2][ 23.460199] ec00: a7bc9cf8 00000000 a7bc9ad0 00000000 0000004a 00004ae0 9a7bf430 0150fd70
[ 2][ 23.468842] ec20: 9a7bec34 00000000 a7e6565c a7bc5268 a7e76b18 00000001 0000053c 00000001
[ 2][ 23.477472] ec40: 9a7bec4c 01ecd938 9a7bec94 01ecf910 a7e76b18 00000002 00000002 00000001
[ 2][ 23.486104] ec60: 00000002 0150fd70 00000003 00000002 a7e0bc30 a7bca838 9a7bed54 a7bc5268
[ 2][ 23.494724] ec80: 00000002 a7e76b18 00000001 0000053c 9a7beccc 01ecce0c 00000001 00000000
[ 2][ 23.503362] eca0: aaa89bf8 9a7becb0 04c151fc 9a7bed54 a7bc5268 00000000 00000152 a7bc5284
[ 2][ 23.511985] ecc0: 0000000c 00000000 9a7bed2c 01ed2a58 a7bc52b0 00000000 a7bc52a0 9a7bed54
[ 2][ 23.520618] ece0: a7bc9ad0 000002a6 00000002 9a7bf430 000002a6 0150fd70 9a7bed54 a7bc9ad0
[ 2][ 23.529248] ed00: 000002a6 a7bc529c 9a7bed4c 01506328 0495635c 9a7bed54 a7bc5268 9a7fe7f4
[ 2][ 23.537877] ed20: 00000152 a7bc5284 9a7bed4c 01ecf0a8 a7bc528c 9a7fe7f4 00000152 a7bc9ad0
[ 2][ 23.546510] ed40: a7bc528c 9a7fe7f4 9a7bed84 0150af08 00000000 9a7fe51c a7bc9ad0 000002a6
[ 2][ 23.555140] ed60: 00000043 a7bca838 a7bc9ad0 000002a6 0000004c 00000000 a7bc5284 a7bc5268
[ 2][ 23.563773] ed80:
9a7bed94 0150ae00 0150adac a7bc5268
9a7bedac 0150fe6c 00000000 00000000
[ 2][ 23.572404] eda0: 9a7bf498 00000000 9a7bef6c
aaa840f8 9a7bf648 9a7bf430 00000000 00000000
[ 2][ 23.581035] edc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.589672] ede0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.598297] ee00: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.606924] ee20: 00000000 00000000 00000000 00000000 00000000 00000000 9a7bf498 00000000
[ 2][ 23.615557] ee40: 9a7fe7f4 00000152 a7bc5284 0000000c 00000000 9a7bef6c 9a7bedb0 aaa840c8
[ 2][ 23.624187] ee60: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.632817] ee80: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.641452] eea0: 80000010 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.650084] eec0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.658712] eee0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.667341] ef00: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.675973] ef20: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.684605] ef40: 00000000 00000000 00000000 00000000 9a7bf498 00000000 9a7fe7f4 00000078
[ 2][ 23.693248] ef60: a7bc5284 00000000 9a7fe83c
[ 2][ 23.697906] -----------------------------------------------------------
这个是正向推到, 如果寄存器或者用户堆栈表被破坏(绝大多数是低端数据被破坏), 那我们可以逆向推导相关函数:
[ 2][ 23.380060] -----------------------------------------------------------
[ 2][ 23.387102] * dump user stack
[ 2][ 23.390452] -----------------------------------------------------------
[ 2][ 23.397496] pid(681) stack vma (0x9a781000 ~ 0x9a7c0000)
[ 2][ 23.403220] User Stack: (0x9a7beb48 to 0x9a7bef68)
[ 2][ 23.408422] eb40: 9a7beb64 a96c8834 0000068d 00000001 a7d46878 00004b19
[ 2][ 23.417046] eb60: 9a7beb84 a96bf2c8 00000000 b63b351c a7d46878 00000001 a7bc5268 00004b19
[ 2][ 23.425679] eb80: 9a7beb9c a96b7444 000000ee 027c0938 a7bc5268 9a7bec04 9a7bebc4 01ecd9cc
[ 2][ 23.434305] eba0: a7bc5268 a7e65620 a7e656fc 9a7bec04 a7bc5268 00004ae0 a7bc9ad0 00000001
[ 2][ 23.442934] ebc0: 9a7bebe4 01ecf278 0150a10c a7bc9ad0 9a7bebe4 a7bc9ad0 9a7bec04 9a7bf430
[ 2][ 23.451569] ebe0: 9a7bebfc 01ed1828 00000000 a7bc5268 a7bc9cf8 9a7bf430 9a7bec44 01ecd824
[ 2][ 23.460199] ec00: a7bc9cf8 00000000 a7bc9ad0 00000000 0000004a 00004ae0 9a7bf430 0150fd70
[ 2][ 23.468842] ec20: 9a7bec34 00000000 a7e6565c a7bc5268 a7e76b18 00000001 0000053c 00000001
[ 2][ 23.477472] ec40: 9a7bec4c 01ecd938 9a7bec94 01ecf910 a7e76b18 00000002 00000002 00000001
[ 2][ 23.486104] ec60: 00000002 0150fd70 00000003 00000002 a7e0bc30 a7bca838 9a7bed54 a7bc5268
[ 2][ 23.494724] ec80: 00000002 a7e76b18 00000001 0000053c 9a7beccc 01ecce0c 00000001 00000000
[ 2][ 23.503362] eca0: aaa89bf8 9a7becb0 04c151fc 9a7bed54 a7bc5268 00000000 00000152 a7bc5284
[ 2][ 23.511985] ecc0: 0000000c 00000000 9a7bed2c 01ed2a58 a7bc52b0 00000000 a7bc52a0 9a7bed54
[ 2][ 23.520618] ece0: a7bc9ad0 000002a6 00000002 9a7bf430 000002a6 0150fd70 9a7bed54 a7bc9ad0
[ 2][ 23.529248] ed00: 000002a6 a7bc529c 9a7bed4c 01506328 0495635c 9a7bed54 a7bc5268 9a7fe7f4
[ 2][ 23.537877] ed20: 00000152 a7bc5284 9a7bed4c 01ecf0a8 a7bc528c 9a7fe7f4 00000152 a7bc9ad0
[ 2][ 23.546510] ed40: a7bc528c 9a7fe7f4 9a7bed84 0150af08 00000000 9a7fe51c a7bc9ad0 000002a6 4. 依次类推,如果search到多个,没办法根据上下文判断,根据search结果,再往上一级
[ 2][ 23.555140] ed60: 00000043 a7bca838 a7bc9ad0 000002a6 0000004c 00000000 a7bc5284 a7bc5268 search,再根据上下文剔除某些不合适的选项。
[ 2][ 23.563773] ed80: 9a7bed94 0150ae00 0150adac a7bc5268
9a7bedac 0150fe6c 00000000 00000000 3. 根据aaa840f8所在堆栈地址9a7bedac,search到0150fe6c
[ 2][ 23.572404] eda0: 9a7bf498 00000000 9a7bef6c
aaa840f8 9a7bf648 9a7bf430 00000000 00000000 2. 有两个地方有9a78ef6c,它的后一位存储的是backtrace函数地址。可以明显的看出
[ 2][ 23.581035] edc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 aaa840f8 是bt函数地址,9a7bedb0 在0x9a781000 ~ 0x9a7c0000用户堆栈信息中,排除掉
[ 2][ 23.589672] ede0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.598297] ee00: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.606924] ee20: 00000000 00000000 00000000 00000000 00000000 00000000 9a7bf498 00000000
[ 2][ 23.615557] ee40: 9a7fe7f4 00000152 a7bc5284 0000000c 00000000
9a7bef6c 9a7bedb0 aaa840c8
[ 2][ 23.624187] ee60: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.632817] ee80: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.641452] eea0: 80000010 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.650084] eec0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.658712] eee0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.667341] ef00: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.675973] ef20: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 2][ 23.684605] ef40: 00000000 00000000 00000000 00000000 9a7bf498 00000000 9a7fe7f4 00000078
[ 2][ 23.693248] ef60: a7bc5284 00000000 9a7fe83c 1. 从最末端开始,9a78ef68 是最后一个存储data的单元。 先找9a78ef6c
[ 2][ 23.697906] ----------------------------------------------------------- 这个是用户堆栈的排布规则,规则就是这样的。
(gdb)
set logging on |
Copying
output to gdb.txt. |
(gdb)
x /2000a $sp //arm 下是寄存器名sp, x86下是寄存器名rsp |
0x426cb890:
0x0 0x4 |
0x426cb8a0:
0x426cb8c0 0x100 |
0x426cb8b0:
0x3e8 0x552f59 <_ZN5tbnet16EPollSocketEvent9getEventsEiPNS_7IOEventEi+41> |
0x426cb8c0:
0x1823c8a000000011 0x0 |
0x426cb8d0:
0x0 0x0 |
0x426cb8e0:
0x0 0x0 |
... |
这个会把 dump user stack(用户堆栈信息)里面所有的 函数地址 转化为 函数名,根据这么函数名推测哪里crash了。
如上图,类似”0x552f59 <_ZN5tbnet16EPollSocketEvent9getEventsEiPNS_7IOEventEi+41>”这样的代码符号看起来是有效的。通过所有看似有效的程序代码符号基本能够得出core dump时的调用栈。
当然,有可能出现core dump线程的调用栈被完全破坏的情况,通过上述方法恢复的信息仍然是无效的。由于每个线程堆栈地址空间的大小为10M,因此,线程之间互相破坏调用堆栈的可能性几乎是不存在的,此时,可以通过其它线程的调用栈分析其行为,往往也能找到线索。如果所有线程的调用栈都“看似被破坏”,那么,往往有两种可能:
a, 可执行程序和core文件对不上,被摆乌龙了,如发现core dump问题的时候可执行程序已经更新到最新版本,老版本没有保存;
b, 磁盘满了或者ulimit设置太小,导致core dump文件信息不全;
参考: http://blog.csdn.net/boyxulin1986/article/details/11757793
http://blog.163.com/zdm_84/blog/static/869493332011522104736984/
gdb 和 addr2line 调试 crash(包含如何调试so里面的crash)
原文地址:http://blog.csdn.net/sunny04/article/details/41897949