[調試技術][GDB] GDB使用概述

前言:

linux環境下幾乎只有gdb可用,windows環境下windbg也是以gdb作爲底部承載,因此gdb的重要作用可見一斑,但gdb作爲基礎套件,其不具備界面展示,因此使用起來不是很方便,這裏對其做簡要的使用說明。

 

前提條件:

使用gdb進行調試必須滿足以下至少一個條件:

1)在編譯時使用了-g選項,那麼得到的二進制文件便是包含調試信息的,那麼此二進制文件是可調試的;

2) 編譯時沒使用-g選項增加調試信息,但有與此二進制文件配套的debuginfo包,那麼可以將此debuginfo包與gdb一起運行,此時相當於把調試信息打入二進制文件中。

注:debuginfo也是在編譯時生成的,通常是通過-g選項生成帶有調試信息的二進制文件,然後再使用objcopy將調試信息從二進制文件中分離出來,後面會介紹objcopy的使用

 

DebugInfo的來龍去脈:

  • debuginfo是指gdb所使用的debug信息,比如使用gcc -g選項,編譯的輸出文件中就會包含debuginfo
  • 一般情況下,都是把debuginfo和可執行文件分開,因爲放在一起,會導致可執行文件過大
  • 如何獲得可執行文件和debuginfo呢?使用如下命令可以
objcopy --only-keep-debug ./a.out a.out.debug    

#這裏拷貝出來,此時可執行文件中還是有debuginfo的,多出來一個.debug文件,原來的a.out大小不變
  • 如果把a.out瘦身呢?使用如下命令可以
objcopy --strip-debug ./a.out(也可以使用strip --strip-debug ./a.out)

#此時,在使用gdb來調試a.out的時候,已經不行了,報錯no debugging symbols found
  • 該怎麼使用debuginfo呢?使用如下命令即可
objcopy --add-gnu-debuglink=a.out.debug ./a.out
	
#此時,在使用gdb來調試a.out,發現可以了
  • 爲什麼加了有debuginfo ,調試的時候有些地方仍然沒有debug信息

 -g 選項默認不會包括一些宏定義的信息。可以在編譯時使用-g3

 

GDB使用細節:

啓動並調試:            gdb program
帶core文件啓動並調試:   gdb program core  (執行後,停在哪,系統就down在哪)
調試一個運行中的進程:   gdb program 1234  或 gdb - 1234  (1234是進程號)
過濾gdb產品信息運行gdb:    gdb --silent
在gdb環境中運行shell命令:  shell ls
在gdb環境中運行make命令:   make all
轉移gdb輸出到文件中:set logging on      set logging file filename   (filename是文件名)

#1  - 命令補全,和shell一樣,用TAB補全,同樣有雙擊TAB羅列可選項的功能

#2  - 基本命令
      run     啓動程序 
      start   主函數處設置斷點,啓動程序,每次過來執行都會停住,相當於一個長期斷點
      starti  主函數處設置斷點,啓動程序,僅在第一個過來執行時會挺住,相當於一次性斷點
      set args  設置運行參數,進入交互界面後,set args arg1 arg2,依次設置參數1——arg1 和 參數2——arg2
      show args 查看已設置的參數
      continue  一直執行,知道下一個斷點,若無斷點,則一直執行到程序結束
      bt      輸出當前調用棧
      n       step over 
      s       step into
      
      break   設置斷點
                break lineno                      當前文件的指定行處
                break filename:lineno             特定文件的指定行處
                break functionname                當前文件的指定函數入口
                break filename:functionname       特定文件的指定函數入口
                break *address                    某個虛擬地址
                break                             下一條指令處
                break ... if xxx                  滿足xxx條件,停在...處(...爲上面提到的lineno、functionname等等)
                                                  比如:break printf if i>100
      info    查看相關信息
                info break                        查看斷點信息
                info threads                      查看線程信息
                info r                            查看寄存器信息
                
      condition 爲斷點加條件(類似於break ... if xxx,更細化)
                假設已經設置了斷點3
                condition 3 a>10                  當a>10的時候,在3號斷點停住
                condition 3                       清除加在3號斷點上的條件(比如上面的a>10)
                
      ignore 3 100                                進入斷點3的前100次將被忽略,從101次開始斷點纔有效                
            
                                          
#3  - 多進程調試
      默認情況下,gdb跟蹤父進程
      可以在任何時候設置跟蹤子進程:set follow-fork-mode childe
      
      那麼exec系列函數是否能夠使用gdb跟蹤呢?
      
#4  - 多線程調試
      info threads    查看所有線程(其中帶*號的爲當前線程)
      thread 2        切換到2號線程
      where           輸出線程調用棧(對應bt)
      break ... thread 2  爲2號線程打上斷點(...爲之前提到的lineno、functionname等等)

 

進階用法:

#1  輸出字符串
      p (char *)字符串初始地址
      
#2  輸出完整字符串
      gdb的字符串輸出有長度限制,最多隻能輸出多少個,可使用show print elements查看
      當字符串商都超過這個限制時,可以通過set print elements N,來把這個限制擴展到N個字符
      
#3  gdb value <optimized out>的解決方式
        調整優化深度,默認優化深度爲-O2,調整爲-O0即可
        
===================================================GDB 進階=====================================================

#1    http://linuxtools-rst.readthedocs.io/zh_CN/latest/tool/gdb.html

#2    打印表達式
            print 表達式:簡記爲 p ,其中“表達式”可以是任何當前正在被測試程序的有效表達式,比如當前正在調試C語言的程序,
                         那麼“表達式”可以是任何C語言的有效表達式,包括數字,變量甚至是函數調用。
            print a:將顯示整數 a 的值
            print ++a:將把 a 中的值加1,並顯示出來
            print name:將顯示字符串 name 的值
            print gdb_test(22):將以整數22作爲參數調用 gdb_test() 函數
            print gdb_test(a):將以變量 a 作爲參數調用 gdb_test() 函數
            display 表達式:在單步運行時將非常有用,使用display命令設置一個表達式後,它將在每次單步進行指令後,緊接着輸
                           出被設置的表達式及值。如: display a
            watch 表達式:設置一個監視點,一旦被監視的“表達式”的值改變,gdb將強行終止正在被調試的程序。如: watch a
            whatis :查詢變量或函數
            info function: 查詢函數
            擴展info locals: 顯示當前堆棧頁的所有變量
            
#3    查詢運行信息
            where/bt :當前運行的堆棧列表;
            bt backtrace 顯示當前調用堆棧
            up/down 改變堆棧顯示的深度
            set args 參數:指定運行時的參數
            show args:查看設置好的參數
            info program: 來查看程序的是否在運行,進程號,被暫停的原因。
            
#4          分割窗口
            layout:用於分割窗口,可以一邊查看代碼,一邊測試:
            layout src:顯示源代碼窗口
            layout asm:顯示反彙編窗口
            layout regs:顯示源代碼/反彙編和CPU寄存器窗口
            layout split:顯示源代碼和反彙編窗口
            Ctrl + L:刷新窗口
            
#5          更強大的工具 --    cgdb
            cgdb可以看作gdb的界面增強版,用來替代gdb的 gdb -tui。cgdb主要功能是在調試時進行代碼的同步顯示,這無疑增加了調試的方便性,
            提高了調試效率。界面類似vi,符合unix/linux下開發人員習慣;如果熟悉gdb和vi,幾乎可以立即使用cgdb。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章