gdb調試命令與技巧

/*********************************************************************
* Author          :     lile
* Modified        :     2019年12月28日星期六  10:16:13
* Email           :     [email protected]
* HomePage        :     lile777.blog.csdn.net
* CopyRight       :     該文章版權由lile所有。
*                       保留原文出處鏈接和本聲明的前提下,可在非商業目的下任意傳播和複製。
*                       對於商業目的下對本文的任何行爲需經作者同意。
*********************************************************************/

1,gdb命令啓動參數

root@ubuntu:~# gdb --help
This is the GNU debugger.  Usage:

    gdb [options] [executable-file [core-file or process-id]]
    gdb [options] --args executable-file [inferior-arguments ...]

Selection of debuggee and its files:

  --args             Arguments after executable-file are passed to inferior
  --core=COREFILE    Analyze the core dump COREFILE.
  --exec=EXECFILE    Use EXECFILE as the executable.
  --pid=PID          Attach to running process PID.
  --directory=DIR    Search for source files in DIR.
  --se=FILE          Use FILE as symbol file and executable file.
  --symbols=SYMFILE  Read symbols from SYMFILE.
  --readnow          Fully read symbol files on first access.
  --write            Set writing into executable and core files.

Initial commands and command files:

  --command=FILE, -x Execute GDB commands from FILE.
  --init-command=FILE, -ix
                     Like -x but execute commands before loading inferior.
  --eval-command=COMMAND, -ex
                     Execute a single GDB command.
                     May be used multiple times and in conjunction
                     with --command.
  --init-eval-command=COMMAND, -iex
                     Like -ex but before loading inferior.
  --nh               Do not read ~/.gdbinit.
  --nx               Do not read any .gdbinit files in any directory.

Output and user interface control:

  --fullname         Output information used by emacs-GDB interface.
  --interpreter=INTERP
                     Select a specific interpreter / user interface
  --tty=TTY          Use TTY for input/output by the program being debugged.
  -w                 Use the GUI interface.
  --nw               Do not use the GUI interface.
  --tui              Use a terminal user interface.
  --dbx              DBX compatibility mode.
  --xdb              XDB compatibility mode.
  --quiet            Do not print version number on startup.

Operating modes:

  --batch            Exit after processing options.
  --batch-silent     Like --batch, but suppress all gdb stdout output.
  --return-child-result
                     GDB exit code will be the child s exit code.
  --configuration    Print details about GDB configuration and then exit.
  --help             Print this message and then exit.
  --version          Print version information and then exit.

Remote debugging options:

  -b BAUDRATE        Set serial port baud rate used for remote debugging.
  -l TIMEOUT         Set timeout in seconds for remote debugging.

Other options:

  --cd=DIR           Change current directory to DIR.

At startup, GDB reads the following init files and executes their commands:
   * system-wide init file: /etc/gdb/gdbinit

For more information, type "help" from within GDB, or consult the
GDB manual (available as on-line info or a printed manual).
Report bugs to "<http://www.gnu.org/software/gdb/bugs/>".

2,調試程序準備

調試版本的程序需要添加 -g 編譯參數選項。

gcc -g -o testApp testApp.c

3,啓動gdb

3.1 程序運行前啓動gdb

gdb --args  --quiet --directory=DIR ./testApp a b c

參數說明:

  • –args :指定啓動參數
  • –quiet :不打印gdb版本信息
  • –directory=DIR:指定源碼的搜索路徑

more: https://www.kancloud.cn/itfanr/i-100-gdb-tips/81926 設置被調試程序的參數

3.2 程序運行中啓動gdb

### 方法一: ps 獲取程序進程的PID
(1)ps -ef | grep testApp
(2)gdb --quiet --directory=DIR --pid=PID 
    // 或者
     gdb -q -d DIR  -p PID
    // 或者
     gdb -q -d DIR attatch PID 

### 方法二:利用 pgrep 命令獲取程序進程的PID
     gdb -q -d DIR  -p `pgrep -f testApp`

### 方法三:利用 pidof 命令獲取程序進程的PID
     gdb -q -d DIR  -p `pidof testApp`

3.3 程序運行崩潰後啓動gdb調試core日誌

core日誌生成的前提是系統已進行了相關的設置,默認程序崩潰時不會生成core日誌。參考以下文章的相關章節設置kernel.core_pattern環境變量。

https://linux.cn/article-9834-1.html?pr 在 Linux 上如何得到一個段錯誤的核心轉儲

有了崩潰時的core日誌後,可以執行以下命令進行調試:

gdb -q -c corefile ./testApp

4,gdb調試

4.1 調試命令查看

(1)在GDB中執行help命令,可以得到如下所示的幫助信息:

(gdb) help
List of classes of commands:

aliases -- Aliases of other commands
breakpoints -- Making program stop at certain points
data -- Examining data
files -- Specifying and examining files
internals -- Maintenance commands
obscure -- Obscure features
running -- Running the program
stack -- Examining the stack
status -- Status inquiries
support -- Support facilities
tracepoints -- Tracing of program execution without stopping the program
user-defined -- User-defined commands

Type "help" followed by a class name for a list of commands in that class.
Type "help all" for the list of all commands.
Type "help" followed by command name for full documentation.
Type "apropos word" to search for commands related to "word".
Command name abbreviations are allowed if unambiguous.
(gdb) 

GDB中的命令可以分爲八類:別名(aliases)、斷點(breakpoints)、數據(data)、文件(files)、內部(internals)、隱含(obscure)、運行(running)、棧(stack)、狀態(status)、支持(support)、跟蹤點(tracepoints)和用戶自定義(user-defined)。

(2)help class-name:查看該類型的命令的詳細幫助說明

(3)help all:列出所有命令的詳細說明

(4)help command:列出命令command的詳細說明

(5)apropos word:列出與word這個詞相關的命令的詳細說明

(6)complete args:列出所有以args爲前輟的命令

(7)info:用來獲取和被調試的應用程序相關的信息

(8)show:用來獲取GDB本身設置相關的一些信息

4.2 斷點(breakpoint)

(1)設置breakpoint:

a. break function: 在函數funtion入口處設置breakpoint

b. break +offset:在程序當前停止的行向前offset行處設置breakpoint

c. break –offset:在程序當前停止的行向衙offset行處設置breakpoint

d. break linenum: 在當前源文件的第linenum行處設置breakpoint

e. break filename:linenum: 在名爲filename的源文件的第linenum行處設置breakpoint

f. break filename:function: 在名爲filename的源文件中的function函數入口處設置breakpoint

    C++中可以使用class::function或function(type,type)格式來指定函數名。
    如果有名稱空間,可以使用namespace::class::function或者function(type,type)格式來指定函數名。
    
    break class::function或function(type,type)  
    (個人感覺這個比較方便,b 類名::函數名,執行後會提示如:
    
    >>b GamePerson::update
    Breakpoint 1 at 0x46b89e: file GamePerson.cpp, line 14.
    
    在類class的function函數的入口處停住
    break namespace::class::function
    在名稱空間爲namespace的類class的function函數的入口處停住        )

g. break *address: 在程序的地址address處設置breakpoint

h. break:

i. break … if cond: …代表上面講到的任意一個可能的參數,在某處設置一個breakpoint,但且僅但cond爲true時,程序停下來

j. tbreak args: 設置一個只停止一次的breakpoints, args與break命令的一樣。這樣的breakpoint當第一次停下來後,就會被自己刪除

k. rbreak regex: 在所有符合正則表達式regex的函數處設置breakpoint

(2)info breakpoints [n]: 查看第n個breakpoints的相關信息,如果省略了n,則顯示所有breakpoints的相關信息;簡寫 i b

(gdb) i b
Num     Type           Disp Enb Address            What
1       watchpoint     keep y                      *pFont
1.1                         y                        *pFont
1.2                         y                        *pFont
2       breakpoint     keep y   0x000000000042a1dc in uartDataHandle at uart.c:204
3       breakpoint     keep y   0x000000000042a150 in uartDataHandle at uart.c:392
(gdb)
(gdb) D                                                #刪除所有斷點  
Delete all breakpoints? (y or n) y  
(gdb) info b                                           #查看斷點  
No breakpoints or watchpoints.  
(gdb) source gdb.cfg                                   #加載斷點  
Breakpoint 9 at 0x40336d: file RecvMain.cpp, line 290.  
Breakpoint 10 at 0x2aaab049c7ef: file CRealCreditEventAb.cpp, line 80.  

  
  
(gdb) info b                                           #查看斷點  
Num     Type           Disp Enb Address            What  
9       breakpoint     keep y   0x000000000040336d in main(int, char**) at RecvMain.cpp:290  
10      breakpoint     keep y   0x00002aaab049c7ef in CRealCreditEventAb::LoopEventCreditCtrl(int)  
                                               at CRealCreditEventAb.cpp:80  
 
 

(3)pending breakpoints: 是指設置在程序開始調試後加載的動態庫中的位置處的breakpoints

a. set breakpoint pending auto: GDB缺省設置,詢問用戶是否要設置pending breakpoint

b. set breakpoint pending on: GDB當前不能識別的breakpoint自動成爲pending breakpoint

c. set breakpoint pending off: GDB當前不能識別某個breakpoint時,直接報錯

d. show breakpoint pending: 查看GDB關於pending breakpoint的設置的行爲(auto, on, off)

(4)breakpoints的刪除:

a. clear: 清除當前stack frame中下一條指令之後的所有breakpoints

b. clear function & clear filename:function: 清除函數function入口處的breakpoints

c. clear linenum & clear filename:linenum: 清除第linenum行處的breakpoints

d. delete [breakpoints] [range…]:刪除由range指定的範圍內的breakpoints,range範圍是指breakpoint的序列號的範圍,序列號可用 i b 命令查看;

(5)breakpoints的禁用、啓用:

a. disable [breakpoints] [range…]:禁用由range指定的範圍內的breakpoints

b. enable [breakpoints] [range…]:啓用由range指定的範圍內的breakpoints

c. enable [breakpoints] once [range…]: 只啓用一次由range指定的範圍內的breakpoints,等程序停下來後,自動設爲禁用

d. enable [breakpoints] delete [range…]: 啓用range指定的範圍內的breakpoints,等程序停下來後,這些breakpoints自動被刪除

(6)條件breakpoints相關命令:

a. 設置條件 breakpoints可以通過break …if cond來設置,也可以通過 condition bnum expression來設置,在這裏首先要通過(1)中介紹的命令設置好breakpoints,然後用condition命令來指定某breakpoint的條件,該breakpoint由bnum指定,條件由expression指定

b. condition bnum: 取消第bnum個breakpoint的條件

c. ignore bnum count: 第bnum個breakpoint跳過count次後開始生效

(7)指定程序在某個breakpoint處停下來後執行一串命令:

a. 格式:

        commands [bnum]

         … command-list …

         end

b. 用途:指定程序在第bnum個breakpoint處停下來後,執行由command-list指定的命令串,如果沒有指定bnum,則對最後一個breakpoint生效

c. 取消命令列表:commands [bnum]

                  end

d. 例子:

break foo if x>0

commands

silent

printf "x is %d\n",x

continue

end

上面的例子含義:當 x>0 時,在foo函數處停下來,然後打印出x的值,然後繼續運行程序

4.3 watchpoints相關命令

watchpoint的作用是讓程序在某個表達式/變量的值發生變化的時候停止運行,達到‘監視’該表達式/變量的目的。

(1)設置watchpoints:

a. watch expr: 設置寫watchpoint,當應用程序寫expr,修改其值時,程序停止運行

b. rwatch expr: 設置讀watchpoint,當應用程序讀表達式expr時,程序停止運行

c. awatch expr: 設置讀寫watchpoint, 當應用程序讀或者寫表達式expr時,程序都會停止運行

(2)info watchpoints: 查看當前調試的程序中設置的watchpoints相關信息

(3)watchpoints和breakpoints很相像,都有enable/disabe/delete等操作,使用方法也與breakpoints的類似

(4)示例 —— 監測 *pFont 結構體變量內容是否改變

(gdb) watch  *pFont
Watchpoint 2: *pFont
(gdb) n
404     in uart.c
(gdb) 
Watchpoint 2: *pFont

Old value = 
  {face = 0x251f110, height = 37, ascent = 31, descent = -5, lineskip = 42, face_style = 0, style = 0, outline = 0, kerning = 1, glyph_overhang = 3, glyph_italics = 7.65899992, underline_offset = -4, underline_height = 1, current = 0x0, cache = {{stored = 0, index = 0, bitmap = {rows = 0, width = 0, pitch = 0, buffer = 0x0, num_grays = 0, pixel_mode = 0 '\000', palette_mode = 0 '\000', palette = 0x0}, pixmap = {rows = 0, width = 0, pitch = 0, buffer = 0x0, num_grays = 0, pixel_mode = 0 '\000', palette_mode = 0 '\000', palette = 0x0}, minx = 0, maxx = 0, miny = 0, maxy = 0, yoffset = 0, advance = 0, cached = 0} <repeats 257 times>}, src = 0x251f0c0, freesrc = 1, args = {flags = 2, memory_base = 0x0, memory_size = 0, pathname = 0x0, stream = 0x1cc92b0, driver = 0x0, num_params = 0, params = 0x0}, font_size_family = 0, hinting = 0}
New value = 
  {face = 0x8080808080808080, height = -2139062144, ascent = -2139062144, descent = -2139062144, lineskip = -2139062144, face_style = -2139062144, style = -2139062144, outline = -2139062144, kerning = -2139062144, glyph_overhang = -2139062144, glyph_italics = -1.18010406e-38, underline_offset = -2139062144, underline_height = -2139062144, current = 0x8080808080808080, cache = {{stored = -2139062144, index = 2155905152, bitmap = {rows = -2139062144, width = -2139062144, pitch = -2139062144, buffer = 0x8080808080808080 <error: Cannot access memory at address 0x8080808080808080>, num_grays = -32640, pixel_mode = 128 '\200', palette_mode = 128 '\200', palette = 0x8080808080808080}, pixmap = {rows = -2139062144, width = -2139062144, pitch = -2139062144, buffer = 0x8080808080808080 <error: Cannot access memory at address 0x8080808080808080>, num_grays = -32640, pixel_mode = 128 '\200', palette_mode = 128 '\200', palette = 0x8080808080808080}, minx = -2139062144, maxx = -2139062144, miny = -2139062144, maxy = -2139062144, yoffset = -2139062144, advance = -2139062144, cached = 32896}, {stored = -2139062144, index = 2155905152, bitmap = {rows = -2139062144, width = -2139062144, pitch = -2139062144, buffer = 0x8080808080808080 <error: Cannot access memory at address 0x8080808080808080>, num_grays = -32640, pixel_mode = 128 '\200', palette_mode = 128 '\200', palette = 0x8080808080808080}, pixmap = {rows = -2139062144, width = -2139062144, pitch = -2139062144, buffer = 0x8080808080808080 <error: Cannot access memory at address 0x8080808080808080>, num_grays = -32640, pixel_mode = 128 '\200', palette_mode = 128 '\200', palette = 0x8080808080808080}, minx = -2139062144, maxx = -2139062144, miny = -2139062144, maxy = -2139062144, yoffset = -2139062144, advance = -2139062144, cached = 32896}, {stored = -2139062144, index = 2155905152, bitmap = {rows = -2139062144, width = -2139062144, pitch = -2139062144, buffer = 0x7c7c7b7c7d7e8080 <error: Cannot access memory at address 0x7c7c7b7c7d7e8080>, num_grays = 31868, pixel_mode = 124 '|', palette_mode = 125 '}', palette = 0x81817f7e7f7f7f7f}, pixmap = {rows = -2138996607, width = -2105442176, pitch = -2122153342, buffer = 0x818181807f7e7f80 <error: Cannot acce---Type <return> to continue, or q <return> to quit---q
Quit


4.4 catchpoints相關命令

catchpoints的作用是讓程序在發生某種事件的時候停止運行,比如C++中發生異常事件,加載動態庫事件。

(1)設置catchpoints:

a. catchevent: 當事件event發生的時候,程序停止運行,這裏event的取值有:

    1)throw: C++拋出異常
    
    2)catch: C++捕捉到異常
    
    3)exec: exec被調用
    
    4)fork: fork被調用
    
    5)vfork: vfork被調用
    
    6)load:加載動態庫
    
    7)loadlibname: 加載名爲libname的動態庫
    
    8)unload:卸載動態庫
    
    9)unload libname: 卸載名爲libname的動態庫
    
    10)syscall [args]:調用系統調用,args可以指定系統調用號,或者系統名稱


b. tcatchevent: 設置只停一次的catchpoint,第一次生效後,該catchpoint被自動刪除

(2)catchpoints和breakpoints很相像,都有enable/disabe/delete等操作,使用方法也與breakpoints的類似

4.5 查看變量

一般來說,GDB會根據變量的類型輸出變量的值。但你也可以自定義GDB的輸出的格式。例如,你想輸出一個整數的十六進制,或是二進制來查看這個整型變量的中的 bit位的情況。要做到這樣,你可以使用GDB的數據顯示格式:

x 按十六進制格式顯示變量。
d 按十進制格式顯示變量。
u 按十六進制格式顯示無符號整型。
o 按八進制格式顯示變量。
t 按二進制格式顯示變量。
a 按十六進制格式顯示變量。
c 按字符格式顯示變量。
f 按浮點數格式顯示變量。

(1)打印變量值 - p

(gdb) help p
Print value of expression EXP.
Variables accessible are those of the lexical environment of the selected
stack frame, plus all those whose scope is global or an entire file.

$NUM gets previous value number NUM.  $ and $$ are the last two values.
$$NUM refers to NUM'th value back from the last one.
Names starting with $ refer to registers (with the values they would have
if the program were to return to the stack frame now selected, restoring
all registers saved by frames farther in) or else to debugger
"convenience" variables (any such name not a known register).
Use assignment expressions to give values to convenience variables.

{TYPE}ADREXP refers to a datum of data type TYPE, located at address ADREXP.
@ is a binary operator for treating consecutive data objects
anywhere in memory as an array.  FOO@NUM gives an array whose first
element is FOO, whose second element is stored in the space following
where FOO is stored, etc.  FOO must be an expression whose value
resides in memory.

EXP may be preceded with /FMT, where FMT is a format letter
but no count or size letter (see "x" command).
(gdb) p i

(2)打印內存值 - x
gdb查看指定地址的內存地址的值:examine 簡寫 x
使用gdb> help x 來查看使用方式

     x/ (n,f,u爲可選參數)
  • n: 需要顯示的內存單元個數,也就是從當前地址向後顯示幾個內存單元的內容,一個內存單元的大小由後面的u定義
  • f:顯示格式

      x(hex) 按十六進制格式顯示變量。
      d(decimal) 按十進制格式顯示變量。
      u(unsigned decimal) 按十進制格式顯示無符號整型。
      o(octal) 按八進制格式顯示變量。
      t(binary) 按二進制格式顯示變量。
      a(address) 按十六進制格式顯示變量。
      c(char) 按字符格式顯示變量。
      f(float) 按浮點數格式顯示變量
    
  • u:每個單元的大小,按字節數來計算。默認是4 bytes。GDB會從指定內存地址開始讀取指定字節,並把其當作一個值取出來,並使用格式f來顯示

             b:1 byte     h:2 bytes     w:4 bytes    g:8 bytes
    

比如x/3uh 0x54320表示從內存地址0x54320讀取內容,h表示以雙字節爲單位,3表示輸出3個單位,u表示 按十進制格式顯示無符號整型。

ref : http://www.cnblogs.com/super119/archive/2011/03/26/1996125.html

(gdb) help x
Examine memory: x/FMT ADDRESS.
ADDRESS is an expression for the memory address to examine.
FMT is a repeat count followed by a format letter and a size letter.
Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),
  t(binary), f(float), a(address), i(instruction), c(char), s(string)
  and z(hex, zero padded on the left).
Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).
The specified number of objects of the specified size are printed
according to the format.

Defaults for format and size letters are those previously used.
Default count is 1.  Default address is following last thing printed
with this command or "print".
(gdb)

(3)gdb變量打印樣式設置

(gdb) help show print 
Generic command for showing print settings.

List of show print subcommands:

show print address -- Show printing of addresses
show print array -- Show pretty formatting of arrays
show print array-indexes -- Show printing of array indexes
show print asm-demangle -- Show demangling of C++/ObjC names in disassembly listings
show print demangle -- Show demangling of encoded C++/ObjC names when displaying symbols
show print elements -- Show limit on string chars or array elements to print
show print entry-values -- Show printing of function arguments at function entry
show print frame-arguments -- Show printing of non-scalar frame arguments
show print inferior-events -- Show printing of inferior events (e.g.
show print max-symbolic-offset -- Show the largest offset that will be printed in <symbol+1234> form
show print null-stop -- Show printing of char arrays to stop at first null char
show print object -- Show printing of object  s derived type based on vtable info
show print pascal_static-members -- Show printing of pascal static members
show print pretty -- Show pretty formatting of structures
show print raw -- Generic command for showing "print raw" settings
show print repeats -- Show threshold for repeated print elements
show print sevenbit-strings -- Show printing of 8-bit characters in strings as \nnn
show print static-members -- Show printing of C++ static members
show print symbol -- Show printing of symbol names when printing pointers
show print symbol-filename -- Show printing of source filename and line number with <symbol>
show print symbol-loading -- Show printing of symbol loading messages
show print thread-events -- Show printing of thread events (such as thread start and exit)
show print type -- Generic command for showing type-printing settings
show print union -- Show printing of unions interior to structures
show print vtbl -- Show printing of C++ virtual function tables

Type "help show print" followed by show print subcommand name for full documentation.
Type "apropos word" to search for commands related to "word".
Command name abbreviations are allowed if unambiguous.
(gdb) 


打印選項:

        a. set print field: 打開field選項
        
        b. set print field on: 打開field選項
        
        c. set print field off: 關閉field選項
        
        d. show print field: 查看field選項的打開、關閉情況

常用設置:
(1)set print array:以一種比較好看的方式打印數組,缺省是關閉的

(2)set print elementsnum-of-elements:設置GDB打印數據時顯示元素的個數,缺省爲200,設爲0表示不限制(unlimited)

(3)set print null-stop:設置GDB打印字符數組的時候,遇到NULL時停止,缺省是關閉的

(4)set print pretty:設置GDB打印結構的時候,每行一個成員,並且有相應的縮進,缺省是關閉的

(5)set print object:設置GDB打印多態類型的時候,打印實際的類型,缺省爲關閉

(6)set print static-members:設置GDB打印結構的時候,是否打印static成員,缺省是打開的

(7)set print vtbl:以漂亮的方式打印C++的虛函數表,缺省是關閉的

  • 示例
(gdb) p i
$21 = 101

(gdb) p/a i
$22 = 0x65

(gdb) p/c i
$23 = 101 'e'

(gdb) p/f i
$24 = 1.41531145e-43

(gdb) p/x i
$25 = 0x65

(gdb) p/t i
$26 = 1100101

(gdb) p pFont
$1 = (TTF_Font *) 0x39a1390

### 結構體變量還可以詳細打印出每個成員變量的值
(gdb) p *pFont
$2 = {face = 0x8080808080808080, height = -2139062144, ascent = -2139062144, descent = -2139062144, lineskip = -2139062144, 
  face_style = -2139062144, style = -2139062144, outline = -2139062144, kerning = -2139062144, glyph_overhang = -2139062144, 
  glyph_italics = -1.18010406e-38, underline_offset = -2139062144, underline_height = -2139062144, current = 0x8080808080808080, 
  cache = {{stored = -2139062144, index = 2155905152, bitmap = {rows = -2139062144, width = -2139062144, pitch = -2139062144, 
        buffer = 0x8080808080808080 <error: Cannot access memory at address 0x8080808080808080>, num_grays = -32640, 
        pixel_mode = 128 '\200', palette_mode = 128 '\200', palette = 0x8080808080808080}, pixmap = {rows = -2139062144, 
        width = -2139062144, pitch = -2139062144, 
        buffer = 0x8080808080808080 <error: Cannot access memory at address 0x8080808080808080>, num_grays = -32640, 
        pixel_mode = 128 '\200', palette_mode = 128 '\200', palette = 0x8080808080808080}, minx = -2139062144, 
		
		
(gdb) 


### 單字節顯示內存中的數據值
(gdb) x/1024xb 0x39a1390
0x39a1390:      0x82    0x82    0x82    0x81    0x83    0x82    0x84    0x83
0x39a1398:      0x82    0x81    0x80    0x80    0x7d    0x7d    0x7c    0x7c
0x39a13a0:      0x7b    0x7c    0x7d    0x7d    0x7e    0x80    0x80    0x7f
0x39a13a8:      0x7f    0x7f    0x80    0x80    0x81    0x81    0x81    0x80
0x39a13b0:      0x81    0x81    0x81    0x82    0x82    0x81    0x81    0x81
0x39a13b8:      0x81    0x81    0x7f    0x80    0x80    0x80    0x7f    0x80
0x39a13c0:      0x7f    0x7e    0x7f    0x7f    0x7f    0x7f    0x7f    0x7f
0x39a13c8:      0x80    0x80    0x7f    0x80    0x80    0x80    0x80    0x81
0x39a13d0:      0x80    0x80    0x82    0x81    0x80    0x81    0x81    0x7f
0x39a13d8:      0x7f    0x7f    0x7f    0x7f    0x7f    0x7f    0x7e    0x7e
0x39a13e0:      0x7d    0x7e    0x7f    0x7f    0x82    0x84    0x85    0x84
0x39a13e8:      0x84    0x83    0x82    0x81    0x81    0x81    0x81    0x81
0x39a13f0:      0x80    0x80    0x80    0x80    0x80    0x80    0x80    0x80
0x39a13f8:      0x80    0x80    0x80    0x80    0x80    0x80    0x80    0x80
0x39a1400:      0x80    0x80    0x80    0x80    0x80    0x80    0x80    0x80
0x39a1408:      0x80    0x80    0x80    0x80    0x80    0x80    0x80    0x80
0x39a1410:      0x80    0x80    0x80    0x80    0x80    0x80    0x80    0x80
0x39a1418:      0x80    0x80    0x80    0x80    0x80    0x80    0x80    0x80
0x39a1420:      0x80    0x80    0x80    0x80    0x80    0x80    0x80    0x80
0x39a1428:      0x80    0x80    0x80    0x80    0x80    0x80    0x80    0x80
0x39a1430:      0x80    0x80    0x80    0x80    0x80    0x80    0x80    0x80
0x39a1438:      0x80    0x80    0x80    0x80    0x80    0x80    0x80    0x80
0x39a1440:      0x80    0x80    0x80    0x80    0x80    0x80    0x80    0x80
0x39a1448:      0x80    0x80    0x80    0x80    0x80    0x80    0x80    0x80
0x39a1450:      0x80    0x80    0x80    0x80    0x80    0x80    0x80    0x80
0x39a1458:      0x80    0x80    0x80    0x80    0x80    0x80    0x80    0x80
0x39a1460:      0x80    0x80    0x80    0x80    0x80    0x80    0x80    0x80
0x39a1468:      0x80    0x80    0x80    0x80    0x80    0x80    0x80    0x80
---Type <return> to continue, or q <return> to quit---q
Quit
(gdb) 
  • 查看文件中某變量的值
file::variable
function::variable

可以通過這種形式指定你所想查看的變量,是哪個文件中的或是哪個函數中的。例如,查看文件f2.c中的全局變量x的值:

(gdb)  p 'f2.c'::x
  • 查看數組的值

有時候,你需要查看一段連續的內存空間的值。比如數組的一段,或是動態分配的數據的大小。你可以使用GDB的“@”操

作符,“@”的左邊是第一個內存的地址的值,“@”的右邊則你你想查看內存的長度。

例如,你的程序中有這樣的語句:

int *array = (int *) malloc (len * sizeof (int));

於是,在GDB調試過程中,你可以以如下命令顯示出這個動態數組的取值:

p *array@len

二維數組打印

p **array@len

如果是靜態數組的話,可以直接用print數組名,就可以顯示數組中所有數據的內容了。

  • 查看變量的類型 – ptype && whatis
(gdb) ptype *pFont
type = struct _TTF_Font {
    FT_Face face;
    int height;
    int ascent;
    int descent;
    int lineskip;
    int face_style;
    int style;
    int outline;
    int kerning;
    int glyph_overhang;
    float glyph_italics;
    int underline_offset;
    int underline_height;
    c_glyph *current;
    c_glyph cache[257];
    SDL_RWops *src;
    int freesrc;
    FT_Open_Args args;
    int font_size_family;
    int hinting;
}
(gdb)
(gdb) ptype font_mtx 
type = union {
    struct __pthread_mutex_s __data;
    char __size[48];
    long __align;
}
(gdb) ptype gMp4pkgerThreadExitFlag 
type = unsigned char
(gdb)
(gdb) whatis gMp4pkgerThreadExitFlag
type = unsigned char

4.6 設置變量

set命令 - 可以改變一個變量的值。

set variable varname = value

varname是變量名稱,value是變量的新值。

(1)修改變量值:

a. print v=value: 修改變量值的同時,把修改後的值顯示出來;

b. set [var]v=value: 修改變量值,需要注意如果變量名與GDB中某個set命令中的關鍵字一樣的話,前面加上var關鍵字。

4.7 運行調試

  • 單步運行next
### 僅在當前函數內,逐行代碼執行
(gdb) next
(gdb) n
  • 單步運行step
### 逐行代碼執行,遇到子函數,遞歸進入子函數內部,繼續逐行代碼執行
(gdb) step
(gdb) s

step和next單步調試

  • 繼續運行continue
### 程序繼續往下運行,直到再次遇到斷點或程序結束
(gdb) continue
(gdb) c
  • 繼續運行until
### 繼續運行直到到達指定行號,或者函數,地址等
(gdb) until
(gdb) u
  • 繼續運行finish
### 繼續運行直到當前函數結束
(gdb) finish
(gdb) help finish
Execute until selected stack frame returns.
Usage: finish
Upon return, the value returned is printed and put in the value history.
(gdb)
  • 中斷函數執行return
### return [expression]:中斷函數執行,從當前位置直接返回。
### (注意:finish是把函數運行完,再返回,return是直接返回。)
(gdb) help return 
Make selected stack frame return to its caller.
Control remains in the debugger, but when you continue
execution will resume in the frame above the one now selected.
If an argument is given, it is an expression for the value to return.
(gdb) 
  • 調用應用程序中的函數call
### 在GDB中調用應用程序中的函數
(gdb) call FUNC
(gdb) help call 
Call a function in the program.
The argument is the function name and arguments, in the notation of the
current working language.  The result is printed and saved in the value
history, if it is not void.
(gdb)
  • 發送信號signal
### 向程序發送信號signal,signal可以是信號的符號或數字形式,如果signal=0,那麼程序將會繼續運行,程序不會收到任何信號。
(gdb) help signal 
Continue program with the specified signal.
Usage: signal SIGNAL
The SIGNAL argument is processed the same as the handle command.

An argument of "0" means continue the program without sending it a signal.
This is useful in cases where the program stopped because of a signal,
and you want to resume the program while discarding the signal.

In a multi-threaded program the signal is delivered to, or discarded from,
the current thread only.
(gdb) 

4.8 堆棧打印

(1)查看調用棧信息:

a. backtrace:顯示程序的調用棧信息,可以用bt縮寫

b. backtracen: 顯示程序的調用棧信息,只顯示棧頂n楨(frame)

c. backtrace -n:顯示程序的調用棧信息,只顯示棧底部n楨(frame)

d. set backtrace limitn: 設置bt顯示的最大楨層數

e. where,info stack:都是bt的別名,功能一樣

(2)選擇某一楨進行查看:

a. framen: 查看第n楨的信息

b. frameaddr: 查看pc地址爲addr的楨的相關信息

c. upn: 查看當前楨上面第n楨的信息

d. downn: 查看當前楨下面第n楨的信息

(3)frame信息內容:

a. 用backtrace、frame N 或者 frame addr得到的簡要信息內容:

(1)楨序號(frame number)

(2)函數名

(3)Program counter(除非set print address off)(在程序當前執行到的那一楨,PC不會被顯示)

(4)源代碼文件名和行號

(5)函數的參數名和傳入的值

b. 用info frame、info frame N 或者info frame addr得到的詳細的信息內容:

(1)當前楨的地址

(2)下一楨的地址

(3)上一楨的地址

(4)源代碼所用的程序的語言(c/c++)

(5)當前楨的參數的地址

(6)當前相中局部變量的地址

(7)PC(program counter)

(8)當前楨中存儲的寄存器

    <1> info args:查看當前楨中的參數
    
    <2> info locals:查看當前楨中的局部變量
    
    <3> info catch:查看當前楨中的異常處理器(exception handlers)

使用gdb堆棧跟蹤很方面調試遞歸程序。

#include <stdio.h>
long long func(int n)
{
    int i = 0;
    if (n > 20) {
        printf("n too large!\n");
        return -1;
    }
    if (n == 0) 
        return 1;
    else {
        i = n * func(n-1);
        return i;
    }
}
int main(void)
{
    long long ret;
    ret = func(10);
    printf("ret = %lld\n",ret);
    return 0;
}


(gdb) bt
#0 func (n=7) at test.c:7
#1 0x0804843f in func (n=8) at test.c:14
#2 0x0804843f in func (n=9) at test.c:14
#3 0x0804843f in func (n=10) at test.c:14
#4 0x08048469 in main () at test.c:22

如上所示,可以很清楚地看到遞歸深入到了第幾層,以及該層局部變量值的情況。

4.9 寄存器查看

(1)info registers:查看當前楨中的各個寄存器的情況

(gdb) info registers
x0             0x7f8bd9e240     547807158848
x1             0x0      0
x2             0x72d    1837
x3             0x0      0
x4             0x7f8bd9e240     547807158848
x5             0x0      0
x6             0x7fb30426f0     548464240368
x7             0x0      0
x8             0x62     98
x9             0xffffff80ffffffc8       -545460846648
x10            0x101010101010101        72340172838076673
x11            0x10     16
x12            0x6e2029286e696f6a       7935387797054648170
x13            0x2e2e2e2e2e2e776f       3327647950551545711
x14            0x0      0
x15            0x7e     126
x16            0x7fb2fff080     548463964288
x17            0x6cf0a0 7139488
x18            0x0      0
x19            0x7f8bd9e170     547807158640
x20            0x7fb3042000     548464238592
x21            0x16     22
x22            0x7f8bd9e590     547807159696
x23            0x7fe63c3110     549323550992
x24            0x0      0
x25            0x5a9b38 5937976
x26            0x5aa6e8 5940968
x27            0x5aa820 5941280
x28            0x0      0
x29            0x7fe63c30c0     549323550912
x30            0x7fb2fff0dc     548463964380
sp             0x7fe63c30c0     0x7fe63c30c0
pc             0x7fb2fff168     0x7fb2fff168 <pthread_join+232>
cpsr           0x60000000       1610612736
fpsr           0x10     16
fpcr           0x0      0
(gdb) 

(2)info registers regname: 查看指定的寄存器

4.10 多線程與多進程

a, 多線程程序調試相關:

(1)thread threadno:切換當前線程到由threadno指定的線程

        (gdb) help thread
        Use this command to switch between threads.
        The new thread ID must be currently known.
        
        List of thread subcommands:
        
        thread apply -- Apply a command to a list of threads
        thread find -- Find threads that match a regular expression
        thread name -- Set the current thread's name
        
        Type "help thread" followed by thread subcommand name for full documentation.
        Type "apropos word" to search for commands related to "word".
        Command name abbreviations are allowed if unambiguous.
        (gdb)

(2)info threads:查看GDB當前調試的程序的各個線程的相關信息

      (gdb) info threads
      Id   Target Id         Frame 
    * 1    LWP 1817 "hi3559A_6xD1_Im" 0x0000007fb2fff168 in pthread_join () from /lib64/libpthread.so.0
    (gdb) 

(3)thread apply [threadno] [all]args:對指定(或所有)的線程執行由args指定的命令

b, 多進程程序調試相關(fork/vfork):

(1)缺省方式:fork/vfork之後,GDB仍然調試父進程,與子進程不相關

(2)set follow-fork-modemode:設置GDB行爲,mode爲parent時,與缺省情況一樣;mode爲child時,fork/vfork之後,GDB進入子進程調試,與父進程不再相關

(3)show follow-fork-mode:查看當前GDB多進程跟蹤模式的設置

4.11 源碼查看

  • 列出指定區域(n1到n2之間)的代碼:
(gdb) list n1 n2 

這樣,list可以簡寫爲l,將會顯示n1行和n2行之間的代碼。如果使用 -tui 啓動gdb,將會在相應的位置顯示。如果沒有n1和n2參數,那麼就會默認顯示當前行和之後的10行,再執行又下滾10行。另外,list還可以接函數名。一般來說在list後面可以跟以下這們的參數:

<linenum>   行號。 

<+offset>   當前行號的正偏移量。 

<-offset>   當前行號的負偏移量。 

<filename:linenum>  哪個文件的哪一行。 

<function>  函數名。 

<filename:function> 哪個文件中的哪個函數。 

<*address>  程序運行時的語句在內存中的地址

有時候在用gdb調試程序的時候,發現gdb找不到源碼。用list命令無效。

記住: gdb的調試信息中並不包含源碼,只是包含了怎樣去尋找源碼,但是因爲某種原因,比如你的源碼轉移了位置或者別的原因。你需要告訴gdb到哪裏去尋找源碼。這個通過directory命令來實現。

要查看當前gdb尋找源碼的路徑:

show directories

添加一個新的路徑到查找路徑:

dir  dirname

添加多個時,dirname用: 分開。

類似於環境變量 $PATH 。

詳細見 : http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_node/gdb_48.html

  • TUI模式

詳細見 : https://blog.csdn.net/xu415/article/details/19021759 GDB調試之TUI界面

TUI模式

4.12 源碼編輯

用edit命令在GDB模式下編輯源代碼:

(1)選擇合適的編輯器,gdb會選擇/bin/ex做爲源代碼編輯器,有些linux發行版上可能會沒有安裝/bin/ex,可以把編輯器修改爲比較常見的vim,具體做法爲:有啓動gdb之前,在命令行執行export EDITOR=/usr/bin/vim(或者可以在.profile中設置EDITOR這個變量的值爲/usr/bin/vim,這樣就不用每次啓動gdb的時候都去設置一下了)

(2)edit:編輯當前文件

(3)edit number: 編輯當前文件的第number行

(4)edit function: 編輯當前文件的function函數

(5)edit filename: number: 編輯名爲filename的文件的第number行

(6)edit filename: function: 編輯名爲filename的文件的function函數

4.13 內存拷貝

(1)dump [format] memory filename start_addr end_addr

(gdb) help dump
Dump target code/data to a local file.

List of dump subcommands:

dump binary -- Write target code/data to a raw binary file
dump ihex -- Write target code/data to an intel hex file
dump memory -- Write contents of memory to a raw binary file
dump srec -- Write target code/data to an srec file
dump tekhex -- Write target code/data to a tekhex file
dump value -- Write the value of an expression to a raw binary file

Type "help dump" followed by dump subcommand name for full documentation.
Type "apropos word" to search for commands related to "word".
Command name abbreviations are allowed if unambiguous.
(gdb) 
(gdb) help dump memory
Write contents of memory to a raw binary file.
Arguments are FILE START STOP.  Writes the contents of memory within the
range [START .. STOP) to the specified FILE in raw target ordered bytes.
(gdb) 

(2)append [binary] memory filename start_addr end_addr

(gdb) help append
Append target code/data to a local file.

List of append subcommands:

append binary -- Append target code/data to a raw binary file
append memory -- Append contents of memory to a raw binary file
append value -- Append the value of an expression to a raw binary file

Type "help append" followed by append subcommand name for full documentation.
Type "apropos word" to search for commands related to "word".
Command name abbreviations are allowed if unambiguous.
(gdb) 

(3)restore filename [binary] bias start end

(gdb) help restore
Restore the contents of FILE to target memory.
Arguments are FILE OFFSET START END where all except FILE are optional.
OFFSET will be added to the base address of the file (default zero).
If START and END are given, only the file contents within that range
(file relative) will be restored to target memory.
(gdb) 

5, 參考

https://www.cnblogs.com/skyofbitbit/p/3672848.html 手把手教你玩GDB
https://www.cnblogs.com/youxin/p/4305227.html gdb各種調試命令和技巧
https://www.cnblogs.com/wuchanming/p/4494141.html Linux下gdb調試(tui)

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