Skip to content
Go back
Table of Contents

GDB 調試入門簡明指南

1. GDB簡介

gdb是gnu debugger的縮寫, 是一款可以用於源碼級和彙編級調試的無圖形界面調試器, 雖然對新手並不算友好, 但是和vim一樣, 都屬於花時間學了就會真香的小工具,學費了就直接拋棄IDE和vscode吧…

2. 源碼級調試

2.1 控制要調試的進程

gdb <executable_file_name>可以啟動調試器, 獲得如下界面

gdb start

  • run可以啟動待調試的可執行文件, 可以簡寫成r. 如果啟動需要帶上命令行參數, 就直接加在後面.

例如r BV1zuCXYfE6z --resolution=1080p --downloader=/usr/bin/curl

  • start可以自動啟動程序, 並在main函數的第一行停下, 若沒有調試信息, 也會完成動態庫加載等準備工作之後停在入口處

  • kill可以殺死正在調試的進程

  • continue可以使程序繼續運行, 直到遇到斷點或崩潰

  • finish可以使程序運行到當前函數結束, 返回調用地點

Notes

gdb的幾乎所有命令都能夠簡寫, 在不具有二義性的情況下可以寫盡量少的字母, 例如run可以寫成r, continue可以寫成c, 也可以使用TAB鍵補全命令

2.2 斷點

gdb的斷點指令是break, 可以只簡寫成b.

  • b <function>: 使程序在進入函數後的第一條語句處停下. 如果是C++代碼, 可以寫出作用域加函數原型, 保證斷點在正確的重載處

  • b <line-number>: 將斷點打在當前文件的對應行號處

  • b <file_name>:<line_number>: 將斷點打在指定文件名稱的指定行號處

  • info breakpoints: 查看斷點信息

  • delete breakpoints <breakpoint number>: 刪除對應標號的斷點, 若沒給出標號, 就刪除所有斷點

2.3 單步運行

單步不進入

next可以單步運行代碼(簡寫n), 不進入下一層的函數內部

單步進入

step可以單步運行代碼(簡寫s), 會進入下一層函數

例如: 當代碼走到auto res...這一行停下時, 鍵入n會進入下一行std::fstream output_file;, 而鍵入s則會進入qrc_decode函數內部

// decode...
auto res = qqmusic::utils::qrc_decode(in_buf, out_buf, qqmusic::utils::qrc_type::local);
std::fstream output_file;
std::string output_file_name = (std::string)argv[i] + ".decode";
ulog(MSG_INFO, "output file is %s", output_file_name.c_str());
output_file.open(output_file_name, std::ios::out);

2.4 查看信息

print

print可以簡寫為p, 可以打印變量的值或表達式的值

print variable

p後面可以加一些修飾來表示以指定的格式輸出內容

  • x: 十六進制顯示

  • d: 十進制顯示

  • u: 十六進制無符號

  • i: 反彙編之後顯示

  • t: 八進制顯示

  • c: 字符格式顯示

  • f: 浮點數格式顯示

  • s: 按C風格字符串顯示

使用案例: p/s str1, 以字符串打印str1變量

x

x指令可以打印內存地址和寄存器中的值. 用法: x/nfu address

  • n 是一個正整數, 指定顯示address向高地址方向打印的內存單元的數量, 不給出就默認一個

  • f 是指定顯示格式的, 和上面p的選項一致, 默認十六進制顯示

  • u 是指定內存單元長度的選項, b表示單字節, h表示雙字節, w表示四字節, g表示八字節

使用案例: x/50wx char_ptr就是十六進制查看char_ptr指向的地址到char_ptr + 50 * 4地址, 也就是char_ptr指向地址偏移200字節內的內容

3. 彙編級調試

在沒有調試信息時gdb仍然可以根據符號表進行調試

3.1 反彙編

  • disassemble <function>可以反彙編指定的函數

  • x/i $rip可以反彙編指令寄存器指向的指令

3.2 彙編級單步執行

  • ni: 彙編級單步不進入(遇到call指令不進入函數)

  • si: 彙編級單步進入(遇到call指令進入函數)

3.3 查看內存與寄存器

  • info register: 簡寫i r, 查看所有寄存器信息

register info

  • 使用x指令查看寄存器和其指向內容—例:x/50wx $rsp查看棧頂指針寄存器向高地址方向的200字節, 4字節一組十六進制顯示

大部分常用的調試技巧其實只有寥寥幾條指令, 讀者稍加練習就能掌握, 並體驗到命令行調試器的優勢.

如果需要更詳細的gdb調試技巧, 可以看看100個gdb小技巧.