blueyi's notes

Follow Excellence,Success will chase you!

0%

GDB调试详解

关于

使用gccg++编译程序时加上-g参数即可将调试信息加入生成的目标文件,否则使用gdb调试时函数名、变量名都只能显示内存地址。直接运行gdb即可进入gdb,然后输入file a.out即可开始调试a.out,当然也可以直接gdb a.out进入a.out的调试状态。可以使用在命令行状态下使用gdb -help来查看帮助,当然也可以用man。在gdb调试状态下使用help可心获得更强大的帮助,类似vim中的帮助,gdb调试状态下使用help step即可查看单步调试相关的帮助。gdb状态下使用quit退出gdb。进入GDB时可以使用可选参数-tui进入GDB的文本用户界面,该界面可以分屏显示源代码及断点所在行,比使用list查看代码方便很多,而且支持使用上下键来滚动显示代码,此时的命令行历史切换需要使用ctrl+n和ctrl+p。当然有一些支持GDB调试的图形软件ddd和code::block。

GDB基本用法

  1. $gdb app -tui:进入调试状态
    选择一种方式进入gdb,例如$gdb app -tui或者$gdb -tui(gdb)file app,当然也可以执行程序之后再启动gdb,然后使用指定pid的方式 调试,此处$(gdb)分别表示bash上的命令行前导符和gdb运行时的前导符
  2. (gdb)break main(gdb)b N:添加断点
    在main函数所在行添加断点,当然可以使用(gdb)b 20在第20行添加断点。
  3. (gdb)run args-list:运行调试程序
    运行程序,run后面可以跟想要传递给所有调试的程序的参数列表。当然可以(gdb)r,即没有输入参数直接运行到断点处
  4. (gdb)list n1,n2:显示被调试程序源代码
    显示n1到n2行之间的程序源码。或者(gdb)l显示当前行和其后10行的代码
  5. (gdb)next N或者(gdb)step N:单步执行
    next将单步执行,一次运行N行,当然省略N则表示一次一行,如果当前行是一个函数,next会直接一次运行完该函数,然后继续进入下一行。而step则是单步进入执行,一次执行一行,遇到函数也会进入函数内部执行,遇到对象转到相应类的构造函数。当然这两个命令可以省略为n和s,也可以直接回车表示执行一次的命令。
  6. (gdb)finish(gdb)until:跳出当前函数或循环体
    finish执行完当前函数后返回到调用它的函数,并给出函数返回值。例如使用step时,想跳出当前函数即可以使用finish。until在循环开始处使用会直接执行完整个循环体。
  7. (gdb)print var(gdb)print var=5:显示变量var的值,或将变量var的值修改为5
    print后面可以是变量名也可以是函数名,还可以是历史记录,当然可以省略为p,可以显示var的状态信息,并且存放在历史记录中。历史记录以$开头,形如$7,使用(gdb)p $7,即可以显示$7中的内容。
  8. (gdb)info breakpoints(gdb)delete N:显示所以断点和删除断点号为N的断点
    可以省略为(gdb)i b(gdb)d N
  9. (gdb)watch var(gdb)info watch:监视变量var的值和查看当前所有监视信息
    当变量var的值变化时显示var的值并暂停程序执行,后面一个命令可以省略为i watch,显示的信息也会跟i b一样带有一个序号,可以使用d N来删除监视对象
  10. (gdb)continuekill:继续运行程序到下一个断点处和停止本次调试

以下是GDB详细用法:

GDB重要提示

  • 首先编译时必须带上参数-g,如g++ a.cpp -o a -g -std=c++11,这样才能在可执行程序中生成调试信息,以供GDB使用
  • 不能使用编译优化参数,例如-O或者-O2,由于这些优化参数为了提高性能会重新安排程序执行操作,导致调试信息与源码不匹配
  • GDB内部可以使用! commandshell command来执行shell命令
  • GDB内部可以使用TAB键进行自动补全,例如info bre+TAB会自动输入命令info breakpoints
  • GDB内部可以使用很多缩写,只要缩写的匹配是唯一的,例如info bre+回车,相当于执行了info breakpoints+回车
  • GDB内部使用ctrl+c可以在当前位置处暂停执行正在执行的程序,例如当循环很大或者死循环时又不想退出调试时

GDB传递命令行参数

gdb test 进入调试之后

可以使用以下两种方法输入命令行参数:

  • run <命令行参数>
  • set args<命令行参数>`

GDB所有可用的命令行参数

调试可执行程序

1
gdb <name-of-excutable>

调试带有core文件的可执行程序

1
gdb -e <name-of-excutable> -c <name-of-core-file>

调试进程

1
gdb <name-of-excutable> --pid=<process-id> # 或者 gdb <name-of-excutable> -p [pid]

可以使用ps -auxw来列出当前正在运行的进程,或者直接pgrep <进程名>

调试多线程
info threads 显示当前可调试的所有线程,每个线程会有一个GDB为其分配的ID,后面操作线程的时候会用到这个ID。 前面有*的是当前调试的线程。

thread ID 切换当前调试的线程为指定ID的线程。

break thread_test.c:123 thread all 在所有线程中相应的行上设置断点

thread apply ID1 ID2 command 让一个或者多个线程执行GDB命令command。

thread apply all command 让所有被调试线程执行GDB命令command。

set scheduler-locking off|on|step 估计是实际使用过多线程调试的人都可以发现,在使用step或者continue命令调试当前被调试线程的时候,
其他线程也是同时执行的,怎么只让被调试程序执行呢?通过这个命令就可以实现这个需求。off 不锁定任何线程,也就是所有线程都执行,这是默认值。 on 只有当前被调试程序会执行。 step 在单步的时候,除了next过一个函数的情况(熟悉情况的人可能知道,这其实是一个设置断点然后continue的行为)以外,只有当前线程会执行。

调试多进程
使用gdb调试多进程时,如果想要在进程间进行切换,那么就需要在fork调用前设置: set detach-on-fork off ,然后使用 info inferiors 来查看进程信息,得到的信息可以看到最前面有一个进程编号,使用 inferior num 来进行进程切换。
那么为什么要使用 set detache-on-fork off 呢?它的意思是在调用fork后相关进程的运行行为是怎么样的,是detache on/off 也就是说分离出去独立运行,不受gdb控制还是不分离,被阻塞住。
这里还涉及到一个设置 set follow-fork-mode [parents/child] ,就是fork之后,gdb的控制落在谁身上,如果是父进程,那么分离的就是子进程,反之亦然。如果detache-on-fork被off了,那么未受控的那个进程就会被阻塞住,进程状态为T,即处于调试状态。

GDB可选的命令行参数: (version 6. 老版本使用一个短划线 "-")

Option Description
--help
-h
List command line arguments
--exec=file-name
-e file-name
Identify executable associated with core file.
--core=name-of-core-file
-c name-of-core-file
Specify core file.
--command=command-file
-x command-file
File listing GDB commands to perform. Good for automating set-up.
--directory=directory
-d directory
Add directory to the path to search for source files.
--cd=directory Run GDB using specified directory as the current working directory.
--nx
-n
Do not execute commands from ~/.gdbinit initialization file. Default is to look at this file and execute the list of commands.
--batch -x command-file Run in batch (not interactive) mode. Execute commands from file. Requires -x option.
--symbols=file-name
-s file-name
Read symbol table from file file.
--se=file-name Use FILE as symbol file and executable file.
--write Enable writing into executable and core files.
--quiet
-q
Do not print the introductory and copyright messages.
--tty=device Specify device for running program's standard input and output.
--tui Use a terminal user interface. Console curses based GUI interface for GDB. Generates a source and debug console area.
--pid=process-id
-p process-id
Specify process ID number to attach to.
--version Print version information and then exit.

GDB常用调试命令

GDB运行时在GDB内部使用的命令

帮助和查看信息命令

Command Description
help List gdb command topics.
help topic-classes List gdb command within class.
help command Command description.
eg help show to list the show commands
apropos search-word Search for commands and command topics containing search-word.
info args
i args
List program command line arguments
info breakpoints List breakpoints
info break List breakpoint numbers.
info break breakpoint-number List info about specific breakpoint.
info watchpoints List breakpoints
info registers List registers in use
info threads List threads in use
info set List set-able option

断点和监视命令

Break and Watch
break funtion-name
break line-number
break ClassName::functionName
Suspend program at specified function of line number.
break +offset
break -offset
Set a breakpoint specified number of lines forward or back from the position at which execution stopped.
break filename:function Don't specify path, just the file name and function name.
break filename:line-number Don't specify path, just the file name and line number.
break Directory/Path/filename.cpp:62
break *address Suspend processing at an instruction address. Used when you do not have source.
break line-number if condition Where condition is an expression. i.e. x > 5
Suspend when boolean expression is true.
break line thread thread-number Break in thread at specified line number. Use info threads to display thread numbers.
tbreak Temporary break. Break once only. Break is then removed. See "break" above for options.
watch condition Suspend processing when condition is met. i.e. x > 5
clear
clear function
clear line-number
Delete breakpoints as identified by command option.
Delete all breakpoints in function
Delete breakpoints at a given line
delete
d
Delete all breakpoints, watchpoints, or catchpoints.
delete breakpoint-number
delete range
Delete the breakpoints, watchpoints, or catchpoints of the breakpoint ranges specified as arguments.
disable breakpoint-number-or-range
enable breakpoint-number-or-range
Does not delete breakpoints. Just enables/disables them.
Example:
Show breakpoints: info break
Disable: disable 2-9
enable breakpoint-number once Enables once
continue
c
Continue executing until next break point/watchpoint.
continue number Continue but ignore current breakpoint number times. Usefull for breakpoints within a loop.
finish Continue to end of function.

单步执行相关命令

Line Execution
step
s
step number-of-steps-to-perform
Step to next line of code. Will step into a function.
next
n
next number
Execute next line of code. Will not enter functions.
until
until line-number
Continue processing until you reach a specified line number. Also: function name, address, filename:function or filename:line-number.
info signals
info handle
handle SIGNAL-NAME option
Perform the following option when signal recieved: nostop, stop, print, noprint, pass/noignore or nopass/ignore
where Shows current line number and which function you are in.

查看堆栈信息命令

Stack
backtrace
bt
bt inner-function-nesting-depth
bt -outer-function-nesting-depth
Show trace of where you are currently. Which functions you are in. Prints stack backtrace.
backtrace full Print values of local variables.
frame
frame number
f number
Show current stack frame (function where you are stopped)
Select frame number. (can also user up/down to navigate frames)
up
down
up number
down number
Move up a single frame (element in the call stack)
Move down a single frame
Move up/down the specified number of frames in the stack.
info frame List address, language, address of arguments/local variables and which registers were saved in frame.
info args
info locals
info catch
Info arguments of selected frame, local variables and exception handlers.

查看源代码相关信息命令

Source Code
list
l
list line-number
list function
list -
list start#,end#
list filename:function
List source code.
set listsize count
show listsize
Number of lines listed when list command given.
directory directory-name
dir directory-name
show directories
Add specified directory to front of source code path.
directory Clear sourcepath when nothing specified.

查看机器代码相关命令

Machine Language
info line
info line number
Displays the start and end position in object code for the current line in source.
Display position in object code for a specified line in source.
disassemble 0xstart 0xend Displays machine code for positions in object code specified (can use start and end hex memory values given by the info line command.
stepi
si
nexti
ni
step/next assembly/processor instruction.
x 0xaddress
x/nfu 0xaddress
Examine the contents of memory.
Examine the contents of memory and specify formatting.
  • n: number of display items to print
  • f: specify the format for the output
  • u: specify the size of the data unit (eg. byte, word, ...)
Example: x/4dw var

测试变量信息的相关命令

Examine Variables
print variable-name
p variable-name
p file-name::variable-name
p 'file-name'::variable-name
Print value stored in variable.
p *array-variable@length Print first # values of array specified by length. Good for pointers to dynamicaly allocated memory.
p/x variable Print as integer variable in hex.
p/d variable Print variable as a signed integer.
p/u variable Print variable as a un-signed integer.
p/o variable Print variable as a octal.
p/t variable
x/b address
x/b &variable
Print as integer value in binary. (1 byte/8bits)
p/c variable Print integer as character.
p/f variable Print variable as floating point number.
p/a variable Print as a hex address.
x/w address
x/4b &variable
Print binary representation of 4 bytes (1 32 bit word) of memory pointed to by address.
ptype variable
ptype data-type
Prints type definition of the variable or declared variable type. Helpful for viewing class or struct definitions while debugging.

测试GDB模式的命令

GDB Modes
set gdb-option value Set a GDB option
set logging on
set logging off
show logging
set logging file log-file
Turn on/off logging. Default name of file is gdb.txt
set print array on
set print array off
show print array
Default is off. Convient readable format for arrays turned on/off.
set print array-indexes on
set print array-indexes off
show print array-indexes
Default off. Print index of array elements.
set print pretty on
set print pretty off
show print pretty
Format printing of C structures.
set print union on
set print union off
show print union
Default is on. Print C unions.
set print demangle on
set print demangle off
show print demangle
Default on. Controls printing of C++ names.

启动和停止的相关命令

Start and Stop
run
r
run command-line-arguments
run < infile > outfile
Start program execution from the beginning of the program. The command break main will get you started. Also allows basic I/O redirection.
continue
c
Continue execution to next break point.
kill Stop program execution.
quit
q
Exit GDB debugger.

参考

主要参考资料:

  1. GNU GDB Debugger Command Cheat Sheet
  2. 用GDB调试程序

Welcome to my other publishing channels