GNU偵錯器

GNU偵錯器（GNU Debugger，縮寫：GDB），是GNU軟體系統中的標準偵錯器，此外GDB也是個具有移攜性的偵錯器，經過移攜需求的調修與重新編譯，如今許多的類UNIX作業系統上都可以使用GDB，而現有GDB所能支援除錯的程式語言有C、C++、Pascal以及FORTRAN。

## 歷史

GNU Debugger最初是在1988年由理察·馬修·斯托曼（Richard Stallman）所撰寫，之後以GNU通用公共許可證（GNU General Public License, GNU GPL）的授權方式將軟體釋出，因此GNU Debugger是一套自由軟體。釋出後的1990年－1993年間則由任職於Cygnus Solutions公司的約翰·吉爾摩（John Gilmore）負責後續的軟體維護工作。

## 技術細節

### 特點

GDB具備各種偵錯功效，能針對電腦程式的執行進行追蹤與警告，使用GDB的除錯人員可以監督及修改程式的內部變數值，甚至監督與修改獨立於主程式運作外，以獨立個體型態呼用（呼叫使用）的函式。

GDB能為多種不同處理器架構上執行的軟體進行偵錯，這些處理器架構包括：DEC/COMPAQ/HP的Alpha、ARM的ARM、Hitachi的H8/300、IBM的System/370、System 390、Intel的X86及X86-64、IA-64 "Itanium"、Motorola 68000、MIPS的MIPS、HP的PA-RISC、AIM聯盟的PowerPC、Hitachi/Renesas/ST的SuperH、Sun的SPARC、DEC/COMPAQ/HP的VAX。

此外一些比較少人知的處理器也一樣受GDB支援，包括：AMD的A29K、ARC的ARC、Atmel的AVR、Axis Communications的ETRAX CRIS、D10V、D30V、Fujitsu的FR-30、FR-V、Intel的i960、Renesas的M32R、Motorola的68HC11、Motorola的88000、Freescale的MCORE、MN10200、MN10300、NS32K、Stormy16、V850、以及Zilog的Z8000，此外更後續版本的GDB只會增加更多的處理器支援而不會短少。

GDB的內部已具備了依據各種支援不同處理器的指令集所編譯成的模擬推演程式（Instruction Set Simulator），就連大眾少知少用的M32R、V850等架構的處理器也都具備。

### 遠端偵錯

GDB具有一種「遠端，Remote」模式，此種模式多半是在為嵌入式系統進行偵錯時使用，遠端操作指的是：GDB在一部機器內執行，而要進行偵錯的程式是在另一部機器上執行，接著欲偵錯的機器上會再加裝一個名為「Stub」的小程式，該程式能夠與另一端的GDB程式溝通，溝通的路徑可以是兩部機器間的串接式接線，也可以是支援TCP/IP協定傳輸的各種網路，在TCP/IP網路及協定上再加搭傳輸GDB專有的除錯操作用通訊協定，如此便能進行遠端偵錯。

不僅GDB有遠端模式，KGDB也同樣具有遠端模式，KGDB主要是為執行中的Linux核心進行偵錯，而GDB則是主要是用在原代碼的層次。運用KGDB，負責核心程式的程式設計師可以將核心以近似於應用程式的除錯方式來偵錯，包括為核心程式碼設置中斷點（breakpoint）、讓核心程式以步階方式逐行執行以及觀看變數值等。

在某些架構的處理器中，會以硬體方式提供一些偵錯功用的寄存器，以及可以設定觀察點（Watchpoint），觀察點的功用是：當程式設計師指定的記憶體位址被執行到或訪問到時，觀察點即會去觸發、觸動一個中斷點。對此KGDB可以安裝在一部傳統機器上，並透過遠端模式使用另一部受偵錯機器上的硬體偵錯功效，同樣的兩部機器可用各種方式進行溝通，如串接式接線、乙太網路等，尤其在FreeBSD作業系統上還允許使用FireWire接線，並用直接記憶體訪問（Direct Memory Access，DMA）的功效來協助遠端偵錯。

### 現有限制

GDB運用上最明顯的限制是在「使用者介面」的部分，預設只有命令列介面（CLI）可用，而不具備較能親合上手、直覺操作的圖形化使用者介面（GUI），不過此一弱處也已經有幾個前端程式為其補強，例如DDD、GDBtk／ Insight 以及Emacs中的「GUD 模式」等，有了這些補強後，GDB在功效使用的便利性上就能夠與「整合發展環境中的偵錯功效使用」相接近。

另外，有些偵錯工具（軟體）也被設計成能與GDB搭配使用，例如記憶體洩漏（memory leak）的偵測程式。

## 命令列使用的範例

```
gdb prog.out      debug prog.out
(gdb) run         run
```

## 過程範例

以下是用GDB進行除錯的一段過程示範，欲進行偵錯的程式已在棧追蹤區內：

```
GNU gdb Red Hat Linux (6.3.0.0-1.21rh)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or 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.
This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db
library "/lib/libthread_db.so.1".

(gdb) run
Starting program: /home/sam/programming/crash
Reading symbols from shared object read from target memory...done.
Loaded system supplied DSO at 0xc11000
This program will demonstrate gdb

Program received signal SIGSEGV, Segmentation fault.
0x08048428 in function_2 (x=24) at crash.c:22
22         return *y;
(gdb) edit
(gdb) shell gcc crash.c -o crash -gstabs+
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
warning: cannot close "shared object read from target memory": File in wrong format
`/home/sam/programming/crash' has changed; re-reading symbols.
Starting program: /home/sam/programming/crash
Reading symbols from shared object read from target memory...done.
Loaded system supplied DSO at 0xa3e000
This program will demonstrate gdb
24
Program exited normally.
(gdb) quit
```

這個程式已處在執行階段，之後找出這個程式中會導致執行錯誤的段落，然後將對應處的原代碼用編輯器進行錯誤修訂，更正完成後用GNU 編譯器（GCC）重新編譯並再次執行。

## 參考

- 書籍：Debugging with GDB（在此暫譯成：用GDB進行除錯）
- 出版：2002年，自由軟體基金會（Free Software Foundation，FSF）
- ISBN 1-882114-88-4
- 作者：Richard M. Stallman、Roland Pesch、Stan Shebs及其他所有參與成員

## 外部連結

- GDB的官方網站
- GDB文件："Debugging with GDB，用GDB進行除錯" （線上HTML格式，折算成PDF格式則超過400頁）
- 深入GDB
- 使用GDB進行C及C++程式語言的除錯
- 用來替Linux核心進行除錯的GDB後端程式：KGDB
- Peter Jay Salzman所撰：如何更專精、善用GDB
- GDB內部結構 (The Architecture of Open Source Applications, Volume II - ISBN 9781105571817)

## 基本資料

- 日語原文：GNU Debugger
- 開發者：GNU計劃
- 軟體版本週期：17.2
- 作業系統：類Unix系統、Windows
- 類型：調試工具
- 許可協議：GNU通用公共許可證
- 網站： gnu.org/software/gdb/