Linux 上的 GNU 調試器入門:速成課程
調試是程序員和安全研究人員不可或缺的技能。深入掌握調試可以讓您了解較低級別的可執行文件並捕獲任何潛在的錯誤。
GNU 調試器(通常稱為 GDB)是一種持久的調試實用程序,長期以來一直受到開發人員的信任和使用。在本節中,我們將探討它在 Linux 系統中的應用。
準備示例程序
為了深入研究 GDB 的功能,有必要使用源代碼和調試符號可供檢查的可執行文件來測試它。作為說明性示例,我們將在兩個不同的程序上運行GDB-一個按鍵檢查應用程序和一個在屏幕上顯示消息的多線程程序-一個用C 開發並使用GNU C 編譯器編譯,而另一個則缺少源代碼。
您可以選擇使用任何替代 C 編譯器,前提是您不要刪除可執行文件的元數據,其中包含有關程序來源和編譯過程中所做修改的信息。
為了有效地利用 GDB,您很可能會在自己的應用程序中使用它。因此,必須確保使用帶有“gcc”的“-g”標誌來編譯這些程序,這樣可以包含調試符號。
事實上,當調試符號不存在並且二進製文件已被顯著最小化時,我們必須深入研究應用程序的反彙編代碼。這樣的努力需要對彙編語言的熟練理解和對 Linux 操作系統內內存分配機制的複雜理解,以及對存儲在堆棧和寄存器中的數據的解釋。
在 GDB 中運行程序
或者,您也可以選擇通過鍵入“gdb”後跟所需的命令行參數來啟動 GNU 調試器,這將隨後提示您輸入需要調試的特定目標二進製文件。加載後,您可以通過輸入“run”命令或簡單地使用鍵盤快捷鍵(例如“r”)來繼續執行程序。
為了使程序在需要命令行參數時能夠正確運行,必須在調用時將它們附加到程序標題後面。 GNU 調試器 (GDB) 用於上傳和執行應用程序及其參數的語法結構可概述如下:
gdb <program>
run <args>
或者:
gdb
file <program>
run <args>
使用 GDB 設置斷點
斷點是調試期間有意中斷執行流程的,充當代碼內的預定停止點。通過策略性地放置這些標記,開發人員可以在特定時刻暫停程序的進展,並在每個階段展開時仔細檢查對數據和變量的影響。
當使用 GNU 調試器 (GDB) 來調試包含調試符號的軟件應用程序時,可以選擇兩種設置斷點的方法。其中包括使用特定函數的標題指定斷點或根據代碼中的特定行號指定斷點。對應的語法如下:
break main
break 47
要訪問此調試會話期間當前處於活動狀態的斷點的完整列表,請輸入以下命令:
info breakpoints
要刪除代碼中的特定或所有當前斷點,可以使用命令“delete”(如果刪除一個)或簡單地“delete”(將它們全部刪除)。
delete 2
delete 3-5
GDB 提供了建立條件斷點的能力,這要求程序在執行期間必須滿足特定的條件才能暫停。這種情況可能涉及變量值的更改、無效的函數調用或您喜歡的任何其他條件。以下表示用於指定條件斷點的語法:
break <location> if n == 2
如果您希望在遇到斷點時恢復程序的運行,請輸入“繼續”命令。
continue
單步執行代碼
逐行檢查計算機程序的執行對於理解其對信息的操作至關重要。通過仔細遍歷軟件中的多個功能並仔細檢查數據狀況,人們可以更深入地了解系統執行源代碼中編碼的原理的方式。
該軟件可以通過查明系統故障的根源來對系統故障進行全面分析,同時通過對各個代碼行的精確控制來深入檢查程序功能。順序執行每一行的過程可以通過稱為 GDB 的調試工具中的三種不同方法來實現。
上述指令指示 GNU 調試器 (GDB) 繼續處理相應源文件的後續行,從而能夠在單獨的基礎上全面遍歷代碼庫。
Pycharm REPL 中的“next”命令允許執行當前活動函數中的後續代碼行,之後執行停止。與對單個指令或語句進行操作的“step”命令不同,“next”將整個函數視為連續的代碼塊,從而使用戶能夠不間斷地執行多行。
“finish”命令有效地完成當前函數中剩餘的任何未完成代碼塊的執行,然後停止該過程。
檢查變量
為了通過使用 GDB 在程序執行期間檢查變量值來分析程序邏輯的變化,可以使用以下語法在調試環境中顯示特定變量的當前值:
print <variable>
為了顯示循環內每次迭代時對特定變量的值所做的修改,可以使用“顯示”命令。這種方法對於監控和記錄所述變量值在迭代過程中的進展特別有益。
display <variable>
設置觀察點
觀察點和條件斷點是相互關聯的,因為它們都對程序內的更改做出反應。具體來說,觀察點用於監視源代碼中發生的數據修改。作為說明,當特定變量的內容髮生任何變化時,人們可能希望軟件暫停。使用GDB實現該功能的過程詳細如下:
watch <variable_name>
使用 GDB 進行特定於線程的調試
利用 GDB 調試器,可以對多線程應用程序中的各個線程進行調試操作。作為說明性示例,考慮一個簡潔的 C 程序,它使用多個線程來生成打印消息。
要獲取有關應用程序中活動線程的信息,請使用“info”命令,後跟一個空行。
info threads
為了訪問列表中的特定線程並與之交互,可以利用其在可用選項陣列內的數字位置或索引。這允許根據分配的標識符來選擇和操作所需的線程。
thread 2
在選擇特定線程後,可以利用如前所述的“step”、“next”和“finish”等步進命令逐步遍歷其執行序列。
使用 GDB 進行遠程調試
為了遠程調試另一台設備上託管的軟件應用程序,必須在目標計算機上配置 gdbserver。此過程可以通過利用操作系統中預安裝的包管理工具或使用系統上已安裝的任何其他包管理器來完成。
為了在以 Ubuntu 或 Debian 為基礎的系統上安裝 gdbserver,可以使用高級軟件包工具 (APT) 來實現此目的。
sudo apt install gdbserver
執行安裝過程後,導航到包含二進製文件的目錄並在該位置執行特定命令以啟動 gdbserver 程序的操作。
gdbserver <ip>:<port> <binary>
“gdbserver”應用程序預計會顯示一條消息,指示它已啟動並正在積極偵聽指定端口上的傳入連接。隨後,在另一台設備上,啟動“GDB”軟件的實例,並使用“目標”命令後跟預期查詢對象的具體名稱,與遠程服務器建立連接。
target remote <server_ip>:<port>
編寫 GDB 腳本來自動調試
利用 GDB 腳本,開發人員可以輕鬆地重複執行預先確定的 GDB 命令。因此,無需設置斷點、導航代碼執行和打印變量數據等重複任務,從而簡化了調試過程。通過利用這些腳本,開發人員可以自動執行一系列繁瑣的操作,從而在調試代碼的特定部分時提高工作效率。
這是一個例子:
set logging enabled on
set logging file sample.out
break main
command 1
backtrace
print N
continue
end
quit
在提供的代碼片段中,指示調試工具 GDB 應激活其日誌記錄功能並將生成的日誌存儲在名為“sample.out”的文件中。此外,在程序的主要函數內指定了一個中斷點。
為了執行位於“main”函數開頭的斷點一,請使用 GNU 調試器 (GDB) 執行以下步驟:首先,通過輸入命令“backtrace”啟動回溯。其次,用指令“print N”顯示變量“N”的值。第三,輸入“繼續”繼續執行程序。調試器最初將進行回溯以確定程序流的當前狀態。隨後,它將顯示“N”變量的值。之後,它將恢復執行過程。最後,一旦顯示了所有相關信息,GDB 將優雅地終止其操作。
要執行此腳本,請使用:
gdb -x <script> <binary>
現在您知道如何使用 GDB 調試程序了!
調試是一項至關重要的能力,掌握使用 GDB 進行調試可以顯著增強開發人員的多功能性。 GDB 提供的各種功能(例如逐步導航代碼、放置斷點、有針對性的線程調試等)使其成為在 Linux 操作系統環境中檢查二進製文件時的有效工具。
對於那些尋求在 Windows 操作系統中分析和排除軟件程序故障的人來說,進一步了解 Windbg(Windows 原生集成的調試工具)可能是一個值得考慮的選擇。