新聞中心

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

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

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

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

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

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

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


評論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉