如何定位Linux應(yīng)用程序崩潰?

背景

最近項(xiàng)目中用到了一個(gè)庫(kù)蜒什,在程序崩潰時(shí)可以生成exception文件测秸,記錄程序崩潰時(shí)的調(diào)用信息,對(duì)于定位問題比較有價(jià)值灾常,因此整理下這個(gè)庫(kù)涉及到的知識(shí)點(diǎn)霎冯。相關(guān)測(cè)試代碼已經(jīng)放到github可以下載調(diào)試。

基礎(chǔ)知識(shí)

maps

maps用來描述進(jìn)程的虛擬地址空間是如何使用的钞瀑∷嗤恚總共包括六列,每列及其含義如下:

名字 含義
address 本段在虛擬內(nèi)存中的地址范圍仔戈。
perms 本段的權(quán)限关串,r-讀,w-寫监徘,x-執(zhí)行晋修, p-私有,s-共享凰盔。
offset 即本段映射地址在文件中的偏移墓卦。
dev 主設(shè)備號(hào)與次設(shè)備號(hào):所映射的文件所屬設(shè)備的設(shè)備號(hào)。
inode 文件索引節(jié)點(diǎn)號(hào)户敬。
pathname 映射的文件名落剪。<br />對(duì)有名映射而言,是映射的文件名尿庐。<br />對(duì)匿名映射來說忠怖,是此段內(nèi)存在進(jìn)程中的作用。<br />[stack]表示本段內(nèi)存作為棧來使用抄瑟,[heap]作為堆來使用凡泣,其他情況則為無。

對(duì)于有名的內(nèi)存區(qū)間而言皮假,屬性為r--p表示存放的是rodata;屬性為rw-p存放的是bssdata;屬性為r-xp表示存放的是text數(shù)據(jù)鞋拟。沒有文件名的內(nèi)存區(qū)間則表示用mmap映射的匿名空間。

以下為./example/maps_test.c編譯成的可執(zhí)行文件mapstest的運(yùn)行結(jié)果:

code addr = 0x55e1df08d6da
A_global_addr = 0x55e1df28e034
B_global_init0_addr = 0x55e1df28e020
C_global_init_addr = 0x55e1df28e010
D_global_static_addr = 0x55e1df28e024
E_global_static_init0_addr = 0x55e1df28e028
F_global_static_init_addr = 0x55e1df28e014
G_global_const_addr = 0x55e1df08d998

a_addr = 0x7ffce299bb90
b_init0_addr = 0x7ffce299bb94
c_init_addr = 0x7ffce299bb98
d_static_addr = 0x55e1df28e02c
e_static_init0_addr = 0x55e1df28e030
f_static_init_addr = 0x55e1df28e018
g_const_addr = 0x7ffce299bb9c

h1_arr_addr = 0x7ffce299bbb2
h2_strconst_addr = 0x55e1df08d99c
h2_point_addr = 0x7ffce299bba0
i_malloc_addr = 0x55e1dfd1d260

ps -ef| grep mapstest得到進(jìn)程對(duì)應(yīng)的pid號(hào)惹资,maps文件如下:(路徑為/proc/{pid}/maps

55e1df08d000-55e1df08e000 r-xp 00000000 08:01 24786338  /mapstest    #text
55e1df28d000-55e1df28e000 r--p 00000000 08:01 24786338  /mapstest    #rodata
55e1df28e000-55e1df28f000 rw-p 00001000 08:01 24786338  /mapstest    #bss data
55e1dfd1d000-55e1dfd3e000 rw-p 00000000 00:00 0         [heap]       #堆
7f64881e5000-7f64883cc000 r-xp 00000000 08:01 10490449  /lib/x86_64-linux-gnu/libc-2.27.so
7f64883cc000-7f64885cc000 ---p 001e7000 08:01 10490449  /lib/x86_64-linux-gnu/libc-2.27.so
7f64885cc000-7f64885d0000 r--p 001e7000 08:01 10490449  /lib/x86_64-linux-gnu/libc-2.27.so
7f64885d0000-7f64885d2000 rw-p 001eb000 08:01 10490449  /lib/x86_64-linux-gnu/libc-2.27.so
7f64885d2000-7f64885d6000 rw-p 00000000 00:00 0 
7f64885d6000-7f64885fd000 r-xp 00000000 08:01 10490421  /lib/x86_64-linux-gnu/ld-2.27.so
7f64887de000-7f64887e0000 rw-p 00000000 00:00 0 
7f64887fd000-7f64887fe000 r--p 00027000 08:01 10490421  /lib/x86_64-linux-gnu/ld-2.27.so
7f64887fe000-7f64887ff000 rw-p 00028000 08:01 10490421  /lib/x86_64-linux-gnu/ld-2.27.so
7f64887ff000-7f6488800000 rw-p 00000000 00:00 0 
7ffce297d000-7ffce299e000 rw-p 00000000 00:00 0          [stack]    #棧
7ffce29ef000-7ffce29f2000 r--p 00000000 00:00 0          [vvar]
7ffce29f2000-7ffce29f4000 r-xp 00000000 00:00 0          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0  [vsyscall]

對(duì)應(yīng)地贺纲,我們可以找到每個(gè)變量在虛擬內(nèi)存中的地址范圍。其中動(dòng)態(tài)鏈接庫(kù)是程序運(yùn)行時(shí)動(dòng)態(tài)加載的而其加載地址也是每次可能不一樣的褪测。

signal

Linux中的信號(hào)是一種消息處理機(jī)制, 它本質(zhì)上是一個(gè)整數(shù)猴誊,不同的信號(hào)對(duì)應(yīng)不同的值潦刃,由于信號(hào)的結(jié)構(gòu)簡(jiǎn)單所以天生不能攜帶很大的信息量,但是信號(hào)在系統(tǒng)中的優(yōu)先級(jí)是非常高的稠肘。

Linux中的很多常規(guī)操作中都會(huì)有相關(guān)的信號(hào)產(chǎn)生福铅,先從我們最熟悉的場(chǎng)景說起: 通過鍵盤操作產(chǎn)生了信號(hào):用戶按下Ctrl-C萝毛,這個(gè)鍵盤輸入產(chǎn)生一個(gè)硬件中斷项阴,使用這個(gè)快捷鍵會(huì)產(chǎn)生信號(hào), 這個(gè)信號(hào)會(huì)殺死對(duì)應(yīng)的某個(gè)進(jìn)程。
通過shell命令產(chǎn)生了信號(hào):通過kill命令終止某一個(gè)進(jìn)程笆包,kill -9 進(jìn)程PID环揽。
通過函數(shù)調(diào)用產(chǎn)生了信號(hào):如果CPU當(dāng)前正在執(zhí)行這個(gè)進(jìn)程的代碼調(diào)用,比如函數(shù) sleep()庵佣,進(jìn)程收到相關(guān)的信號(hào)歉胶,被迫掛起。
通過對(duì)硬件進(jìn)行非法訪問產(chǎn)生了信號(hào):正在運(yùn)行的程序訪問了非法內(nèi)存巴粪,發(fā)生段錯(cuò)誤通今,進(jìn)程退出。

信號(hào)也可以實(shí)現(xiàn)進(jìn)程間通信肛根,但是信號(hào)能傳遞的數(shù)據(jù)量很少辫塌,不能滿足大部分需求,另外信號(hào)的優(yōu)先級(jí)很高派哲,并且它對(duì)應(yīng)的處理動(dòng)作是回調(diào)完成的臼氨,它會(huì)打亂程序原有的處理流程,影響到最終的處理結(jié)果芭届。因此非常不建議使用信號(hào)進(jìn)行進(jìn)程間通信储矩。

通過 kill -l 命令可以查看系統(tǒng)定義的信號(hào)列表。

進(jìn)程對(duì)信號(hào)的處理可以有以下三種措施:

  1. 忽略這個(gè)信號(hào)褂乍;

  2. 執(zhí)行用戶定義相應(yīng)操作持隧;

  3. 執(zhí)行默認(rèn)的操作;

SIGKILLSIGTSTOP是不可以被信號(hào)處理函數(shù)捕捉或者忽略逃片。

常用接口:

函數(shù)名 備注
signal 信號(hào)安裝函數(shù)舆蝴,但是有消息重入問題,不建議使用
sigaction 信號(hào)安裝函數(shù)
kill 給指定進(jìn)程發(fā)送信號(hào)
raise 給自己發(fā)送信號(hào)题诵,和kill(getpid( ),sig)等價(jià)
alarm 設(shè)置定時(shí)器洁仗,定時(shí)器超時(shí)后,發(fā)送一個(gè)SIGALRM信號(hào)

例子:

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
void catch_signal(int sig)
 {
    switch(sig)
    {
        case SIGINT:printf("get SIGINT signal\n");    
    }

}

int main (int argc,char *argv[ ])
{
    signal(SIGINT,catch_signal);
    int i = 0;
    while(1)
    {
        sleep(100);//執(zhí)行完信號(hào)后sleep()立即返回性锭,不會(huì)一直休眠下去
        printf("hello i = %d",i++);
    }
    return 0;
}
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
int temp = 0;

void handler_sigint(int signo)
{
    printf("recv SIGINT\n");
    sleep(5);
    temp += 1;
    printf("the value of temp is:%d\n",temp);
    printf("in handler_sigint, after sleep\n");
}

int main()
{
    struct sigaction act;
    act.sa_handler = handler_sigint;
    act.sa_flags = SA_NOMASK;
    sigaction(SIGINT, &act, NULL);
    while(1);
    return 0;
}

objdump

objdump -d可以將目標(biāo)文件赠潦、動(dòng)態(tài)庫(kù)、可執(zhí)行文件反匯編草冈,如下:

00000000000006da <swap>:
 6da:   55                      push   %rbp
 6db:   48 89 e5                mov    %rsp,%rbp
 6de:   48 89 7d e8             mov    %rdi,-0x18(%rbp)
 6e2:   48 89 75 e0             mov    %rsi,-0x20(%rbp)
 6e6:   48 8b 45 e8             mov    -0x18(%rbp),%rax
 6ea:   8b 00                   mov    (%rax),%eax
 6ec:   89 45 fc                mov    %eax,-0x4(%rbp)
 6ef:   48 8b 45 e0             mov    -0x20(%rbp),%rax
 6f3:   8b 10                   mov    (%rax),%edx
 6f5:   48 8b 45 e8             mov    -0x18(%rbp),%rax
 6f9:   89 10                   mov    %edx,(%rax)
 6fb:   48 8b 45 e0             mov    -0x20(%rbp),%rax
 6ff:   8b 55 fc                mov    -0x4(%rbp),%edx
 702:   89 10                   mov    %edx,(%rax)
 704:   90                      nop
 705:   5d                      pop    %rbp
 706:   c3                      retq   

00000000000006da是函數(shù)的地址她奥,<swap>是函數(shù)名瓮增,整個(gè)匯編文件分為三列,分別是指令地址哩俭、指令機(jī)器碼绷跑、指令機(jī)器碼反匯編得到的指令。

strip

實(shí)際項(xiàng)目中凡资,許多組件編譯后砸捏,都會(huì)使用strip命令減小目標(biāo)文件的大小,處理后的文件依然可以正常運(yùn)行隙赁,但是其中的符號(hào)信息(比如函數(shù)名)會(huì)失去垦藏。出問題后不利于定位。

解決方法是在編譯(gcc -c)階段加入-rdynamic選項(xiàng)伞访,此方法會(huì)將函數(shù)名加入到*.dyn節(jié)中掂骏,strip對(duì)其無效。

backtrace

在Linux上的C/C++編程環(huán)境下厚掷,我們可以通過如下三個(gè)函數(shù)來獲取程序的調(diào)用棧信息弟灼。

#include <execinfo.h>
/* Store up to SIZE return address of the current program state in
   ARRAY and return the exact number of values stored.  */
int backtrace(void **array, int size);
 
/* Return names of functions from the backtrace list in ARRAY in a newly
   malloc()ed memory block.  */
char **backtrace_symbols(void *const *array, int size);
 
/* This function is similar to backtrace_symbols() but it writes the result
   immediately to a file.  */
void backtrace_symbols_fd(void *const *array, int size, int fd);

使用它們的時(shí)候有一下幾點(diǎn)需要我們注意的地方:

  • backtrace的實(shí)現(xiàn)依賴于棧指針(fp寄存器),在gcc編譯過程中任何非零的優(yōu)化等級(jí)(-On參數(shù))或加入了棧指針優(yōu)化參數(shù)-fomit-frame-pointer后多將不能正確得到程序棧信息冒黑;
  • backtrace_symbols的實(shí)現(xiàn)需要符號(hào)名稱的支持田绑,在gcc編譯過程中需要加入-rdynamic參數(shù);
  • 內(nèi)聯(lián)函數(shù)沒有棧幀薛闪,它在編譯過程中被展開在調(diào)用的位置辛馆;
  • 尾調(diào)用優(yōu)化(Tail-call Optimization)將復(fù)用當(dāng)前函數(shù)棧,而不再生成新的函數(shù)棧豁延,這將導(dǎo)致棧信息不能正確被獲取昙篙。

崩潰定位

在程序崩潰時(shí),系統(tǒng)會(huì)發(fā)送信號(hào)诱咏,在注冊(cè)的信號(hào)處理函數(shù)中苔可,將進(jìn)程的maps文件保存下來,同時(shí)記錄此時(shí)的函數(shù)調(diào)用鏈袋狞,利用這些信息就可以進(jìn)行故障定位焚辅。前提是需要添加編譯選項(xiàng)-g(不加也沒事,不過用addr2line獲得崩潰代碼的行號(hào)需要)苟鸯,鏈接選項(xiàng)-rdynamic一定要加) 同蜻。

在可執(zhí)行文件中崩潰

在64位Linux上編譯運(yùn)行example下的test,程序崩潰:

hello world
segmentfault addr 0x55daa333903e
=========>>>maps <<<=========
55daa3338000-55daa333a000 r-xp 00000000 08:01 24786361  /example/test
55daa3539000-55daa353a000 r--p 00001000 08:01 24786361  /example/test
55daa353a000-55daa353b000 rw-p 00002000 08:01 24786361  /example/test
55daa3e40000-55daa3e61000 rw-p 00000000 00:00 0         [heap]
7f09107eb000-7f09109d2000 r-xp 00000000 08:01 10490449  /lib/x86_64-linux-gnu/libc-2.27.so
7f09109d2000-7f0910bd2000 ---p 001e7000 08:01 10490449  /lib/x86_64-linux-gnu/libc-2.27.so
7f0910bd2000-7f0910bd6000 r--p 001e7000 08:01 10490449  /lib/x86_64-linux-gnu/libc-2.27.so
7f0910bd6000-7f0910bd8000 rw-p 001eb000 08:01 10490449  /lib/x86_64-linux-gnu/libc-2.27.so
7f0910bd8000-7f0910bdc000 rw-p 00000000 00:00 0 
7f0910bdc000-7f0910c03000 r-xp 00000000 08:01 10490421  /lib/x86_64-linux-gnu/ld-2.27.so
7f0910de4000-7f0910de6000 rw-p 00000000 00:00 0 
7f0910e03000-7f0910e04000 r--p 00027000 08:01 10490421  /lib/x86_64-linux-gnu/ld-2.27.so
7f0910e04000-7f0910e05000 rw-p 00028000 08:01 10490421  /lib/x86_64-linux-gnu/ld-2.27.so
7f0910e05000-7f0910e06000 rw-p 00000000 00:00 0 
7ffc3e767000-7ffc3e788000 rw-p 00000000 00:00 0         [stack]
7ffc3e79e000-7ffc3e7a1000 r--p 00000000 00:00 0         [vvar]
7ffc3e7a1000-7ffc3e7a3000 r-xp 00000000 00:00 0         [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]

=========>>>catch signal 11 <<<=========   # 信號(hào)11是段錯(cuò)誤
Dump stack start...
backtrace() returned 7 addresses
  [00] ./test(dump+0x2e) [0x55daa3338d98]
  [01] ./test(signal_handler+0xb8) [0x55daa3338f2a]
  [02] /lib/x86_64-linux-gnu/libc.so.6(+0x3ef20) [0x7f0910829f20]
  [03] ./test(segmentfault+0x3a) [0x55daa3339078]   #這里崩潰
  [04] ./test(main+0x36) [0x55daa3338f9c]
  [05] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xe7) [0x7f091080cb97]
  [06] ./test(_start+0x2a) [0x55daa3338c8a]
Dump stack end...
Segmentation fault (core dumped)

由于64位系統(tǒng)運(yùn)行的可執(zhí)行文件的符號(hào)表地址和實(shí)際運(yùn)行時(shí)地址差異甚大早处。

崩潰地址0x55daa3339078是動(dòng)態(tài)映射的虛擬地址湾蔓,該虛擬地址是通過符號(hào)表地址+該代碼段映射區(qū)間(maps里面有)的地址得來的。

0x55daa3339078落在區(qū)間55daa3338000-55daa333a000

得到真正的符號(hào)表地址0x55daa3339078-0x55daa3338000=0x1078

daniel@daniel:~/example$  addr2line -e test 1078
~/example/calc.c:44

32位系統(tǒng)顯示的是實(shí)際地址砌梆,可以不用轉(zhuǎn)換默责。

上面是獲得符號(hào)表地址的一種方法贬循,也可以使用objdump -d testtest反匯編找到segmentfault的地址:

000000000000103e <segmentfault>:
    103e:   55                      push   %rbp
    103f:   48 89 e5                mov    %rsp,%rbp
    1042:   48 83 ec 10             sub    $0x10,%rsp
    1046:   48 8d 35 f1 ff ff ff    lea    -0xf(%rip),%rsi   # 103e <segmentfault>
    104d:   48 8d 3d b1 01 00 00    lea    0x1b1(%rip),%rdi  # 1205 <_IO_stdin_used+0xe5>
    1054:   b8 00 00 00 00          mov    $0x0,%eax
    1059:   e8 a2 fb ff ff          callq  c00 <printf@plt>
    105e:   c7 45 f0 0a 00 00 00    movl   $0xa,-0x10(%rbp)
    1065:   c7 45 f4 00 00 00 00    movl   $0x0,-0xc(%rbp)
    106c:   48 c7 45 f8 00 00 00    movq   $0x0,-0x8(%rbp)
    1073:   00 
    1074:   48 8b 45 f8             mov    -0x8(%rbp),%rax
    1078:   c7 00 01 00 00 00       movl   $0x1,(%rax)
    107e:   48 8b 45 f8             mov    -0x8(%rbp),%rax
    1082:   8b 10                   mov    (%rax),%edx
    1084:   8b 45 f0                mov    -0x10(%rbp),%eax
    1087:   01 d0                   add    %edx,%eax
    1089:   89 45 f4                mov    %eax,-0xc(%rbp)
    108c:   8b 45 f4                mov    -0xc(%rbp),%eax
    108f:   c9                      leaveq 
    1090:   c3                      retq   
    1091:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
    1098:   00 00 00 
    109b:   0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

真正的符號(hào)表地址為000000000000103e + 0x3a = 0x1078

在動(dòng)態(tài)庫(kù)中崩潰

hello world
add(1,2)=3
segmentfault addr 0x7f7335fb483a

=========>>>maps <<<=========
5631f8167000-5631f8169000 r-xp 00000000 08:01 24786364     /example/test_dynamic
5631f8368000-5631f8369000 r--p 00001000 08:01 24786364     /example/test_dynamic
5631f8369000-5631f836a000 rw-p 00002000 08:01 24786364     /example/test_dynamic
5631f8706000-5631f8727000 rw-p 00000000 00:00 0            [heap]
7f7335bc3000-7f7335daa000 r-xp 00000000 08:01 10490449  /lib/x86_64-linux-gnu/libc-2.27.so
7f7335daa000-7f7335faa000 ---p 001e7000 08:01 10490449  /lib/x86_64-linux-gnu/libc-2.27.so
7f7335faa000-7f7335fae000 r--p 001e7000 08:01 10490449  /lib/x86_64-linux-gnu/libc-2.27.so
7f7335fae000-7f7335fb0000 rw-p 001eb000 08:01 10490449  /lib/x86_64-linux-gnu/libc-2.27.so
7f7335fb0000-7f7335fb4000 rw-p 00000000 00:00 0 
7f7335fb4000-7f7335fb5000 r-xp 00000000 08:01 24786363  /example/libcalc.so
7f7335fb5000-7f73361b4000 ---p 00001000 08:01 24786363  /example/libcalc.so
7f73361b4000-7f73361b5000 r--p 00000000 08:01 24786363  /example/libcalc.so
7f73361b5000-7f73361b6000 rw-p 00001000 08:01 24786363   /example/libcalc.so
7f73361b6000-7f73361dd000 r-xp 00000000 08:01 10490421   /lib/x86_64-linux-gnu/ld-2.27.so
7f73363bb000-7f73363be000 rw-p 00000000 00:00 0 
7f73363db000-7f73363dd000 rw-p 00000000 00:00 0 
7f73363dd000-7f73363de000 r--p 00027000 08:01 10490421   /lib/x86_64-linux-gnu/ld-2.27.so
7f73363de000-7f73363df000 rw-p 00028000 08:01 10490421   /lib/x86_64-linux-gnu/ld-2.27.so
7f73363df000-7f73363e0000 rw-p 00000000 00:00 0 
7fffe6dfd000-7fffe6e1e000 rw-p 00000000 00:00 0                          [stack]
7fffe6fd4000-7fffe6fd7000 r--p 00000000 00:00 0                          [vvar]
7fffe6fd7000-7fffe6fd9000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

=========>>>catch signal 11 <<<=========   # 信號(hào)11是段錯(cuò)誤
Dump stack start...
backtrace() returned 7 addresses
  [00] ./test_dynamic(dump+0x2e) [0x5631f8167cc8]
  [01] ./test_dynamic(signal_handler+0xb8) [0x5631f8167e5a]
  [02] /lib/x86_64-linux-gnu/libc.so.6(+0x3ef20) [0x7f7335c01f20]
  [03] ./libcalc.so(segmentfault+0x3d) [0x7f7335fb4877]   #在動(dòng)態(tài)庫(kù)里面崩潰
  [04] ./test_dynamic(main+0x58) [0x5631f8167eee]
  [05] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xe7) [0x7f7335be4b97]
  [06] ./test_dynamic(_start+0x2a) [0x5631f8167bba]
Dump stack end...
Segmentation fault (core dumped)

同樣地獲得符號(hào)表地址:0x7f7335fb4877 - 0x7f7335fb4000 = 0x877

daniel@daniel:~/example$ addr2line -e libcalc.so 877
/example/calc.c:44

objdump -d libcalc.so獲得segmentfault符號(hào)地址000000000000083a,加上偏移0x3d得到 0x877

000000000000083a <segmentfault>:
 83a:   55                      push   %rbp
 83b:   48 89 e5                mov    %rsp,%rbp
 83e:   48 83 ec 10             sub    $0x10,%rsp
 842:   48 8b 05 9f 07 20 00    mov    0x20079f(%rip),%rax        # 200fe8 <segmentfault@@Base+0x2007ae>
 849:   48 89 c6                mov    %rax,%rsi
 84c:   48 8d 3d 46 00 00 00    lea    0x46(%rip),%rdi        # 899 <_fini+0x9>
 853:   b8 00 00 00 00          mov    $0x0,%eax
 858:   e8 43 fe ff ff          callq  6a0 <printf@plt>
 85d:   c7 45 f0 0a 00 00 00    movl   $0xa,-0x10(%rbp)
 864:   c7 45 f4 00 00 00 00    movl   $0x0,-0xc(%rbp)
 86b:   48 c7 45 f8 00 00 00    movq   $0x0,-0x8(%rbp)
 872:   00 
 873:   48 8b 45 f8             mov    -0x8(%rbp),%rax
 877:   c7 00 01 00 00 00       movl   $0x1,(%rax)
 87d:   48 8b 45 f8             mov    -0x8(%rbp),%rax
 881:   8b 10                   mov    (%rax),%edx
 883:   8b 45 f0                mov    -0x10(%rbp),%eax
 886:   01 d0                   add    %edx,%eax
 888:   89 45 f4                mov    %eax,-0xc(%rbp)
 88b:   8b 45 f4                mov    -0xc(%rbp),%eax
 88e:   c9                      leaveq 
 88f:   c3                      retq   

參考文獻(xiàn)

  1. 跟我一起寫Makefile
  2. linux進(jìn)程地址空間
  3. /proc/{pid}/maps簡(jiǎn)要分析
  4. Linux利用maps文件和反匯編定位崩潰地址
  5. Linux信號(hào)處理程序的一個(gè)應(yīng)用定位故障
  6. 在Linux中如何利用backtrace信息解決問題
  7. objdump(Linux)反匯編命令使用指南
  8. addr2line 動(dòng)態(tài)庫(kù)
  9. linux64位系統(tǒng) addr2line使用
  10. strip命令介紹
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末桃序,一起剝皮案震驚了整個(gè)濱河市杖虾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌媒熊,老刑警劉巖奇适,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異泛释,居然都是意外死亡滤愕,警方通過查閱死者的電腦和手機(jī)温算,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門怜校,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人注竿,你說我怎么就攤上這事茄茁。” “怎么了巩割?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵裙顽,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我宣谈,道長(zhǎng)愈犹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任闻丑,我火速辦了婚禮漩怎,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嗦嗡。我一直安慰自己勋锤,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布侥祭。 她就那樣靜靜地躺著叁执,像睡著了一般。 火紅的嫁衣襯著肌膚如雪矮冬。 梳的紋絲不亂的頭發(fā)上谈宛,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音胎署,去河邊找鬼吆录。 笑死,一個(gè)胖子當(dāng)著我的面吹牛硝拧,可吹牛的內(nèi)容都是我干的径筏。 我是一名探鬼主播葛假,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼滋恬!你這毒婦竟也來了聊训?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤恢氯,失蹤者是張志新(化名)和其女友劉穎带斑,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體勋拟,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡勋磕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了敢靡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挂滓。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖啸胧,靈堂內(nèi)的尸體忽然破棺而出赶站,到底是詐尸還是另有隱情,我是刑警寧澤纺念,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布贝椿,位于F島的核電站,受9級(jí)特大地震影響陷谱,放射性物質(zhì)發(fā)生泄漏烙博。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一烟逊、第九天 我趴在偏房一處隱蔽的房頂上張望渣窜。 院中可真熱鬧,春花似錦焙格、人聲如沸图毕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)予颤。三九已至,卻和暖如春冬阳,著一層夾襖步出監(jiān)牢的瞬間蛤虐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工肝陪, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留驳庭,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像饲常,于是被迫代替她去往敵國(guó)和親蹲堂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容