gdb使用

編譯時需添加-gdwarf-2和-g3兩個參數。html

加了-g3的參數後,gcc編譯的時候,會將擴展的debug 信息編譯進二進制文件裏面,包括宏定義信息。web

 

gdb主動生成core文件:  gcore多線程

break if (condition)
例子: break if (testval > 3) (testval能夠是局部變量)app

 

顯示字符串所有長度ide

 set print elements 0 函數

 

整理經常使用的gdb技巧。ui

經常使用命令

經常使用的gdb命令...編碼

啓動gdb

  1. 直接運行spa

    gdb --args prog arg1 arg2
    
  2. 運行gdb後使用run命令線程

    gdb prog
    run arg1 arg2
    
  3. attach到已運行的程序

    gdb --pid ${PID_OF_PROG}
    

ptype

ptype用於顯示Symbol的類型,示例源碼爲:

struct ABC {
    int val;
}

int main() {
    ABC abc;
    return 0;
}

運行gdb:

(gdb) b 7
(gdb) r
(gdb) ptype abc

type = struct XXX {
    int val;
}

ptype能夠輸出表達式的返回類型,具體介紹可參考Examining the Symbol Table

print {type} variable

print(p)能夠按照某種類型輸出變量的值,示例源碼以下:

struct ABC {
    double val;
    int val2;
}

int main() {
    ABC abc;
    abc.val = 1.5;
    abc.val2 = 10;

    void *pAbc = &abc;

    return 0;
}

運行gdb:

(gdb) b 13
(gdb) r

(gdb) p pAbc
$1 = (void *) 0x7fffffffe710

(gdb) p {ABC} 0x7fffffffe710
$2 = {val = 1.5, val2 = 10}

(gdb) p {ABC} pAbc
$3 = {val = 1.5, val2 = 10}

(gdb) p * (ABC*) pAbc
$4 = {val = 1.5, val2 = 10}

(gdb) p {double} pAbc
$5 = 1.5

(gdb) p * (double*) pAbc
$6 = 1.5

(gdb) p {int} (pAbc + sizeof (double))
$7 = 10

(gdb) p * (int*) (pAbc + sizeof (double))
$8 = 10

examine

examine(x)能夠按照必定的格式打印內存地址處的數據,詳細文檔可參考這裏

(gdb) x/{COUNT}{FMT}{SIZE} {ADDRESS}
  • {COUNT}: 打印的數目,默認爲1。
  • {FMT}: 打印的格式1,默認爲上次使用的{FMT}:
    • o(octal): 8進制整數
    • x(hex): 16進制整數
    • d(decimal): 10進制整數
    • u(unsigned decimal): 10進制非負整數
    • t(binary): 2進制整數
    • f(float): 浮點數
    • a(address): 輸出相對於前面最近的符號的偏移
    • i(instruction): 輸出地址處的彙編指令
    • c(char): 字符
    • s(string): c字符串(null-terminated string)
    • z(hex, zero padded on the left): 見說明
  • {SIZE}: 打印的字節數目,默認爲上次使用的{SIZE}:
    • b(byte): 1個字節
    • h(halfword): 2個字節
    • w(word): 4個字節
    • g(giant, 8 bytes): 8個字節
  • {ADDRESS}: 目標地址

幾個例子:

(gdb) x/a 0x401419
0x401419 <main()+113>:  0x55c3c900000000b8

(gdb) x/i 0x40138d
=> 0x40138d <crash(int, double)+41>:    mov    -0x10(%rbp),%eax

(gdb) x/1fg 140737488346064
0x7fffffffdbd0: 10.125

設置源碼目錄

參考Specifying Source Directories,使用dir /path/to/your/sources可在調試時添加一個源碼目錄。

設置字符編碼

gdb默認使用utf-8編碼,能夠使用以下命令修改編碼。

set charset GBK

也可直接在~/.gdbinit裏設置。

線程相關的命令

下面是一些調試多線程程序時經常使用的命令:

  • info threads: 查看線程列表
  • thread 2: 切換到2號線程,線程編號可由info threads得知
  • thread apply all bt: 打印全部線程的堆棧

高級技巧

一些不太廣爲人知的技巧...

加載獨立的調試信息

gdb調試的時候能夠從單獨的符號文件中加載調試信息。

(gdb) exec-file test
(gdb) symbol-file test.debug

test是移除了調試信息的可執行文件, test.debug是被移除後單獨存儲的調試信息。參考stackoverflow上的一個問題,能夠以下分離調試信息:

# 編譯程序,帶調試信息(-g)
gcc -g -o test main.c

# 拷貝調試信息到test.debug
objcopy --only-keep-debug test test.debug

# 移除test中的調試信息
strip --strip-debug --strip-unneeded test

# 而後啓動gdb
gdb -s test.debug -e test

# 或這樣啓動gdb
gdb
(gdb) exec-file test
(gdb) symbol-file test.debug

分離出的調試信息test.debug還能夠連接回可執行文件test中

objcopy --add-gnu-debuglink test.debug test

而後就能夠正經常使用addr2line等須要讀取調試信息的程序了

addr2line -e test 0x401c23

更多內容可閱讀GDB: Debugging Information in Separate Files

在內存和文件系統之間拷貝數據

  1. 將內存數據拷貝到文件裏

    dump binary value file_name variable_name
    dump binary memory file_name begin_addr end_addr
    
  2. 改變內存數據

    使用set命令

執行gdb腳本

經常使用的gdb操做,好比打斷點等能夠放在一個gdb腳本里,而後使用時導入便可。例如:

b main.cpp:15
b test.cpp:18

gdb運行時,使用source命令便可導入

(gdb) source /path/to/breakpoints.txt

或gdb運行時導入

gdb -x /path/to/breakpoints.txt prog

對於每次gdb運行都要調用的腳本,好比設置字符集等,能夠放在~/.gdbinit初始文件裏,這樣每次gdb啓動時都會自動調用。

執行命令並退出

有時候須要gdb執行若干條命令後就當即退出,而不是進入交互界面,這時能夠使用-batch選項。

gdb -ex "set pagination 0" -ex "thread apply all bt" -batch -p $pid

上面的命令打印$pid進程全部線程的堆棧並退出。

自定義命令

參考gdb/Define,能夠在gdb中自定義命令,好比:

(gdb) define hello
(gdb) print "welcome"
(gdb) print "hello $arg0"
(gdb) end

而後如此調用

(gdb) hello world

便可輸出

(gdb) $1 = "welcome"
(gdb) $2 = "hello world"

條件斷點

在條件斷點裏能夠調用標準庫的函數,好比下面這個:

# 若是strA == strB,則在斷點處暫停
(gdb) b main.cpp:255 if strcmp(strA.c_str(), strB.c_str()) == 0

# 仍是上面的場景,直接用string類的compare函數
(gdb) b main.cpp:255 if strA.compare(strB) != 0


gdb的stl調試方法:
 source ./stl-views-1.0.3.gdb    STL的GDB的調試配置


STL的gdb調試命令:
Data type   GDB command   
std::vector<T>    pvector stl_variable   
std::list<T>  plist stl_variable T   
std::map<T,T> pmap stl_variable   
std::multimap<T,T>    pmap stl_variable   
std::set<T>   pset stl_variable T   
std::multiset<T>  pset stl_variable   
std::deque<T> pdequeue stl_variable   
std::stack<T> pstack stl_variable   
std::queue<T> pqueue stl_variable   
std::priority_queue<T>    ppqueue stl_variable   
std::bitset<n>td>  pbitset stl_variable   
std::string pstring stl_variable   
std::widestring pwstring stl_variable 

pmap  var left_var_type right_var_type
pmap (*(CRoleItemAbility*)pRole.m_pItemAbi).m_uNormalPack.m_vItemMap TITEMPOS CUnitItem*
相關文章
相關標籤/搜索