新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > Linux內(nèi)核調(diào)試器內(nèi)幕2

Linux內(nèi)核調(diào)試器內(nèi)幕2

——
作者: 時(shí)間:2007-04-18 來(lái)源: 收藏
我們可以看到 rmqueue() 被 __alloc_pages 調(diào)用,后者接下來(lái)又被 _alloc_pages 調(diào)用,以此類(lèi)推。
每一幀的第一個(gè)雙字(double word)指向下一幀,這后面緊跟著調(diào)用函數(shù)的地址。因此,跟蹤堆棧就變成一件輕松的工作了。
[size=18:6ddc15f4ad]技巧 #3[/size:6ddc15f4ad]
go 命令可以有選擇地以一個(gè)地址作為參數(shù)。如果您想在某個(gè)特定地址處繼續(xù)執(zhí)行,則可以提供該地址作為參數(shù)。另一個(gè)辦法是使用 rm 命令修改指令指針寄存器,然后只要輸入 go。如果您想跳過(guò)似乎會(huì)引起問(wèn)題的某個(gè)特定指令或一組指令,這就會(huì)很有用。但是,請(qǐng)注意,該指令使用不慎會(huì)造成嚴(yán)重的問(wèn)題,系統(tǒng)可能會(huì)嚴(yán)重崩潰。
[size=18:6ddc15f4ad]技巧 #4[/size:6ddc15f4ad]
您可以利用一個(gè)名為 defcmd 的有用命令來(lái)定義自己的命令集。例如,每當(dāng)遇到斷點(diǎn)時(shí),您可能希望能同時(shí)檢查某個(gè)特殊變量、檢查某些寄存器的內(nèi)容并轉(zhuǎn)儲(chǔ)堆棧。通常,您必須要輸入一系列命令,以便能同時(shí)執(zhí)行所有這些工作。defcmd 允許您定義自己的命令,該命令可以包含一個(gè)或多個(gè)預(yù)定義的 KDB 命令。然后只需要用一個(gè)命令就可以完成所有這三項(xiàng)工作。其語(yǔ)法如下:
[code:1:6ddc15f4ad][0]kdb> defcmd name "usage" "help"

[0]kdb> [defcmd] type the commands here

[0]kdb> [defcmd] endefcmd [/code:1:6ddc15f4ad]
例如,可以定義一個(gè)(簡(jiǎn)單的)新命令 hari,它顯示從地址 0xc000000 開(kāi)始的一行內(nèi)存、顯示寄存器的內(nèi)容并轉(zhuǎn)儲(chǔ)堆棧:
[code:1:6ddc15f4ad][0]kdb> defcmd hari "" "no arguments needed"

[0]kdb> [defcmd] md 0xc000000 1

[0]kdb> [defcmd] rd

[0]kdb> [defcmd] md %ebp 1

[0]kdb> [defcmd] endefcmd [/code:1:6ddc15f4ad]
該命令的輸出會(huì)是:
[code:1:6ddc15f4ad][0]kdb> hari

[hari]kdb> md 0xc000000 1

0xc000000 00000001 f000e816 f000e2c3 f000e816

[hari]kdb> rd

eax = 0x00000000 ebx = 0xc0105330 ecx = 0xc0466000 edx = 0xc0466000
....
...

[hari]kdb> md %ebp 1

0xc0467fbc c0467fd0 c01053d2 00000002 000a0200

[0]kdb> [/code:1:6ddc15f4ad]
[size=18:6ddc15f4ad]技巧 #5[/size:6ddc15f4ad]
可以使用 bph 和 bpha 命令(假如體系結(jié)構(gòu)支持使用硬件寄存器)來(lái)應(yīng)用讀寫(xiě)斷點(diǎn)。這意味著每當(dāng)從某個(gè)特定地址讀取數(shù)據(jù)或?qū)?shù)據(jù)寫(xiě)入該地址時(shí),我們都可以對(duì)此進(jìn)行控制。當(dāng)調(diào)試數(shù)據(jù)/內(nèi)存毀壞問(wèn)題時(shí)這可能會(huì)極其方便,在這種情況中您可以用它來(lái)識(shí)別毀壞的代碼/進(jìn)程。
示例
[code:1:6ddc15f4ad]每當(dāng)將四個(gè)字節(jié)寫(xiě)入地址 0xc0204060 時(shí)就進(jìn)入內(nèi)核
[0]kdb> bph 0xc0204060 dataw 4 
在讀取從 0xc000000 開(kāi)始的至少兩個(gè)字節(jié)的數(shù)據(jù)時(shí)進(jìn)入內(nèi)核
[0]kdb> bph 0xc000000 datar 2[/code:1:6ddc15f4ad] 
[size=18:6ddc15f4ad]結(jié)束語(yǔ)[/size:6ddc15f4ad]
對(duì)于執(zhí)行內(nèi)核調(diào)試,KDB 是一個(gè)方便的且功能強(qiáng)大的工具。它提供了各種選項(xiàng),并且使我們能夠分析內(nèi)存內(nèi)容和數(shù)據(jù)結(jié)構(gòu)。最妙的是,它不需要用另一臺(tái)機(jī)器來(lái)執(zhí)行調(diào)試。
[size=18:6ddc15f4ad]參考資料[/size:6ddc15f4ad] 
?請(qǐng)?jiān)?nbsp;Documentation/kdb 目錄中查找 KDB 手冊(cè)頁(yè)。
?有關(guān)設(shè)置串行控制臺(tái)的信息,請(qǐng)查找 Documentation 目錄中的 serial-console.txt。
?請(qǐng)?jiān)?nbsp;SGI 的內(nèi)核項(xiàng)目網(wǎng)站上下載 KDB。
?有關(guān)幾個(gè)基于方案的 Linux 調(diào)試技術(shù)的概述,請(qǐng)閱讀“掌握 Linux 調(diào)試技術(shù)”(developerWorks,2002 年 8 月)。
?教程“編譯 Linux 內(nèi)核”(developerWorks,2000 年 8 月)讓您完整地了解配置、編譯和安裝內(nèi)核的過(guò)程。
?IBM AIX 用戶(hù)可以在 KDB Kernel Debugger and Command 頁(yè)面上獲取有關(guān)用于 AIX 的 KDB 的使用幫助。
?那些尋求有關(guān)調(diào)試 OS/2 信息的讀者應(yīng)該閱讀 IBM 紅皮書(shū) The OS/2 Debugging Handbook(共四卷)的第 II 卷。
?在 developerWorks Linux 專(zhuān)區(qū)中查找更多針對(duì) Linux 開(kāi)發(fā)人員的參考資料。

【發(fā)表回復(fù)】【查看CU論壇原帖】【關(guān)閉】
zhchhui 回復(fù)于:2003-09-15 10:38:56
掌握 Linux 調(diào)試技術(shù) 
內(nèi)容:
常見(jiàn)調(diào)試方法
第 1 種情況:內(nèi)存調(diào)試工具
MEMWATCH
YAMD
Electric Fence
第 2 種情況:使用 strace
第 3 種情況:使用 gdb 和 Oops
kgdb
Oops 分析
kdb
第 4 種情況:使用魔術(shù)鍵控順序獲取反跟蹤
結(jié)束語(yǔ)

zhchhui 回復(fù)于:2003-09-15 10:42:18
在 Linux 上找出并解決程序錯(cuò)誤的主要方法
Steve Best(sbest@us.ibm.com)
JFS 核心小組成員,IBM
2002 年 8 月
您可以用各種方法來(lái)監(jiān)控運(yùn)行著的用戶(hù)空間程序:可以為其運(yùn)行調(diào)試器并單步調(diào)試該程序,添加打印語(yǔ)句,或者添加工具來(lái)分析程序。本文描述了幾種可以用來(lái)調(diào)試在 Linux 上運(yùn)行的程序的方法。我們將回顧四種調(diào)試問(wèn)題的情況,這些問(wèn)題包括段錯(cuò)誤,內(nèi)存溢出和泄漏,還有掛起。
本文討論了四種調(diào)試 Linux 程序的情況。在第 1 種情況中,我們使用了兩個(gè)有內(nèi)存分配問(wèn)題的樣本程序,使用 MEMWATCH 和 Yet Another Malloc Debugger(YAMD)工具來(lái)調(diào)試它們。在第 2 種情況中,我們使用了 Linux 中的 strace 實(shí)用程序,它能夠跟蹤系統(tǒng)調(diào)用和信號(hào),從而找出程序發(fā)生錯(cuò)誤的地方。在第 3 種情況中,我們使用 Linux 內(nèi)核的 Oops 功能來(lái)解決程序的段錯(cuò)誤,并向您展示如何設(shè)置內(nèi)核源代碼級(jí)調(diào)試器(kernel source level debugger,kgdb),以使用 GNU 調(diào)試器(GNU debugger,gdb)來(lái)解決相同的問(wèn)題;kgdb 程序是使用串行連接的 Linux 內(nèi)核遠(yuǎn)程 gdb。在第 4 種情況中,我們使用 Linux 上提供的魔術(shù)鍵控順序(magic key sequence)來(lái)顯示引發(fā)掛起問(wèn)題的組件的信息。
[size=18:b0b26de3a8][b:b0b26de3a8]常見(jiàn)調(diào)試方法[/b:b0b26de3a8][/size:b0b26de3a8]
當(dāng)您的程序中包含錯(cuò)誤時(shí),很可能在代碼中某處有一個(gè)條件,您認(rèn)為它為真(true),但實(shí)際上是假(false)。找出錯(cuò)誤的過(guò)程也就是在找出錯(cuò)誤后推翻以前一直確信為真的某個(gè)條件過(guò)程。
以下幾個(gè)示例是您可能確信成立的條件的一些類(lèi)型: 
?在源代碼中的某處,某變量有特定的值。 
?在給定的地方,某個(gè)結(jié)構(gòu)已被正確設(shè)置。 
?對(duì)于給定的 if-then-else 語(yǔ)句,if 部分就是被執(zhí)行的路徑。 
?當(dāng)子例程被調(diào)用時(shí),該例程正確地接收到了它的參數(shù)。 
找出錯(cuò)誤也就是要確定上述所有情況是否存在。如果您確信在子例程被調(diào)用時(shí)某變量應(yīng)該有特定的值,那么就檢查一下情況是否如此。如果您相信 if 結(jié)構(gòu)會(huì)被執(zhí)行,那么也檢查一下情況是否如此。通常,您的假設(shè)都會(huì)是正確的,但最終您會(huì)找到與假設(shè)不符的情況。結(jié)果,您就會(huì)找出發(fā)生錯(cuò)誤的地方。
調(diào)試是您無(wú)法逃避的任務(wù)。進(jìn)行調(diào)試有很多種方法,比如將消息打印到屏幕上、使用調(diào)試器,或只是考慮程序執(zhí)行的情況并仔細(xì)地揣摩問(wèn)題所在。
在修正問(wèn)題之前,您必須找出它的源頭。舉例來(lái)說(shuō),對(duì)于段錯(cuò)誤,您需要了解段錯(cuò)誤發(fā)生在代碼的哪一行。一旦您發(fā)現(xiàn)了代碼中出錯(cuò)的行,請(qǐng)確定該方法中變量的值、方法被調(diào)用的方式以及關(guān)于錯(cuò)誤如何發(fā)生的詳細(xì)情況。使用調(diào)試器將使找出所有這些信息變得很簡(jiǎn)單。如果沒(méi)有調(diào)試器可用,您還可以使用其它的工具。(請(qǐng)注意,產(chǎn)品環(huán)境中可能并不提供調(diào)試器,而且 Linux 內(nèi)核沒(méi)有內(nèi)建的調(diào)試器。)
[size=18:b0b26de3a8][b:b0b26de3a8]實(shí)用的內(nèi)存和內(nèi)核工具[/b:b0b26de3a8][/size:b0b26de3a8]
您可以使用 Linux 上的調(diào)試工具,通過(guò)各種方式跟蹤用戶(hù)空間和內(nèi)核問(wèn)題。請(qǐng)使用下面的工具和技術(shù)來(lái)構(gòu)建和調(diào)試您的源代碼: 
[size=18:b0b26de3a8][b:b0b26de3a8]用戶(hù)空間工具[/b:b0b26de3a8][/size:b0b26de3a8]: 
?內(nèi)存工具:MEMWATCH 和 YAMD 
?strace 
?GNU 調(diào)試器(gdb) 
?魔術(shù)鍵控順序 
[size=18:b0b26de3a8][b:b0b26de3a8]內(nèi)核工具[/b:b0b26de3a8][/size:b0b26de3a8]: 
?內(nèi)核源代碼級(jí)調(diào)試器(kgdb) 
?內(nèi)建內(nèi)核調(diào)試器(kdb) 
?Oops 
本文將討論一類(lèi)通過(guò)人工檢查代碼不容易找到的問(wèn)題,而且此類(lèi)問(wèn)題只在很少見(jiàn)的情況下存在。內(nèi)存錯(cuò)誤通常在多種情況同時(shí)存在時(shí)出現(xiàn),而且您有時(shí)只能在部署程序之后才能發(fā)現(xiàn)內(nèi)存錯(cuò)誤。


評(píng)論


相關(guān)推薦

技術(shù)專(zhuān)區(qū)

關(guān)閉