DEBUG HACKS 學(xué)習(xí)筆記

作者:edelweiss 日期:2020年3月3日
參考書目:ISBN 978-7-121-14048-8 DEBUG HACKS 中文版


日本人放置蚊香用的“驅(qū)蚊豬”

1. 熱身準(zhǔn)備

1 調(diào)試是什么
2 Debug hacks 的地圖
3 調(diào)試的心得

2. 調(diào)試前的必知必會

4 獲取進程的內(nèi)核轉(zhuǎn)儲

獲取內(nèi)核轉(zhuǎn)儲 (core dump) 的最大好處是陋气,它能保存問題發(fā)生時的狀態(tài)。只要有問題發(fā)生時程序的可執(zhí)行文件和內(nèi)核轉(zhuǎn)儲引润,就可以知道進程當(dāng)時的狀態(tài)巩趁。比如,在不清楚 bug 復(fù)現(xiàn)方法的情況下淳附,或是 bug 極其罕見议慰,又或者 bug 只在特定機器上發(fā)生的情況等,只要獲取內(nèi)核轉(zhuǎn)儲奴曙,那么即使手頭沒有復(fù)現(xiàn)環(huán)境别凹,也能夠進行調(diào)試。

啟用內(nèi)核轉(zhuǎn)儲
大多數(shù) Linux 發(fā)行版默認(rèn)情況下關(guān)閉了內(nèi)核轉(zhuǎn)儲功能洽糟。用 ulimit 命令可以查看當(dāng)前的內(nèi)核轉(zhuǎn)儲功能是否有效炉菲。

-c 選項 表示內(nèi)核轉(zhuǎn)儲文件的大小限制。上例中限制為 0 坤溃,表示內(nèi)核轉(zhuǎn)儲無效拍霜。按照以下方式執(zhí)行 ulimit 命令,即可開啟內(nèi)核轉(zhuǎn)儲浇雹。

hanhan@ubuntu:~/DEBUG$ ulimit -c
0
hanhan@ubuntu:~/DEBUG$ ulimit -c unlimited #這個命令的意思是不限制內(nèi)核轉(zhuǎn)儲的空間大小
hanhan@ubuntu:~/DEBUG$ ulimit -c
unlimited

在設(shè)置成無限制之后沉御,發(fā)生問題時進程的內(nèi)存就可以全部轉(zhuǎn)儲到內(nèi)核轉(zhuǎn)儲文件中。在調(diào)試大量消耗內(nèi)存的進程時昭灵,可能會希望設(shè)置內(nèi)核轉(zhuǎn)儲文件的上限吠裆,這是直接在參數(shù)中指定大小即可。例如烂完,下面的命令設(shè)置上限為 1 GB试疙。

$ ulimit -c 1073741824

樣例程序
segfault.c

#include <stdio.h>

int main(void)
{
    int *a = NULL;
    *a = 0x1;
    return 0;
}

使用 gcc -g 編譯并加入調(diào)試信息。

dongyu@During:~/DEBUG$ gcc -g segfault.c 

在開啟內(nèi)核轉(zhuǎn)儲之后抠蚣,執(zhí)行上面的程序祝旷,確認(rèn)能否生成內(nèi)核轉(zhuǎn)儲。

dongyu@During:~/DEBUG$ ./a.out 
Segmentation fault (core dumped)
dongyu@During:~/DEBUG$ ls
a.out  core  segfault.c

當(dāng)前目錄下已經(jīng)生成了 core 文件,要用 GDB 調(diào)試生成的內(nèi)核轉(zhuǎn)儲文件怀跛,應(yīng)當(dāng)使用以下方式啟動 GDB距贷。

dongyu@During:~/DEBUG$ gdb -c core ./a.out
...
[New LWP 19862]
Core was generated by `./a.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x000056464918d60a in main () at segfault.c:6
6       *a = 0x1;
(gdb) 

segfault.c 的第六行收到了 SIGSEGV 信號。用 GDB list 命令可以查看附近的源代碼。

(gdb) l 5
1   #include <stdio.h>
2   
3   int main(void)
4   {
5       int *a = NULL;
6       *a = 0x1;
7       return 0;
8   }
(gdb) 

由于指針變量的值為 NULL ,所以在解引用空指針的時候收到了信號膛堤。
這是個最簡單的例子,但調(diào)試復(fù)雜程序時阁最,從內(nèi)核轉(zhuǎn)儲入手十分有效。程序越復(fù)雜骇两,就越難判斷接收信號的時候程序作了什么操作速种。此外,如果 bug 很難復(fù)現(xiàn)低千,那么單靠跟蹤源代碼會很難確定原因配阵。在這些情況下,內(nèi)核轉(zhuǎn)儲能將問題發(fā)生時的狀態(tài)原原本本地保存下來示血,有助于確定 bug 原因闸餐。

在專用目錄中生成內(nèi)核轉(zhuǎn)儲
在使用大型文件系統(tǒng)時,會希望將內(nèi)核轉(zhuǎn)儲放在固定的位置矾芙。默認(rèn)情況下會在當(dāng)前目錄中生成,但可能難以弄清文件到低在哪里生成近上。此外剔宪,大量生成的內(nèi)核轉(zhuǎn)儲文件可能會給系統(tǒng)的磁盤空間造成壓力。這種情況下可以準(zhǔn)備內(nèi)核轉(zhuǎn)儲專用分區(qū)壹无,并在該分區(qū)中設(shè)置內(nèi)核轉(zhuǎn)儲文件葱绒,這樣就方便很多。轉(zhuǎn)儲保存位置的完整路徑可以通過 sysctl 變量 kernel.core_pattern 設(shè)置斗锭。假設(shè)在 /etc/sysctl.conf 中這樣設(shè)置地淀。
/etc/sysctl.conf

  1 # DEBUG HACKS 
  2 kernel.core_pattern = /var/core/%t-%e-%p-%c.core
  3 kernel.core_uses_pid = 0  
dongyu@During:~/DEBUG$ sudo sysctl -p

在該狀態(tài)下 sudo 執(zhí)行剛才的 a.out 程序,就會在 /var/core下生成內(nèi)核轉(zhuǎn)儲文件岖是。

dongyu@During:~/DEBUG$ sudo ./a.out 
Segmentation fault
dongyu@During:~/DEBUG$ ls /var/core/
1583486733-a.out-20519-18446744073709551615.core
dongyu@During:~/DEBUG$ sudo ./a.out 
Segmentation fault
dongyu@During:~/DEBUG$ ls
a.out  segfault.c
dongyu@During:~/DEBUG$ ls /var/core/
1583486733-a.out-20519-18446744073709551615.core
dongyu@During:~/DEBUG$ 

kernel.core_pattern 中可以設(shè)置的格式符

格式符 說明
%% %本身
%p 被轉(zhuǎn)儲的進程 ID (PID)
%u 被轉(zhuǎn)儲的進程的真實用戶 ID (read UID)
%g 被轉(zhuǎn)儲進程的真實組 ID (real GID)
%s 引發(fā)轉(zhuǎn)儲的信號編號
%t 轉(zhuǎn)儲時刻 (從 1970年 1 月 1 日 0:00 開始的秒數(shù))
%h 主機名 (同 uname (2) 返回的 nodename)
%e 可執(zhí)行文件名
%c 轉(zhuǎn)儲文件的大小上限 (內(nèi)核版本 2.6.24 以后可以使用)

上例中設(shè)置了 kernel.core_uses_pid=0, 是因為我們改變了文件中 PID 的位置帮毁。如果設(shè)置該值為 1,文件名末尾就會添加.PID豺撑。

使用用戶編寫的程序自動壓縮內(nèi)核轉(zhuǎn)儲文件
啟動整個系統(tǒng)的內(nèi)核轉(zhuǎn)儲功能
利用內(nèi)核轉(zhuǎn)儲掩碼排除共享內(nèi)存

5 GDB 的基本使用方法一

GDB 的基本使用流程
(1) 帶著調(diào)試選項編譯烈疚、構(gòu)建調(diào)試對象
(2) 啟動調(diào)試器 (GDB)
(2-1) 設(shè)置斷點
(2-2)顯示棧幀
(2-3)顯示值
(2-4)繼續(xù)執(zhí)行

準(zhǔn)備
uname.c

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 
  4 
  5 int main(int argc, char* argv[])
  6 {
  7     int a = 10;
  8     int b = 20;
  9     int c = a + b;
 10 
 11     printf("c = %d\n", c);
 12 
 13     for (int i = 1; i < argc; i++ )
 14     {
 15         printf("%s\n", argv[i]);
 16     }                                                                                     
 17 
 18     return 0;
 19 }
~        

通過 gcc 的 -g 選項生成調(diào)試信息

$ gcc -wall -O2 -g 源文件

如果用 configure 腳本生成 makefile, 可以這樣用。
$ ./configure CFLAGS="-Wall -02 -g"
本例實際操作

dongyu@During:~/DEBUG$ gcc -o uname -Wall -g -O2 uname.c 
dongyu@During:~/DEBUG$ ls
uname  uname.c

啟動

dongyu@During:~/DEBUG$ gdb uname 
...
(gdb) 

設(shè)置斷點
可以在函數(shù)名行號上設(shè)置斷點聪轿。程序運行后爷肝,到達(dá)斷點就會自動暫停運行。此時可以查看該時刻的變量值、顯示棧幀灯抛、重新設(shè)置斷點或重新運行等金赦。斷點命令 (break) 可以簡寫為 b 。

格式:
break 函數(shù)名
break 行號
break 文件名:行號
break 文件名:函數(shù)名
break + 偏移量
break *地址

(gdb) break main 
Breakpoint 1 at 0x5a0: file uname.c, line 6.
(gdb) break 9
Breakpoint 2 at 0x5c1: file uname.c, line 9.

設(shè)置好的斷點可以通過 info break 確認(rèn)

(gdb) info break
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000000005a0 in main at uname.c:6
2       breakpoint     keep y   0x00000000000005c1 in main at uname.c:9
(gdb) 

運行
用 run 命令開始運行对嚼。不加參數(shù)只執(zhí)行 run, 就會執(zhí)行到設(shè)置了斷點的位置暫停下來夹抗。可以簡寫為 run 猪半。
在 run 命令后面加上可執(zhí)行程序的參數(shù)

(gdb) run hello world   #參數(shù) 1 hello 參數(shù) 2 world

經(jīng)常用到的一個操作是在 main() 上設(shè)置斷點兔朦,然后執(zhí)行到 main()函數(shù)。start 命令能達(dá)到同樣的效果磨确。

顯示棧幀
backtrace 命令可以在遇到斷點而暫停時顯示棧幀沽甥。該命令簡寫為 bt 。此外乏奥,backtrace 的別名還有 where 和 info stack (簡寫為 info s)摆舟。

格式:
backtrace:顯示所有棧幀。
backtrace N:只顯示開頭 N 個棧幀邓了。
backtrace full N :只顯示最后 N 個 棧幀恨诱。

顯示變量
print 命令可以顯示變量。print 可以簡寫為 p骗炉。

(gdb) print argc
$1 = 3
(gdb) print argv
$2 = (char **) 0x7fffffffe578
(gdb) print argv
$3 = (char **) 0x7fffffffe578
(gdb) print argv[0]
$4 = 0x7fffffffe7bf "/home/dongyu/DEBUG/uname"
(gdb) print argv[1]
$5 = 0x7fffffffe7d8 "hello"
(gdb) 

顯示寄存器
info registers 可以顯示寄存器照宝,簡寫為 info reg。
在寄存器名之前添加 $句葵,即可顯示各個寄存器的內(nèi)容厕鹃。

格式:
p/格式 變量名

顯示寄存器可使用的格式

格式 說明
x 顯示為十六進制數(shù)
d 顯示為十進制數(shù)
u 顯示為無符號十進制數(shù)
o 顯示為八進制數(shù)
t 顯示為二進制數(shù), t 的由來是 two
a 地址
c 顯示為字符 (ASCII)
f 浮點小數(shù)
s 顯示為字符串
i 顯示為機器語言 (僅在顯示內(nèi)存的 X 命令中可用)

單步執(zhí)行
單步執(zhí)行的意思是根據(jù)源代碼一行一行地執(zhí)行乍丈。

執(zhí)行源代碼中一行的命令為 next (簡寫為 n)剂碴。執(zhí)行時如果遇到函數(shù)調(diào)用,可能想執(zhí)行到函數(shù)內(nèi)部轻专,此時可以使用 step (簡寫為 p ) 命令忆矛。

next 命令和 step 命令都是執(zhí)行源代碼中的一行。如果要逐條執(zhí)行匯編指令请垛,可以分別使用 nexti 和 stepi 命令催训。

nexti 命令不會進入函數(shù)內(nèi)部執(zhí)行,而 stepi 命令會宗收。

繼續(xù)運行
調(diào)試時瞳腌,可以使用 continue (簡寫為c) 命令繼續(xù)運行程序。程序會在遇到斷點后再次暫停運行镜雨。如果沒有遇到斷點嫂侍,就會一直運行到結(jié)束儿捧。

格式:
continue
continue 次數(shù)

指定次數(shù)可以忽略斷點。例如挑宠,continue 5 則 5 次遇到斷點不停止菲盾,第6次遇到斷點是才暫停執(zhí)行。

被調(diào)試的程序通常為以下幾種情況之一:

  1. 可以正常結(jié)束各淀。
  2. 由于某種原因異常結(jié)束 (發(fā)生內(nèi)核轉(zhuǎn)儲懒鉴、非法訪問等)
  3. 無法結(jié)束 (死循環(huán)等)
  4. 被掛起 (停止響應(yīng)、死鎖等)
    除了正常結(jié)束之外碎浇,其他情況都需要從頭開始繼續(xù)執(zhí)行临谱,以尋找問題的原因 (調(diào)試)。

監(jiān)視點
大型軟件或大量使用指針的程序中奴璃,很難弄清楚變量在什么地方被改變悉默。要想找到變量在何處被改變,可以使用 watch 命令 (監(jiān)視點, watchpoint)苟穆。

格式:
watch <表達(dá)式>
<表達(dá)式> 發(fā)生變化時暫停運行抄课。
此處 <表達(dá)式> 的意思是常量或變量等。

格式:
awatch <表達(dá)式>
<表達(dá)式> 被訪問雳旅、改變時暫停運行跟磨。

格式:
reatch <表達(dá)式>
<表達(dá)式> 被訪問時暫停運行。

刪除斷點和監(jiān)視點
用 delete (簡寫為d)命令刪除斷點和監(jiān)視斷點攒盈。

格式:
delete <編號>
刪除 <編號> 指示的斷點或監(jiān)視點抵拘。

其他斷點
硬件斷點 (hbreak), 適用于 ROM 空間等無法修改的內(nèi)存區(qū)域中的程序。在有些架構(gòu)中無法使用型豁。
臨時斷點 (tbreak)和臨時硬件斷點 (thbreak), 與斷點 (硬件斷點)相同仑濒,都會在運行到該處時暫停,不同之處就是臨時斷點 (臨時硬件斷點)會在此時被刪除偷遗,所以在只需要停止一次時用起來很方便。

遺憾的是并沒有臨時監(jiān)視點驼壶。

改變變量的值

格式:
set variable <變量>=<表達(dá)式>

該功能可以在運行時隨意修改變量的值氏豌,因此無需修改源代碼就能確認(rèn)各種值的情況。

生成內(nèi)核轉(zhuǎn)儲文件
使用 generate-core-file 可將調(diào)試中的進程生成內(nèi)核轉(zhuǎn)儲文件热凹。

有了內(nèi)核轉(zhuǎn)儲文件和調(diào)試對象泵喘,以后就能查看生成轉(zhuǎn)儲文件時的運行歷史 (寄存器值、內(nèi)存值等)般妙。

6 GDB 的基本使用方法二

attach 到進程
要調(diào)試守護進程 (daemon process )等已經(jīng)啟動的進程纪铺,或者調(diào)試陷入死循環(huán)而無法返回控制臺的進程時,可以使用 attach 命令碟渺。

格式:
attach pid
執(zhí)行這一命令就可以 attach 到進程 ID 為 pid的進程上鲜锚。

條件斷點
有一種斷點只在特定條件下中斷。

格式:
break 斷點 if 條件
這條命令將測試給定的條件,如果為真則暫停運行旺隙。

刪除斷點觸發(fā)條件

格式:
condition 斷點編號

添加斷點觸發(fā)條件

格式:
condition 斷點編號 條件

反復(fù)執(zhí)行

格式:
igore 斷點編號 次數(shù)
在編號指定的斷點蔬捷、監(jiān)視點(watchpoint)或捕獲點(catchpoint)忽略指定的次數(shù)。

continue 命令與 ignore 命令一樣凰兑,也可以指定次數(shù)罕容,達(dá)到指定次數(shù)前,執(zhí)行到斷點時不暫停稿饰,二者的意義是相同的锦秒。

刪除斷點和禁用斷點
用 clear 命令刪除已定義的斷點。
只想臨時禁用斷點的話喉镰,可以使用disable 命令旅择。將禁用的斷點重新啟用,則可使用 enable 命令侣姆。

斷點命令
斷點命令 (commands)可以定義在斷點中斷后自動執(zhí)行的命令生真。

7 GDB 的基本使用方法三

值的歷史
通過 print 命令顯示過的值會記錄在內(nèi)部的值歷史中捺宗。這些值可以在其他表達(dá)式中使用蚜厉。

變量 說明
$ 值歷史的最后一個值
$n 值歷史的第 n 個值
$$ 值歷史的倒數(shù)第 2 個值
$$n 值歷史的倒數(shù)第 n 個值
$_ x 命令顯示過的最后的地址
$__ x 命令顯示過的最后的地址的值
$_exitcode 調(diào)試中的程序的返回代碼
$bpnum 最后設(shè)置的斷點編號

變量
可以隨意定義變量。變量以$開頭昼牛,有英文字母和數(shù)字組成术瓮。

命令歷史
可以將命令歷史保存到文件中。保存命令歷史后贰健,就能在其他調(diào)試會話中重復(fù)利用這些命令(通過箭頭查找以前的命令),十分方便。默認(rèn)命令歷史文件位于./.gdb_history。

初始化文件
Linux 環(huán)境下的初始化文件為.gdbinit载庭。如果存在.gdbinit 文件,GDB 就會在啟動之前將其作為命令文件運行。

命令定義
利用 define 命令可以自定義命令,還可以使用 document 命令給自定義命令添加說明。用 "help 命令名" 可以查看定義的命令匕争。

8 intel 架構(gòu)的基本知識

作為調(diào)試的基本知識,這里簡單介紹一下 CPU 架構(gòu)艘蹋。
字節(jié)序
所謂 Endian,就是多字節(jié)數(shù)據(jù)在內(nèi)存中的排列方式票灰。
例如 0x12345678 這個數(shù)據(jù)女阀,地位數(shù)據(jù)排在內(nèi)存低地址宅荤,高位數(shù)據(jù)排在內(nèi)存高地址,這就叫做小端浸策。

0003 0002 0001 0000
0x12 0x34 0x56 0x78

32 位環(huán)境中的寄存器
通用寄存器有 8 種冯键,分別是 EAX、EBX庸汗、ECX惫确、ESI、EDI蚯舱、EBP改化、ESP,用于邏輯運算枉昏、數(shù)學(xué)運算陈肛、地址計算、內(nèi)存指針等兄裂。

32位環(huán)境中運行基本程序的寄存器

ESP 寄存器用于保存棧指針
某些命令使用特定的寄存器句旱。例如,字符串將 EXC晰奖、ESI 和 EDI 寄存器作為操作數(shù)使用谈撒。

通用寄存器的主要用途

寄存器 用途
EAX 操作數(shù)的運算、結(jié)果
EBX 指向 DS 端中數(shù)據(jù)的指針 (主要端寄存器的用途見表 2-8)
ECX 字符串操作或循環(huán)的計數(shù)器
EDX 輸入輸出指針
ESI 指向 DS 寄存器所指示的段中某個數(shù)據(jù)的指針畅涂,或者是字符串操作中字符串的復(fù)制源 (source)
EDI 指向 ES 寄存器所指示的端中某個數(shù)據(jù)的指針港华,或者是字符串操作中字符串的復(fù)制目的地 (destination)
ESP 棧指針 (SS 段)
EBP 指向棧上數(shù)據(jù)的指針 (SS 段)
CS 代碼段
DS 數(shù)據(jù)段
SS 堆棧段
ES 數(shù)據(jù)段
FS 數(shù)據(jù)段
GS 數(shù)據(jù)段

程序代碼放在代碼段中,數(shù)據(jù)放在數(shù)據(jù)段中午衰,程序所用的棧放在堆棧段中立宜。

但是,通用寄存器的用途并不限于上面所述臊岸,也可以用于一般用途橙数,所以上表只能作為參考。寄存器的結(jié)構(gòu)見下圖帅戒。


通用系統(tǒng)

EFLAGS 寄存器中包含狀態(tài)標(biāo)志 (status flag)灯帮、控制標(biāo)志 (confrol flag)、系統(tǒng)標(biāo)志 (system flag) 等逻住。


EFLAGS 寄存器

EIP (Instruction Pointer)寄存器是 32 位指令指針
其他寄存器有控制寄存器 (CR0~CR4)钟哥、GDTR、IDTR瞎访、TR腻贰、LDTR、調(diào)試寄存器 ( DR0/DR1/DR2/DR3/DR6/DR7 )扒秸、內(nèi)存類型范圍寄存器 MTPP播演、MSR(Model Specific Register)寄存器冀瓦、機器檢查寄存器 (Machine Check Register)、性能監(jiān)視計數(shù)器 (Performance Monitoring Counter)等写烤。


FPU 寄存器
MMX 寄存器和 XMM 寄存器

64 位環(huán)境中的寄存器

64 位環(huán)境中的寄存器

地址
CPU 可以通過內(nèi)存總線訪問到的地址稱為物理地址翼闽。

平坦模型 (flat model)中,內(nèi)存可看做單一洲炊、平坦的連續(xù)地址空間感局,稱為線性地址空間。Linux 采用這種內(nèi)存模型选浑。


平坦模型

分段式內(nèi)存模型 (segment model) 中蓝厌,將內(nèi)存看做被稱為“段”(segment)的獨立地址空間的集合。通過段選擇器和偏移量組成的邏輯地址來訪問段內(nèi)地址古徒。首先用段選擇器識別出要訪問的段拓提,然后通過偏移量找到該段的地址空間中的內(nèi)存 (圖 2-10)。32位模式下最多能指定 16383 個段隧膘,各段的最大大小為 2的32次方 字節(jié)代态。


分段模型

64 位模式采用了平坦模型,因此可以使用 64 位線性地址疹吃。不能使用分段式內(nèi)存模型蹦疑。

數(shù)據(jù)類型
基本數(shù)據(jù)類型包括字節(jié) (8 比特)、字(16 比特)萨驶、雙字(32 比特)歉摧、四字(64比特)、和雙四字(128比特)腔呜。

9 調(diào)試時必須的棧知識

棧 (strack) 是程序存放數(shù)據(jù)的內(nèi)存區(qū)域之一叁温,其特征是 LIFO (Last In First Out)式數(shù)據(jù)結(jié)構(gòu),即后放進去的數(shù)據(jù)先被取出核畴。向棧中存儲數(shù)據(jù)的操作稱為 PUSH, 從棧中取出數(shù)據(jù)的操作稱為 POP 膝但。在保存動態(tài)分配的自動變量時需要使用棧。此外在函數(shù)調(diào)用時谤草,棧還用于傳遞函數(shù)參數(shù)跟束,以及用于保存返回地址和返回值。

示例程序:這個程序?qū)⒚钚袇?shù)傳遞過來的數(shù)字作為終值丑孩,計算 0 到終值之前所有正數(shù)的總和冀宴。

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#define MAX (1UL << 20)

typedef unsigned long long u64;
typedef unsigned int u32;

u32 max_addend = MAX;

u64 sum_till_MAX(u32 n)
{
    u64 sum;
    n++;
    sum = n;

    if (n < max_addend)
        sum += sum_till_MAX(n);
    return sum;
}

int main(int argc, char** argv)
{
    u64 sum = 0;

    if ((argc == 2) && isdigit(*(argv[1])))
        max_addend = strtoul(argv[1], NULL, 0);
    if (max_addend > MAX || max_addend ==  0){
        fprintf(stderr, "Invalid number is specified\n");
        return 1;
    }

    sum = sum_till_MAX(0);
    printf("sum(0..%lu) = %llu\n", max_addend, sum);
    return 0;
}

10 函數(shù)調(diào)用時的參數(shù)傳遞方法 X86_64
11 函數(shù)調(diào)用時的參數(shù)傳遞方法 i386
12 函數(shù)調(diào)用時的參數(shù)傳遞方法 C++
13 怎樣學(xué)習(xí)匯編語言
14 從匯編代碼查找相應(yīng)的源代碼

3. 內(nèi)核調(diào)試的準(zhǔn)備

15 Oops 信息的解讀方法
16 使用 minicom 進行串口連接
17 通過網(wǎng)絡(luò)獲取內(nèi)核消息
18 使用 SysRq 鍵調(diào)試
19 使用 diskdump 獲取內(nèi)核崩潰轉(zhuǎn)儲
20 使用 kdump 獲取內(nèi)核崩潰轉(zhuǎn)儲
21 crash 命令的使用方法
22 死機時利用 IPMI watchdog timer 獲取崩潰轉(zhuǎn)儲
23 用 NMI watchdog 在死機時獲取崩潰轉(zhuǎn)儲
24 內(nèi)核獨有的匯編指令之一
25 內(nèi)核獨有的匯編指令之二

4. 應(yīng)用程序調(diào)試實踐

26 發(fā)生SIGSEGV, 應(yīng)用程序異常停止
27 backtrace 無法正確顯示
28 數(shù)組非法訪問導(dǎo)致內(nèi)存破壞
29 利用監(jiān)視點檢測非法內(nèi)存訪問
30 mallco() 和 free() 發(fā)生故障
31 應(yīng)用程序停止響應(yīng) (死鎖篇)
32 應(yīng)用程序停止響應(yīng) (死循環(huán)篇)

5. 實踐內(nèi)核調(diào)試

33 kernel panic (空指針引用篇)
34 kernel panic (鏈表破壞篇)
35 kernel panic
36 內(nèi)核停止響應(yīng)(死循環(huán)篇)
37 內(nèi)核停止響應(yīng)(自旋鎖篇之一)
38 內(nèi)核停止響應(yīng)(信號量篇之二)
39 內(nèi)核停止響應(yīng)(信號量篇)
40 實時進程停止響應(yīng)
41 運行緩慢的故障
42 CPU 負(fù)載過高的故障

6. 高手們的調(diào)試技術(shù)

43 使用 strace 尋找故障原因的線索
44 objdump 的方便選項
45 Valfrind 的使用方法(基本篇)
46 Valfrind 的使用方法 (實踐篇)
48 使用 jprobes 查看內(nèi)核內(nèi)部的信息
49 使用 kprobes 獲取內(nèi)核內(nèi)部任意位置的信息
50 使用 kprobes 在內(nèi)核內(nèi)部任意位置通過變量名獲取信息
51 使用 KAHO 獲取被編譯器優(yōu)化掉的變量的值
52 使用 systemtap 調(diào)試運行中的內(nèi)核之一
53 使用 systemtap 調(diào)試運行中的內(nèi)核之二
54 /proc/meminfo 中的寶藏
55 用/proc/<PID>/mem 快速讀取進程的內(nèi)存內(nèi)容
56 OOM Killer 的行為和原理
57 錯誤注入
58 利用錯誤注入發(fā)現(xiàn)Linux 內(nèi)核的潛在bug
59 Linux 內(nèi)核的 init 節(jié)
60 解決性能問題
61 利用VMware Vprobe 獲取信息
62 利用 Xen 獲取內(nèi)存轉(zhuǎn)儲
63 理解用 GOT/PLT 調(diào)用函數(shù)的原理
64 調(diào)試 initramfs 鏡像
65 使用 RT Watchdog 檢測失去響應(yīng)的實時進程
66 查看手頭的 x86 機器是否支持 64 位模式
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市温学,隨后出現(xiàn)的幾起案子略贮,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刨肃,死亡現(xiàn)場離奇詭異,居然都是意外死亡箩帚,警方通過查閱死者的電腦和手機真友,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來紧帕,“玉大人盔然,你說我怎么就攤上這事是嗜《焯拢” “怎么了?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵恢准,是天一觀的道長甫题。 經(jīng)常有香客問我坠非,道長,這世上最難降的妖魔是什么盟迟? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任队萤,我火速辦了婚禮矫钓,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘赵辕。我一直安慰自己概龄,他們只是感情好私杜,可當(dāng)我...
    茶點故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布救欧。 她就那樣靜靜地躺著笆怠,像睡著了一般誊爹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上办成,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天迂卢,我揣著相機與錄音桐汤,去河邊找鬼惊科。 笑死,一個胖子當(dāng)著我的面吹牛充活,可吹牛的內(nèi)容都是我干的蜡娶。 我是一名探鬼主播,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼幕随,長吁一口氣:“原來是場噩夢啊……” “哼赘淮!你這毒婦竟也來了睦霎?” 一聲冷哼從身側(cè)響起副女,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎戴陡,沒想到半個月后恤批,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年赋荆,在試婚紗的時候發(fā)現(xiàn)自己被綠了窄潭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片酵颁。...
    茶點故事閱讀 39,754評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡躏惋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出距误,到底是詐尸還是另有隱情准潭,我是刑警寧澤域仇,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布暇务,位于F島的核電站,受9級特大地震影響武鲁,放射性物質(zhì)發(fā)生泄漏蝠检。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一乘盖、第九天 我趴在偏房一處隱蔽的房頂上張望憔涉。 院中可真熱鬧兜叨,春花似錦国旷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽被环。三九已至筛欢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間揣钦,已是汗流浹背冯凹。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工宇姚, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留夫凸,地道東北人夭拌。 一個月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓衷咽,卻偏偏與公主長得像蒜绽,于是被迫代替她去往敵國和親躲雅。 傳聞我的和親對象是個殘疾皇子相赁,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,654評論 2 354

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