linux調試工具glibc的示範分析

來源:互聯網
上載者:User
一)MALLOC_CHECK_GNU的標準庫(glibc)可以通過內建的調試特性對動態記憶體進行調試,它就是MALLOC_CHECK_環境變數,它在預設情況下是不設定的,在老的版本預設這個值為0,新的版本預設值為2,但有一個矛盾,如果設定為空白,它將會列印出長長的跟蹤資訊,這比設為2更詳細.MALLOC_CHECK_有三種設定,即:MALLOC_CHECK_=0 ----- 關閉所有檢查.MALLOC_CHECK_=1 ----- 當有錯誤被探測到時,在標準錯誤輸出(stderr)上列印錯誤資訊.MALLOC_CHECK_=2 ----- 當有錯誤被探測到時,不顯示錯誤資訊,直接進行中斷.我們用下面的小程式做一下測試,來源程式如下:#include <stdio.h>#include <stdlib.h>int main (int argc,char *argv[]){        int i;        char* p = (char *)malloc(10);        char* pt = p;        for (i = 0;i < 10;i++)        {                p[i] = 'z';        }        free (p);        free(pt);        return 0;}gcc double-free.c -o double-free注:這個程式會釋放兩次指標.echo $MALLOC_CHECK_我們在MALLOC_CHECK_預設設定的情況下,執行test程式,輸出如下的資訊: ./test *** glibc detected *** ./test: double free or corruption (fasttop): 0x0890f008 ***======= Backtrace: =========/lib/libc.so.6[0x175f7d]/lib/libc.so.6(cfree+0x90)[0x1795d0]./test[0x80483dc]/lib/libc.so.6(__libc_start_main+0xdc)[0x125dec]./test[0x8048301]======= Memory map: ========00110000-00247000 r-xp 00000000 08:01 3704502    /lib/libc-2.5.so00247000-00249000 r-xp 00137000 08:01 3704502    /lib/libc-2.5.so00249000-0024a000 rwxp 00139000 08:01 3704502    /lib/libc-2.5.so0024a000-0024d000 rwxp 0024a000 00:00 0 00b51000-00b6a000 r-xp 00000000 08:01 3704501    /lib/ld-2.5.so00b6a000-00b6b000 r-xp 00018000 08:01 3704501    /lib/ld-2.5.so00b6b000-00b6c000 rwxp 00019000 08:01 3704501    /lib/ld-2.5.so00bf3000-00bf4000 r-xp 00bf3000 00:00 0          [vdso]00dab000-00db6000 r-xp 00000000 08:01 3704511    /lib/libgcc_s-4.1.1-20070105.so.100db6000-00db7000 rwxp 0000a000 08:01 3704511    /lib/libgcc_s-4.1.1-20070105.so.108048000-08049000 r-xp 00000000 08:01 327681     /root/test08049000-0804a000 rw-p 00000000 08:01 327681     /root/test0890f000-08930000 rw-p 0890f000 00:00 0 b7e00000-b7e21000 rw-p b7e00000 00:00 0 b7e21000-b7f00000 ---p b7e21000 00:00 0 b7f26000-b7f27000 rw-p b7f26000 00:00 0 b7f3b000-b7f3c000 rw-p b7f3b000 00:00 0 bfdcf000-bfde4000 rw-p bfdcf000 00:00 0          [stack]Aborted這裡我們調整MALLOC_CHECK_為0,再次運行程式,如下:export MALLOC_CHECK_=0./test 注:我們看到程式沒有任何輸出.我們將MALLOC_CHECK_調整為1,再次運行程式,如下:export MALLOC_CHECK_=1./test malloc: using debugging hooks*** glibc detected *** ./test: free(): invalid pointer: 0x0811e008 ***注:我們看到每次運行程式都會有malloc: using debugging hooks的輸出,同時程式檢測到free()兩次釋放的問題.我們將MALLOC_CHECK_調整為2,再次運行程式,如下:export MALLOC_CHECK_=2./test Aborted注:我們看到程式只輸出了Aborted,並中斷了程式的運行.二)用mtrace尋找記憶體泄露mtrace是由glibc提供的一個工具,在Redhat中將它打包在glibc-utils包中.我們安裝此包,如下:rpm -ivh /mnt/Server/glibc-utils-2.5-12.i386.rpmmtrace的主要作用是尋找記憶體泄露,為了應用mtrace程式,必須在代碼中使用glibc提供的函數mtrace和muntrace.另外,必須設定一個檔案的名字給環境變數MALLOC_TRACE,因為glibc利用它為mtrace程式儲存資料.當執行完代碼後,資料將會存在這個確認的檔案中,每執行一次程式,這個檔案的內容都會被重寫.我們用下面的代碼進行測試,如下:#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <mcheck.h>int main (int argc,char *argv[]){        setenv("MALLOC_TRACE","output",1);        mtrace();        int i;        char* p = (char *)malloc(10);        char* pt = p;        for (i = 0;i < 10;i++)        {                p[i] = 'z';        }        return 0;}編譯:gcc test.c -o test注:程式用setenv函數設定環境變數MALLOC_TRACE運行程式:./test 這時在目前的目錄下產生了一個名為output的檔案,如下:cat output = Start@ ./test:[0x80483f2] + 0x82ba438 0xa@ /lib/libc.so.6:(clearenv+0x7c)[0xb9910c] - 0x82ba008@ /lib/libc.so.6:(tdestroy+0x47)[0xc39b77] - 0x82ba090@ /lib/libc.so.6:(tdestroy+0x4f)[0xc39b7f] - 0x82ba0b0用mtrace尋找記憶體泄露,它告訴我們memory not freedmtrace output - 0x082ba008 Free 3 was never alloc'd 0xb9910c- 0x082ba090 Free 4 was never alloc'd 0xc39b77- 0x082ba0b0 Free 5 was never alloc'd 0xc39b7fMemory not freed:-----------------   Address     Size     Caller0x082ba438      0xa  at 0x80483f2三)使用memusage收集記憶體統計資料memusage不需要在代碼中做出任何指示.這個工具也來自由glibc-utils包.它以柱形顯示程式佔用了多少記憶體.它預設輸出到標準輸出中,用ASCII文本顯示一個繪成圖畫似的柱形.如下:memusage awk 'BEGIN{print "hello world"}'hello worldMemory usage summary: heap total: 7487, heap peak: 6891, stack peak: 8624         total calls   total memory   failed calls malloc|         58           7487              0realloc|          0              0              0  (nomove:0, dec:0, free:0) calloc|          0              0              0   free|         15            797Histogram for block sizes:    0-15             27  46% ==================================================   16-31              7  12% ============   32-47              2   3% ===   48-63              6  10% ===========   64-79              1   1% =   80-95              1   1% =   96-111             1   1% =  112-127             4   6% =======  160-175             1   1% =  176-191             2   3% ===  192-207             1   1% =  208-223             2   3% ===  384-399             1   1% =  480-495             1   1% = 4000-4015            1   1% = 四)使用Electric Fence檢測記憶體流失Electric Fence用一些巧妙的技術來檢測程式在堆記憶體區上的溢出,不需要用Electric Fence來修改代碼,相反,它提供一個動態庫,這個庫有多個動態分配函數.一個名為ef的指令碼被用來處理環境變數LD_PRELOAD的設定,我們可以用ef命令來調用程式.下面是安裝Electric Fence,如下:rpm -ivh /mnt/Server/ElectricFence-2.2.2-20.2.2.i386.rpm我們下面用一個小程式做測試,原始碼如下:#include <string.h>intmain (int argc, char *argv[]){        int *ptr = new int;        memset(ptr, 0, sizeof(int) + 1);        delete ptr;}編譯:g++ new-corrupt.cpp -o new-corrupt注:這個小程式會導致邊界溢出.執行程式:./new-corrupt注:程式沒有任何指示.我們用ef執行這個程式,如下:ef ./new-corrupt     Electric Fence 2.2.0 Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com>/usr/bin/ef: line 20:  4148 Segmentation fault      ( export LD_PRELOAD=libefence.so.0.0; exec $* )注:此時有輸出資訊,它告訴我們出現了Segmentation {敏感詞}t,並且指明在哪行出現的問題.我們也可以將electric fence和gdb聯用,如下:編譯器,同時指定-g選項g++ -g new-corrupt.cpp -o new-corrupt 用gdb開啟程式,如下:gdb ./new-corruptGNU gdb Red Hat Linux (6.5-16.el5rh)Copyright (C) 2006 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Public License, and you arewelcome to change it and/or distribute copies of it under certain conditions.Type "show copying" to see the conditions.There is absolutely no warranty for GDB.  Type "show warranty" for details.This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".(gdb) set environment LD_PRELOAD libefence.so.0.0              /*設定環境變數LD_PRELOAD為libefence.so.0.0*/(gdb) run                                                      /*運行程式*/Starting program: /root/new-corrupt   Electric Fence 2.2.0 Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com>  Electric Fence 2.2.0 Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com>Program received signal SIGSEGV, Segmentation fault.0x0804849d in main () at new-corrupt.cpp:7                     /*檢查出在調用memset函數時導致越界*/7               memset(ptr, 0, sizeof(int) + 1);(gdb) quit下面我們在gdb中不指定環境變數,我們看到gdb沒有列印出相關的錯誤資訊.gdb ./new-corruptGNU gdb Red Hat Linux (6.5-16.el5rh)Copyright (C) 2006 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Public License, and you arewelcome to change it and/or distribute copies of it under certain conditions.Type "show copying" to see the conditions.There is absolutely no warranty for GDB.  Type "show warranty" for details.This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".(gdb) runStarting program: /root/new-corrupt Program exited normally.

一)MALLOC_CHECK_GNU的標準庫(glibc)可以通過內建的調試特性對動態記憶體進行調試,它就是MALLOC_CHECK_環境變數,它在預設情況下是不設定的,在老的版本預設這個值為0,新的版本預設值為2,但有一個矛盾,如果設定為空白,它將會列印出長長的跟蹤資訊,這比設為2更詳細.MALLOC_CHECK_有三種設定,即:MALLOC_CHECK_=0 ----- 關閉所有檢查.MALLOC_CHECK_=1 ----- 當有錯誤被探測到時,在標準錯誤輸出(stderr)上列印錯誤資訊.MALLOC_CHECK_=2 ----- 當有錯誤被探測到時,不顯示錯誤資訊,直接進行中斷.我們用下面的小程式做一下測試,來源程式如下:#include <stdio.h>#include <stdlib.h>int main (int argc,char *argv[]){        int i;        char* p = (char *)malloc(10);        char* pt = p;        for (i = 0;i < 10;i++)        {                p[i] = 'z';        }        free (p);        free(pt);        return 0;}gcc double-free.c -o double-free注:這個程式會釋放兩次指標.echo $MALLOC_CHECK_我們在MALLOC_CHECK_預設設定的情況下,執行test程式,輸出如下的資訊: ./test *** glibc detected *** ./test: double free or corruption (fasttop): 0x0890f008 ***======= Backtrace: =========/lib/libc.so.6[0x175f7d]/lib/libc.so.6(cfree+0x90)[0x1795d0]./test[0x80483dc]/lib/libc.so.6(__libc_start_main+0xdc)[0x125dec]./test[0x8048301]======= Memory map: ========00110000-00247000 r-xp 00000000 08:01 3704502    /lib/libc-2.5.so00247000-00249000 r-xp 00137000 08:01 3704502    /lib/libc-2.5.so00249000-0024a000 rwxp 00139000 08:01 3704502    /lib/libc-2.5.so0024a000-0024d000 rwxp 0024a000 00:00 0 00b51000-00b6a000 r-xp 00000000 08:01 3704501    /lib/ld-2.5.so00b6a000-00b6b000 r-xp 00018000 08:01 3704501    /lib/ld-2.5.so00b6b000-00b6c000 rwxp 00019000 08:01 3704501    /lib/ld-2.5.so00bf3000-00bf4000 r-xp 00bf3000 00:00 0          [vdso]00dab000-00db6000 r-xp 00000000 08:01 3704511    /lib/libgcc_s-4.1.1-20070105.so.100db6000-00db7000 rwxp 0000a000 08:01 3704511    /lib/libgcc_s-4.1.1-20070105.so.108048000-08049000 r-xp 00000000 08:01 327681     /root/test08049000-0804a000 rw-p 00000000 08:01 327681     /root/test0890f000-08930000 rw-p 0890f000 00:00 0 b7e00000-b7e21000 rw-p b7e00000 00:00 0 b7e21000-b7f00000 ---p b7e21000 00:00 0 b7f26000-b7f27000 rw-p b7f26000 00:00 0 b7f3b000-b7f3c000 rw-p b7f3b000 00:00 0 bfdcf000-bfde4000 rw-p bfdcf000 00:00 0          [stack]Aborted這裡我們調整MALLOC_CHECK_為0,再次運行程式,如下:export MALLOC_CHECK_=0./test 注:我們看到程式沒有任何輸出.我們將MALLOC_CHECK_調整為1,再次運行程式,如下:export MALLOC_CHECK_=1./test malloc: using debugging hooks*** glibc detected *** ./test: free(): invalid pointer: 0x0811e008 ***注:我們看到每次運行程式都會有malloc: using debugging hooks的輸出,同時程式檢測到free()兩次釋放的問題.我們將MALLOC_CHECK_調整為2,再次運行程式,如下:export MALLOC_CHECK_=2./test Aborted注:我們看到程式只輸出了Aborted,並中斷了程式的運行.二)用mtrace尋找記憶體泄露mtrace是由glibc提供的一個工具,在Redhat中將它打包在glibc-utils包中.我們安裝此包,如下:rpm -ivh /mnt/Server/glibc-utils-2.5-12.i386.rpmmtrace的主要作用是尋找記憶體泄露,為了應用mtrace程式,必須在代碼中使用glibc提供的函數mtrace和muntrace.另外,必須設定一個檔案的名字給環境變數MALLOC_TRACE,因為glibc利用它為mtrace程式儲存資料.當執行完代碼後,資料將會存在這個確認的檔案中,每執行一次程式,這個檔案的內容都會被重寫.我們用下面的代碼進行測試,如下:#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <mcheck.h>int main (int argc,char *argv[]){        setenv("MALLOC_TRACE","output",1);        mtrace();        int i;        char* p = (char *)malloc(10);        char* pt = p;        for (i = 0;i < 10;i++)        {                p[i] = 'z';        }        return 0;}編譯:gcc test.c -o test注:程式用setenv函數設定環境變數MALLOC_TRACE運行程式:./test 這時在目前的目錄下產生了一個名為output的檔案,如下:cat output = Start@ ./test:[0x80483f2] + 0x82ba438 0xa@ /lib/libc.so.6:(clearenv+0x7c)[0xb9910c] - 0x82ba008@ /lib/libc.so.6:(tdestroy+0x47)[0xc39b77] - 0x82ba090@ /lib/libc.so.6:(tdestroy+0x4f)[0xc39b7f] - 0x82ba0b0用mtrace尋找記憶體泄露,它告訴我們memory not freedmtrace output - 0x082ba008 Free 3 was never alloc'd 0xb9910c- 0x082ba090 Free 4 was never alloc'd 0xc39b77- 0x082ba0b0 Free 5 was never alloc'd 0xc39b7fMemory not freed:-----------------   Address     Size     Caller0x082ba438      0xa  at 0x80483f2三)使用memusage收集記憶體統計資料memusage不需要在代碼中做出任何指示.這個工具也來自由glibc-utils包.它以柱形顯示程式佔用了多少記憶體.它預設輸出到標準輸出中,用ASCII文本顯示一個繪成圖畫似的柱形.如下:memusage awk 'BEGIN{print "hello world"}'hello worldMemory usage summary: heap total: 7487, heap peak: 6891, stack peak: 8624         total calls   total memory   failed calls malloc|         58           7487              0realloc|          0              0              0  (nomove:0, dec:0, free:0) calloc|          0              0              0   free|         15            797Histogram for block sizes:    0-15             27  46% ==================================================   16-31              7  12% ============   32-47              2   3% ===   48-63              6  10% ===========   64-79              1   1% =   80-95              1   1% =   96-111             1   1% =  112-127             4   6% =======  160-175             1   1% =  176-191             2   3% ===  192-207             1   1% =  208-223             2   3% ===  384-399             1   1% =  480-495             1   1% = 4000-4015            1   1% = 四)使用Electric Fence檢測記憶體流失Electric Fence用一些巧妙的技術來檢測程式在堆記憶體區上的溢出,不需要用Electric Fence來修改代碼,相反,它提供一個動態庫,這個庫有多個動態分配函數.一個名為ef的指令碼被用來處理環境變數LD_PRELOAD的設定,我們可以用ef命令來調用程式.下面是安裝Electric Fence,如下:rpm -ivh /mnt/Server/ElectricFence-2.2.2-20.2.2.i386.rpm我們下面用一個小程式做測試,原始碼如下:#include <string.h>intmain (int argc, char *argv[]){        int *ptr = new int;        memset(ptr, 0, sizeof(int) + 1);        delete ptr;}編譯:g++ new-corrupt.cpp -o new-corrupt注:這個小程式會導致邊界溢出.執行程式:./new-corrupt注:程式沒有任何指示.我們用ef執行這個程式,如下:ef ./new-corrupt     Electric Fence 2.2.0 Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com>/usr/bin/ef: line 20:  4148 Segmentation fault      ( export LD_PRELOAD=libefence.so.0.0; exec $* )注:此時有輸出資訊,它告訴我們出現了Segmentation {敏感詞}t,並且指明在哪行出現的問題.我們也可以將electric fence和gdb聯用,如下:編譯器,同時指定-g選項g++ -g new-corrupt.cpp -o new-corrupt 用gdb開啟程式,如下:gdb ./new-corruptGNU gdb Red Hat Linux (6.5-16.el5rh)Copyright (C) 2006 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Public License, and you arewelcome to change it and/or distribute copies of it under certain conditions.Type "show copying" to see the conditions.There is absolutely no warranty for GDB.  Type "show warranty" for details.This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".(gdb) set environment LD_PRELOAD libefence.so.0.0              /*設定環境變數LD_PRELOAD為libefence.so.0.0*/(gdb) run                                                      /*運行程式*/Starting program: /root/new-corrupt   Electric Fence 2.2.0 Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com>  Electric Fence 2.2.0 Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com>Program received signal SIGSEGV, Segmentation fault.0x0804849d in main () at new-corrupt.cpp:7                     /*檢查出在調用memset函數時導致越界*/7               memset(ptr, 0, sizeof(int) + 1);(gdb) quit下面我們在gdb中不指定環境變數,我們看到gdb沒有列印出相關的錯誤資訊.gdb ./new-corruptGNU gdb Red Hat Linux (6.5-16.el5rh)Copyright (C) 2006 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Public License, and you arewelcome to change it and/or distribute copies of it under certain conditions.Type "show copying" to see the conditions.There is absolutely no warranty for GDB.  Type "show warranty" for details.This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".(gdb) runStarting program: /root/new-corrupt Program exited normally.

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.