linux後臺開發常用除錯工具
一、編譯階段
nm 獲取二進位制檔案包含的符號資訊
strings 獲取二進位制檔案包含的字串常量
strip 去除二進位制檔案包含的符號
readelf 顯示目標檔案詳細資訊
objdump 儘可能反彙編出原始碼
addr2line 根據地址查詢程式碼行
二、執行階段
gdb 強大的除錯工具
ldd 顯示程式需要使用的動態庫和實際使用的動態庫
strace 跟蹤程式當前的系統呼叫
ltrace 跟蹤程式當前的庫函式
time 檢視程式執行時間、使用者態時間、核心態時間
gprof 顯示使用者態各函式執行時間
valgrind 檢查記憶體錯誤
mtrace 檢查記憶體錯誤
三、其他
proc檔案系統
系統日誌
一、編譯階段
nm(獲取二進位制檔案裡面包含的符號)
符號:函式、變數
引數:
-C 把C++函式簽名轉為可讀形式
-A 列出符號名的時候同時顯示來自於哪個檔案。
-a 列出所有符號(這將會把除錯符號也列出來。預設狀態下除錯符號不會被列出)
-l 列出符號在原始碼中對應的行號(指定這個引數後,nm將利用除錯資訊找出檔名以及符號的行號。對於一個已定義符號,將會找出這個符號定義的行號,對於未定義符號,顯示為空)
-n 根據符號的地址來排序(預設是按符號名稱的字母順序排序的)
-u 只列出未定義符號
strings(獲取二進位制檔案裡面的字串常量)
功能:
獲取二進位制檔案裡面的字串常量
用途:
比較重要的是檢查KEY洩露
eg:strings <your_proc> | grep '^.\{16\}$‘ 查詢<your_proc>中是否存在一行有16個字元的行,並顯示出來。
選項:
-a不只是掃描目標檔案初始化和裝載段, 而是掃描整個檔案。
-f在顯示字串之前先顯示檔名。
-n min-len列印至少min-len字元長的字串.預設的是4。
#strings /lib/tls/libc.so.6 | grep GLIBC
GLIBC_2.0
GLIBC_2.1
GLIBC_2.1.1
……
這樣就能看到glibc支援的版本。
strip(去除二進位制檔案裡面包含的符號)
用途:
可執行程式減肥(通常只在已經除錯和測試過的生成模組上,因為不能除錯了)
反編譯、反跟蹤
readelf(顯示目標檔案詳細資訊)
nm 程式可用於列舉符號及其型別和值,但是,要更仔細地研究目標檔案中這些命名段的內容,需要使用功能更強大的工具。其中兩種功能強大的工具是objdump和readelf。
readelf工具使用來顯示一個或多個ELF格式檔案資訊的GNU工具。使用不同的引數可以檢視ELF檔案不同的的資訊。
readelf <option> <elffile>
-a 顯示所有ELF檔案的資訊
-h 顯示ELF檔案的檔案頭
-l 顯示程式頭(program-header)和程式段(segment)和段下面的節
-S 顯示較為詳細的節資訊(section)
-s 顯示符號資訊,
-n 顯示標識資訊(如果有)
-r 顯示重定位資訊(如果有)
-u 顯示展開函式資訊(如果有)
-d 顯示動態節資訊,一般是動態庫的資訊
objdump(儘可能反彙編出原始碼)
objdump –S <exe>
儘可能反彙編出原始碼,尤其當編譯的時候指定了-g引數時,效果比較明顯。
addr2line(根據地址查詢程式碼行)
當某個程式崩潰時,日誌檔案(/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找到對應的程式碼行,很方便。
注意:
1. 該可執行程式用-g編譯,使之帶除錯資訊。
2. 如果crash在一個so裡面,那addr2line不能直接給出程式碼行。
引數:
-a 在顯示函式名或檔案行號前顯示地址
-b 指定二進位制檔案格式
-C 解析C++符號為使用者級的名稱,可指定解析樣式
-e 指定二進位制檔案
-f 同時顯示函式名稱
-s 僅顯示檔案的基本名,而不是完整路徑
-i 展開行內函數
-j 讀取相對於指定節的偏移而不是絕對地址
-p 每個位置都在一行顯示
二、執行階段
除錯程式的常見步驟:
1、確定執行時間主要花在使用者態還是核心態(比較土的一個方法:程式暫時遮蔽daemon()呼叫,hardcode收到n個請求後exit(0),time一下程式……)。
2、如果是使用者態,則使用gprof進行效能分析。
2‘、如果是核心態,則使用strace進行效能分析,另外可以使用其他工具(比如ltrace等)輔助。
ldd(顯示程式需要使用的動態庫和實際使用的動態庫)
# ldd /bin/ls
linux-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)
第一欄:需要用什麼庫;第二欄:實際用哪個庫檔案;第三欄:庫檔案裝載地址。
如果缺少動態庫,就會沒有第二欄。
strace(跟蹤當前系統呼叫)
結果預設輸出到2。
-p <pid> attach到一個程式
-c 最後統計各個system call的呼叫情況
-T 列印system call的呼叫時間
-t/-tt/-ttt 時間格式
-f/-F 跟蹤由fork/vfork呼叫所產生的子程式
-o <file>,將strace的輸出定向到file中。
如:strace -f -o ~/<result_file> <your_proc>
-e expr 指定一個表示式,用來控制如何跟蹤,格式如下:
-e open等價於-e trace=open,表示只跟蹤open呼叫
使用 strace –e open ./prg 來看程式使用了哪些配置檔案或日誌檔案,很方便。
-e trace=<set> 只跟蹤指定的系統呼叫
例如:-e trace=open,close,rean,write表示只跟蹤這四個系統呼叫.
-e trace=file只跟蹤有關檔案操作的系統呼叫
-e trace=process只跟蹤有關程式控制的系統呼叫
-e trace=network跟蹤與網路有關的所有系統呼叫
-e strace=signal 跟蹤所有與系統訊號有關的系統呼叫
-e trace=ipc跟蹤所有與程式通訊有關的系統呼叫
ltrace(跟蹤當前庫函式)
引數和strace很接近
time(檢視程式執行時間、使用者態時間、核心態時間)
# 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(顯示使用者態各函式執行時間)
gprof原理:
在編譯和連結程式的時候(使用 -pg 編譯和連結選項),gcc在你應用程式的每個函式中都加入了一個名為mcount(or“_mcount”, or“__mcount”)的函式,也就是說-pg編譯的應用程式裡的每一個函式都會呼叫mcount, 而mcount會在記憶體中儲存一張函式呼叫圖,並通過函式呼叫堆疊的形式查詢子函式和父函式的地址。這張呼叫圖也儲存了所有與函式相關的呼叫時間,呼叫次數等等的所有資訊。
使用步驟:
1、使用 -pg 編譯和連結應用程式
gcc -pg -o exec exec.c
如果需要庫函式呼叫情況:
gcc -lc_p -gp -o exec exec.c
2、執行應用程式使之生成供gprof 分析的資料gmon.out
3、使用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
以下是引數列表:
%p - insert pid into filename 新增pid
%u - insert current uid into filename 新增當前uid
%g - insert current gid into filename 新增當前gid
%s - insert signal that caused the coredump into the filename 新增導致產生core的訊號
%t - insert UNIX time that the coredump occurred into filename 新增core檔案生成時的unix時間
%h - insert hostname where the coredump happened into filename 新增主機名
%e - insert coredumping executable name into filename 新增命令名
使用gdb檢視core:
gdb <program> <core檔案>
valgrind(檢查記憶體錯誤)
使用步驟:
1、官網下載並安裝valgrind。
2、-g編譯的程式都可以使用。
官網的示例程式碼test.c
1 #include <stdlib.h>
2
3 void f(void)
4 {
5 int* x = malloc(10 * sizeof(int));
6 x[10] = 0; // problem 1: heap block overrun
7 } // problem 2: memory leak -- x not freed
8
9 int main(void)
10 {
11 f();
12 return 0;
13 }
編譯程式gcc -Wall -g -o test test.c
3、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(檢查記憶體錯誤)
mtrace是glibc內提供的工具,原理很簡單,就是把你程式中malloc()和free()的位置全部下來,最後兩輛配對,沒有配對到的就是memory leak。
使用的步驟如下:
1、程式碼中新增mtrace()
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int main(void)
5 {
6 int *p;
7 int i;
8
9 #ifdef DEBUG
10 setenv("MALLOC_TRACE", "./memleak.log", 1);
11 mtrace();
12 #endif
13
14 p=(int *)malloc(1000);
15
16 return 0;
17 }
這段程式碼malloc了一個空間,卻沒有free掉。我們新增9-12行的mtrace呼叫。
2、編譯gcc -g -DDEBUG -o test1 test1.c
3、執行./test1,在目錄裡會發現./memleak.log。
4、使用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 14行沒有對應的free()。
三、其他
proc檔案系統
核心的視窗。
proc檔案系統是一個偽檔案系統,它存在記憶體當中,而不佔用外存空間。
使用者和應用程式可以通過proc得到系統的資訊,並可以改變核心的某些引數。
proc/目錄結構(部分):
cmdline 核心命令列
cpuinfo 關於Cpu資訊
devices 可以用到的裝置(塊裝置/字元裝置)
filesystems 支援的檔案系統
interrupts 中斷的使用
ioports I/O埠的使用
kcore 核心核心映像
kmsg 核心訊息
meminfo 記憶體資訊
mounts 載入的檔案系統
stat 全面統計狀態表
swaps 對換空間的利用情況
version 核心版本
uptime 系統正常執行時間
net 網路資訊
sys 可寫,可以通過它來訪問或修改核心的引數
proc/<pid>/目錄結構(部分):
cmdline 命令列引數
environ 環境變數值
fd 一個包含所有檔案描述符的目錄
mem 程式的記憶體被利用情況
stat 程式狀態
status Process status in human readable form
cwd 當前工作目錄的連結
exe Link to the executable of this process
maps 記憶體映像
statm 程式記憶體狀態資訊
root 連結此程式的root目錄
系統日誌
/var/log/下的日誌檔案:
/var/log/messages 整體系統資訊,其中也包含系統啟動期間的日誌。此外,mail、cron、daemon、kern和auth等內容也記錄在var/log/messages日誌中。
/var/log/auth.log 系統授權資訊,包括使用者登入和使用的許可權機制等。
/var/log/boot.log 系統啟動時的日誌。
/var/log/daemon.log 各種系統後臺守護程式日誌資訊。
/var/log/lastlog 記錄所有使用者的最近資訊。這不是一個ASCII檔案,因此需要用lastlog命令檢視內容。
/var/log/user.log 記錄所有等級使用者資訊的日誌。
/var/log/cron 每當cron程式開始一個工作時,就會將相關資訊記錄在這個檔案中。
/var/log/wtmp或utmp 登入資訊。
/var/log/faillog 使用者登入失敗資訊。此外,錯誤登入命令也會記錄在本檔案中。
相關文章
- IE, FF, Safari前端開發常用除錯工具前端除錯
- Linux後臺開發工具箱Linux
- linux環境常用的效能監控和協助開發除錯工具Linux除錯
- 常用的 Python 除錯工具,Python開發必讀Python除錯
- 前端開發環境(開發,除錯,測試工具)前端開發環境除錯
- 我常用的 Python 除錯工具Python除錯
- 微信開放平臺高效開發除錯方法除錯
- Linux下的除錯工具Linux除錯
- 我常用的Python除錯工具(二)Python除錯
- [譯]使用開發工具來除錯 Beta 版 WebView除錯WebView
- 移動web開發除錯工具AlloyLever介紹Web除錯
- Linux 端藍芽除錯工具Linux藍芽除錯
- Linux下搭建FFmpeg開發除錯環境Linux除錯
- 我開發的一款PHP線上除錯工具PHP除錯
- 可提高Java開發效能的5款除錯工具Java除錯
- 【linux學習--工具篇】串列埠除錯工具Linux串列埠除錯
- 跨平臺web除錯代理工具---whistleWeb除錯
- Linux GDB 程式除錯工具使用詳解Linux除錯
- postman使用 Android java後端 介面除錯工具PostmanAndroidJava後端除錯
- WEB輔助開發、除錯、效能檢測、調優工具集Web除錯
- ios 除錯工具iOS除錯
- FLEX - 開發環境:除錯Flex開發環境除錯
- linux c之gdb常用斷點除錯總結Linux斷點除錯
- Linux下效能除錯工具運維筆記Linux除錯運維筆記
- 最常用的scrum工具、敏捷開發工具、看板工具Scrum敏捷
- 大資料開發-linux後臺執行,關閉,檢視後臺任務大資料Linux
- 在自己的 app 中使用 Sarfari 開發工具除錯 Web 頁面APP除錯Web
- Ionic DevApp :非常好用的免費官方開發除錯工具devAPP除錯
- 【同行說技術】Python開發、除錯、爬蟲類工具 大全Python除錯爬蟲
- Linux除錯Linux除錯
- Fiddler助力微信開發除錯除錯
- 前端開發移動端除錯前端除錯
- 使用typescript開發除錯nodejsTypeScript除錯NodeJS
- 移動開發真機除錯移動開發除錯
- PHP開發除錯環境建立PHP除錯
- 求golang除錯工具?Golang除錯
- 效能除錯工具——oprofile除錯
- hyperf-admin 釋出啦, 配置化後臺開發工具, 後臺搭建 從此簡單.