來源:李海彬
https://urlify.cn/VF7V7v
符號:函數、變量python
參數:linux
功能:網絡
獲取二進制文件裏面的字符串常量app
用途:函數
比較重要的是檢查KEY泄露工具
eg:strings <your_proc> | grep '^.\{16\}$'
性能
查找<your_proc>中是否存在一行有16個字符的行,並顯示出來。測試
選項:ui
#strings /lib/tls/libc.so.6 | grep GLIBC GLIBC_2.0 GLIBC_2.1 GLIBC_2.1.1……
這樣就能看到glibc支持的版本。this
用途:
可執行程序減肥(一般只在已經調試和測試過的生成模塊上,由於不能調試了)
反編譯、反跟蹤
nm 程序可用於列舉符號及其類型和值,可是,要更仔細地研究目標文件中這些命名段的內容,須要使用功能更強大的工具。其中兩種功能強大的工具是objdump和readelf。
readelf工具使用來顯示一個或多個ELF格式文件信息的GNU工具。使用不一樣的參數能夠查看ELF文件不一樣的的信息。
readelf <option> <elffile>
objdump(儘量反彙編出源代碼)objdump –S <exe>
儘量反彙編出源代碼,尤爲當編譯的時候指定了-g參數時,效果比較明顯。
當某個進程崩潰時,日誌文件(/var/log/messages)中就會給出附加的信息,包括程序終止緣由、故障地址,以及包含程序狀態字(PSW)、通用寄存器和訪問寄存器的簡要寄存器轉儲。
eg:Mar 31 11:34:28 l02 kernel: failing address: 0
若是可執行文件包括調試符號(帶-g編譯的),使用addr2line,能夠肯定哪一行代碼致使了問題。
eg:addr2line –e exe addr
其實gdb也有這個功能,不過addr2line的好處是,不少時候,bug很難重現,咱們手上只有一份crash log。這樣就能夠利用addr2line找到對應的代碼行,很方便。
注意:
參數:
調試程序的常見步驟:
一、肯定運行時間主要花在用戶態仍是內核態(比較土的一個方法:程序暫時屏蔽daemon()調用,hardcode收到n個請求後exit(0),time一下程序……)。
二、若是是用戶態,則使用gprof進行性能分析。
三、若是是內核態,則使用strace進行性能分析,另外可使用其餘工具(好比ltrace等)輔助。
# ldd /bin/lslinux-gate.so.1 => (0xbfffe000)librt.so.1 => /lib/librt.so.1 (0xb7f0a000)libacl.so.1 => /lib/libacl.so.1 (0xb7f04000)libc.so.6 => /lib/libc.so.6 (0xb7dc3000)libpthread.so.0 => /lib/libpthread.so.0 (0xb7dab000)/lib/ld-linux.so.2 (0xb7f1d000)libattr.so.1 => /lib/libattr.so.1 (0xb7da6000)
第一欄:須要用什麼庫;第二欄:實際用哪一個庫文件;第三欄:庫文件裝載地址。
若是缺乏動態庫,就會沒有第二欄。
結果默認輸出到2。
<pid>
attach到一個進程<file>
,將strace的輸出定向到file中。如:strace -f -o ~/<result_file> <your_proc>
使用 strace –e open ./prg
來看程序使用了哪些配置文件或日誌文件,很方便。
<set>
只跟蹤指定的系統調用例如:-e trace=open,close,rean,write
表示只跟蹤這四個系統調用.
參數和strace很接近
# time ps aux | grep 'hi' 1020 21804 0.0 0.0 1888 664 pts/6 S+ 17:46 0:00 grep hi real 0m0.009s user 0m0.000s sys 0m0.004s
注意:
time只跟蹤父進程,因此不能fork
gprof原理:
在編譯和連接程序的時候(使用 -pg 編譯和連接選項),gcc在你應用程序的每一個函數中都加入了一個名爲mcount(or「_mcount」, or「__mcount」)的函數,也就是說-pg編譯的應用程序裏的每個函數都會調用mcount, 而mcount會在內存中保存一張函數調用圖,並經過函數調用堆棧的形式查找子函數和父函數的地址。這張調用圖也保存了全部與函數相關的調用時間,調用次數等等的全部信息。
使用步驟:
一、使用 -pg 編譯和連接應用程序
gcc -pg -o exec exec.c
若是須要庫函數調用狀況:
gcc -lc_p -gp -o exec exec.c
二、執行應用程序使之生成供gprof 分析的數據gmon.out
三、使用gprof 程序分析應用程序生成的數據
gprof exec gmon.out > profile.txt
注意:
程序必須經過正常途徑退出(exit()、main返回),kill無效。對後臺常駐程序的調試——個人比較土方法是,屏蔽daemon()調用,程序hardcode收到n個請求後exit(0)。
有時不太準。
只管了用戶態時間消耗,沒有管內核態消耗。
gdb core exec
(gdb查看core文件) 準備生成core:
啓動程序前,ulimit -c unlimited
,設置core文件不限制大小。(相反,ulimit -c 0
,能夠阻止生成core文件)
默認在可執行程序的路徑,生成的是名字爲core的文件,新的core會覆蓋舊的。
設置core文件名字:
/proc/sys/kernel/core_uses_pid
能夠控制產生的core文件的文件名中是否添加pid做爲擴展,1爲擴展,不然爲0。
proc/sys/kernel/core_pattern
能夠設置格式化的core文件保存位置或文件名,好比原來文件內容是core,能夠修改成:
echo "/data/core/core-%e-%p-%t" > core_pattern
如下是參數列表:
使用gdb查看core:
gdb <program> <core文件>
經常使用命令
使用oprofile進行cpu使用狀況檢測,須要通過初始化、啓動檢測、導出檢測數據、查看檢測結果等步驟,如下爲經常使用的oprofile命令。
初始化
檢測控制
查看檢測結果
linux # opreport CPU: Core 2, speed 2128.07 MHz (estimated) Counted CPU_CLK_UNHALTED events (Clock cycles when not halted) with a unit mask of 0x00 (Unhalted core cycles) count 100000CPU_CLK_UNHAL T.........| samples | %| ------------------------ 31645719 87.6453 no-vmlinux 4361113 10.3592 libend.so 7683 0.1367 libpython2.4.so.1.0 7046 0.1253 op_test
使用步驟:
一、官網下載並安裝valgrind。
二、-g編譯的程序均可以使用。
官網的示例代碼test.c
#include <stdlib.h> void f(void) { int* x = malloc(10 * sizeof(int)); x[10] = 0; // problem 1: heap block overrun } // problem 2: memory leak -- x not freed int main(void) { f(); return 0; }
編譯程序gcc -Wall -g -o test test.c
三、valgrind啓動程序,屏幕輸出結果。
valgrind --tool=memcheck --leak-check=full ./test
注意:
valgrind只能查找堆內存的訪問錯誤,對棧上的對象和靜態對象沒辦法。
valgrind會影響進程性能,聽說可能慢20倍,因此在性能要求高的狀況下,只能使用mtrace這種輕量級的工具了(可是mtrace只能識別簡單的內存錯誤)。
若是程序生成的core的堆棧是錯亂的,那麼基本上是stackoverflow了。這種狀況,能夠經過在編譯的時候,加上 –fstack-protector-all
和 -D_FORTIFY_SOURCE=2
來檢測。Stack-protector-all
會在每一個函數里加上堆棧保護的代碼,並在堆棧上留上指紋。(記錄下,沒用過)
由於valgrind 查不了棧和靜態對象的內存訪問越界,這類問題,能夠經過使用gcc的-fmudflap –lmudflap
來檢測。(記錄下,沒用過)
全局變量的類型不一致的問題,如今還找到比較好的方法,這從另外一個方面說明全局對象不是個好的設計,這給調試帶來了麻煩。
mtrace是glibc內提供的工具,原理很簡單,就是把你程序中malloc()和free()的位置所有下來,最後兩輛配對,沒有配對到的就是memory leak。
使用的步驟以下:
一、代碼中添加mtrace()
#include <stdio.h> #include <stdlib.h> int main(void) { int *p; int i; #ifdef DEBUG setenv("MALLOC_TRACE", "./memleak.log", 1); mtrace(); #endif p=(int *)malloc(1000); return 0; }
這段代碼malloc了一個空間,卻沒有free掉。咱們添加9-12行的mtrace調用。
二、編譯gcc -g -DDEBUG -o test1 test1.c
三、執行./test1
,在目錄裏會發現./memleak.log
。
四、使用mtrace <your_proc> memleak.log
查看信息。
# mtrace test1 memleak.log - 0x0804a008 Free 3 was never alloc'd 0xb7e31cbe - 0x0804a100 Free 4 was never alloc'd 0xb7ec3e3f - 0x0804a120 Free 5 was never alloc'd 0xb7ec3e47 Memory not freed: ----------------- Address Size Caller 0x0804a4a8 0x3e8 at /home/illidanliu/test1.c:14
能夠看到test1.c沒有對應的free()。
內核的窗口。
proc文件系統是一個僞文件系統,它存在內存當中,而不佔用外存空間。
用戶和應用程序能夠經過proc獲得系統的信息,並能夠改變內核的某些參數。
proc/目錄結構(部分):
proc/<pid>/
目錄結構(部分):
/var/log/
下的日誌文件: