【 原文由 System_Killer@bbs.ustc.edu.cn[37m 所發(fā)表 】
his is Info file ./gdb.info, produced by Makeinfo-1.63 from the input file gdb.texinfo. START-INFO-DIR-ENTRY * Gdb: (gdb). The GNU debugger. END-INFO-DIR-ENTRY This file documents the GNU debugger GDB. This is Edition 4.12, January 1994, of `Debugging with GDB: the GNU Source-Level Debugger" for GDB Version 4.16. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions. 使用GDB: 本文描述GDB,GNU的原代碼調試器。(這是4.12版1994年一月,GDB版本4。16) * 目錄: * 摘要: GDB的摘要 * 實例: 一個使用實例 * 入門: 進入和退出GDB * 命令: GDB 的命令 * 運行: 在GDB下運行程序 * 停止: 暫停和繼續(xù)執(zhí)行 * 棧: 檢查堆棧 * 原文件: 檢查原文件 * 數據: 檢查數據 * 語言: 用不同的語言來使用GDB * 符號: 檢查符號表 * 更改: 更改執(zhí)行 * GDB的文件 文件 * 對象 指定調試對象 * 控制GDB 控制 * 執(zhí)行序列: 執(zhí)行一序列命令 * Emacs: 使GDB和Emacs一起工作 * GDB的bug: * 命令行編輯: 行編輯 * 使用歷史記錄交互: * 格式化文檔: 如何格式化和打印GDB文檔 * 安裝GDB : * 索引: GDB簡介: ************** 調試器(比如象GDB)能讓你觀察另一個程序在執(zhí)行時的內部活動,或程序出錯時 發(fā)生了什么。 GDB主要能為你做四件事(包括為了完成這些事而附加的功能),幫助你找出程序 中的錯誤。 * 運行你的程序,設置所有的能影響程序運行的東西。 * 保證你的程序在指定的條件下停止。 * 當你程序停止時,讓你檢查發(fā)生了什么。 * 改變你的程序。那樣你可以試著修正某個bug引起的問題,然后繼續(xù)查找另一 個bug. 你可以用GDB來調試C和C++寫的程序。(參考 *C 和C++) 部分支持Modula-2和chill,但現(xiàn)在還沒有這方面的文檔。 調試Pascal程序時,有一些功能還不能使用。 GDB還可以用來調試FORTRAN程序,盡管現(xiàn)在還不支持表達式的輸入,輸出變量, 或類FORTRAN的詞法。 * GDB是"free software",大家都可以免費拷貝。也可以為GDB增加新的功能,不 過可要遵守GNU的許可協(xié)議幺。反正我認為GNU還是比較不錯的:-) 就這句話: Fundamentally, the General Public License is a license which says that you have these freedoms and that you cannot take these freedoms away from anyone else. GDB的作者: Richard Stallman是GDB的始作俑者,另外還有許多別的GNU的成員。許多人 為此作出了貢獻。(都是老外不提也罷,但愿他們不要來找我麻煩:-)) 一個例子: ******************** 當你吃飽了的話,你可以慢慢的把所有的關于GDB文章看完。(嘻嘻,我好象 差不多)然而,一些常用的命令足夠讓你開始在GDB的世界中探險了。Let"s go! 一個最初的GNU"m4"(一個普通的宏處理)展示了一些bug:有時我們會改變缺省的 引用串,這個命令用來捕捉另一個嵌套宏定義出問題了。 這里是GDB的一個例子: 原文中是使用一個叫m4的程序。但很遺憾我找不到這個程序的原代碼, 所以沒有辦法來按照原文來說明。不過反正是個例子,我就拿一個操作系統(tǒng)的 進程調度原碼來說明把,原代碼我會附在后面。 首先這個程序叫os.c是一個模擬進程調度的原程序(也許是個老古董了:-))。 先說明一下如何取得包括原代碼符號的可執(zhí)行代碼。大家有心的話可以去看一下gcc的 man文件(在shell下打man gcc)。gcc -g <原文件.c> -o <要生成的文件名> -g 的意思是生成帶原代碼調試符號的可執(zhí)行文件。 -o 的意思是指定可執(zhí)行文件名。 (gcc 的命令行參數有一大堆,有興趣可以自己去看看。) 反正在linux下把os.c用以上方法編譯連接以后就產生了可供gdb使用的可執(zhí)行文件。 我用gcc -g os.c -o os,產生的可執(zhí)行文檔叫os. 然后打gdb os,就可進入gdb,屏幕提示: GDB is free software and you are welcome to distribute copies of it under certain conditions; type "show copying" to see the conditions. There is absolutely no warranty for GDB; type "show warranty" for details. GDB 4.16, Copyright 1995 Free Software Foundation, Inc... (gdb) (gdb)是提示符,在這提示符下可以輸入命令,直到退出。(退出命令是q/Q) 為了盡量和原文檔說明的命令相符,即使在本例子中沒用的命令我也將演示。 首先我們可以設置gdb的屏幕大小。鍵入: (gdb)set width 70 就是把標準屏幕設為70列。 然后讓我們來設置斷點。設置方法很簡單:break或簡單打b后面加行號或函數名 比如我們可以在main 函數上設斷點: (gdb)break main 或(gdb)b main 系統(tǒng)提示:Breakpoint 1 at 0x8049552: file os.c, line 455. 然后我們可以運行這個程序,當程序運行到main函數時程序就會停止返回到gdb的 提示符下。運行的命令是run或r(gdb中有不少alias,可以看一下help,在gdb下打help) run 后面可以跟參數,就是為程序指定命令行參數。 比如r abcd,則程序就會abcd以作為參數。(這里要說明的是可以用set args來指定參 數)。打入r或run后,程序就開始運行直到進入main的入口停止,顯示: Starting program: <路徑>/os Breakpoint 1, main () at os.c:455 455 Initial(); 這里455 Initial();是將要執(zhí)行的命令或函數。 gdb提供兩種方式:1.單步進入,step into就是跟蹤到函數內啦。命令是step或s 2.單步,next,就是簡單的單步,不會進入函數。命令是next或n 這兩個命令還有別的用法以后再說。 我們用n命令,鍵入: (gdb)n Success forking process# 1 ,pid is 31474 Success forking process# 2 ,pid is 31475 Success forking process# 3 ,pid is 31476 Success forking process# 4 ,pid is 31477 Success forking process# 5 ,pid is 31478 Success forking process# 6 ,pid is 31479 Dispatching Algorithm : FIFO ******************************************************************************** PCB# PID Priority PC State 1 31474 24 0 WAITING 2 31475 19 0 WAITING 3 31476 16 0 WAITING 4 31477 23 0 WAITING 5 31478 22 0 WAITING 6 31479 20 0 WAITING ****************************************************************************** CPU : NO process running IO : No process Waiting CPU!!! 31474 31475 31476 31477 31478 31479 Waiting IO NONE 456 State=WAITING; 最后的一行就是下一句要執(zhí)行的命令。我們現(xiàn)在在另一個函數上加斷點。注意我們 可以用l/list命令來顯示原代碼。這里我們鍵入 (gdb)l 451 main() 452 { 453 int message; 454 455 Initial(); 456 State=WAITING; 457 printf("Use Control-C to halt \n"); 458 signal(SIGALRM,AlarmMessage); 459 signal(SIGINT,InteruptMessage); 460 signal(SIGUSR2,IoMessage); (gdb) l 461 alarm(TimeSlot); 462 for(;;) 463 { 464 message=GetMessage(); 465 switch(message) 466 { 467 case INTERRUPT : printf("Use Control-C t; 468 break; 469 case CHILD_IO: WaitingIo(); 470 break; 顯示了原代碼,現(xiàn)在在AlarmMessage上加斷點。 (gdb) b AlarmMessage Breakpoint 2 at 0x8048ee3: file os.c, line 259. (gdb) 然后我們繼續(xù)運行程序。 (gdb)c c或continue命令讓我們繼續(xù)被中斷的程序。 顯示: Continuing. Use Control-C to halt Breakpoint 2, AlarmMessage () at os.c:259 259 ClearSignal(); 注意我們下一句語句就是ClearSignal(); 我們用s/step跟蹤進入這個函數看看它是干什么的。 (gdb) s ClearSignal () at os.c:227 227 signal(SIGINT,SIG_IGN); 用l命令列出原代碼: (gdb) l 222 } 223 224 225 void ClearSignal() /* Clear other signals */ 226 { 227 signal(SIGINT,SIG_IGN); 228 signal(SIGALRM,SIG_IGN); 229 signal(SIGUSR2,SIG_IGN); 230 } 231 (gdb) 我們可以用s命令繼續(xù)跟蹤?,F(xiàn)在讓我們來試試bt或backtrace命令。這個命令可以 顯示棧中的內容。 (gdb) bt #0 ClearSignal () at os.c:227 #1 0x8048ee8 in AlarmMessage () at os.c:259 #2 0xbffffaec in ?? () #3 0x80486ae in ___crt_dummy__ () (gdb) 大家一定能看懂顯示的意思。棧頂是AlarmMessage,接下來的函數沒有名字--就是 沒有原代碼符號。這顯示了函數調用的嵌套。 好了,我們跟蹤了半天還沒有檢查過變量的值呢。檢查表達式的值的命令是p或print 格式是p <表達式> 讓我們來找一個變量來看看。:-) (gdb)l 1 還記得l的作用嗎?l或list顯示原代碼符號,l或list加<行號>就顯示從<行號>開始的 原代碼。好了找到一個讓我們來看看WaitingQueue的內容 (gdb) p WaitingQueue $1 = {1, 2, 3, 4, 5, 6, 0} (gdb) WaitingQueue是一個數組,gdb還支持結構的顯示, (gdb) p Pcb $2 = {{Pid = 0, State = 0, Prior = 0, pc = 0}, {Pid = 31474, State = 2, Prior = 24, pc = 0}, {Pid = 31475, State = 2, Prior = 19, pc = 0}, { Pid = 31476, State = 2, Prior = 16, pc = 0}, {Pid = 31477, State = 2, Prior = 23, pc = 0}, {Pid = 31478, State = 2, Prior = 22, pc = 0}, { Pid = 31479, State = 2, Prior = 20, pc = 0}} (gdb) 這里可以對照原程序看看。 原文檔里是一個調試過程,不過我想這里我已經把gdb的常用功能介紹了一遍,基本上可以用來調試程序了。:-) |
|