/*********************************************************************
* Author          :     lile
* Modified        :     2019年12月28日星期六  10:16:13
* Email           :     roger0212@163.com
* 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, -ixLike -x but execute commands before loading inferior.--eval-command=COMMAND, -exExecute a single GDB command.May be used multiple times and in conjunctionwith --command.--init-eval-command=COMMAND, -iexLike -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=INTERPSelect 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-resultGDB 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/gdbinitFor 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 命令获取程序进程的PIDgdb -q -d DIR  -p `pgrep -f testApp`### 方法三:利用 pidof 命令获取程序进程的PIDgdb -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 commandsType "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入口处设置breakpointb. break +offset:在程序当前停止的行向前offset行处设置breakpointc. break –offset:在程序当前停止的行向衙offset行处设置breakpointd. break linenum: 在当前源文件的第linenum行处设置breakpointe. break filename:linenum: 在名为filename的源文件的第linenum行处设置breakpointf. break filename:function: 在名为filename的源文件中的function函数入口处设置breakpointC++中可以使用class::function或function(type,type)格式来指定函数名。如果有名称空间,可以使用namespace::class::function或者function(type,type)格式来指定函数名。break class::function或function(type,type)  (个人感觉这个比较方便,b 类名::函数名,执行后会提示如:>>b GamePerson::updateBreakpoint 1 at 0x46b89e: file GamePerson.cpp, line 14.在类class的function函数的入口处停住break namespace::class::function在名称空间为namespace的类class的function函数的入口处停住        )g. break *address: 在程序的地址address处设置breakpointh. 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 breakpointb. set breakpoint pending on: GDB当前不能识别的breakpoint自动成为pending breakpointc. set breakpoint pending off: GDB当前不能识别某个breakpoint时,直接报错d. show breakpoint pending: 查看GDB关于pending breakpoint的设置的行为(auto, on, off)

(4)breakpoints的删除:

a. clear: 清除当前stack frame中下一条指令之后的所有breakpointsb. clear function & clear filename:function: 清除函数function入口处的breakpointsc. clear linenum & clear filename:linenum: 清除第linenum行处的breakpointsd. delete [breakpoints] [range…]:删除由range指定的范围内的breakpoints,range范围是指breakpoint的序列号的范围,序列号可用 i b 命令查看;

(5)breakpoints的禁用、启用:

a. disable [breakpoints] [range…]:禁用由range指定的范围内的breakpointsb. enable [breakpoints] [range…]:启用由range指定的范围内的breakpointsc. 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 …endb. 用途:指定程序在第bnum个breakpoint处停下来后,执行由command-list指定的命令串,如果没有指定bnum,则对最后一个breakpoint生效c. 取消命令列表:commands [bnum]endd. 例子:break foo if x>0commandssilentprintf "x is %d\n",xcontinueend上面的例子含义:当 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: *pFontOld 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 tablesType "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

  • 继续运行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 threadUse 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 threadsthread find -- Find threads that match a regular expressionthread name -- Set the current thread's nameType "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 threadsId   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界面

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 fileType "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 fileType "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)

gdb调试命令与技巧相关推荐

  1. linux下gdb调试方法与技巧整理

    目录 一.gdb简介 二.gdb使用流程 1.启动gdb 2.查看源码 3.运行程序 4.设置断点 5.单步执行 6.查看变量 7.退出gdb 三.gdb基本使用命令 1.运行命令 2.设置断点 3. ...

  2. linux下gdb调试方法和技巧详解

    linux下gdb调试方法和技巧整理 简介 UNIX或者UNIX-like下调试工具 启动gdb # 1. 在可执行程序不需要输入参数时,我们可以使用 gdb + 可执行程序 gdb ./typeid ...

  3. gdb调试命令的使用及总结

    gdb是一个在UNIX环境下的命令行调试工具.如果需要使用gdb调试程序,请在gcc时加上-g选项.下面的命令部分是简化版,比如使用l代替list等等 1.基本命令 1)进入GDB #gdb test ...

  4. gdb 调试命令的使用及总结

    GDB: The GNU Project Debugger:http://www.gnu.org/software/gdb/documentation/ 参考:http://www.jianshu.c ...

  5. GDB 调试命令讲解-转

    首 先需要肯定一点,GDB是个功能异常强大的调试工具,其本身只能运行于字符模式,但是当前众多基于GUI的调试器/IDE,无论是自由软件还是商业软件, 绝大多数都使用GDB作为其后端(但这些基于GUI的 ...

  6. 比较全面的gdb调试命令

    用GDB调试程序  GDB是一个强大的命令行调试工具.大家知道命令行的强大就是在于,其可以形成执行序 列,形成脚本.UNIX下的软件全是命令行的,这给程序开发提代供了极大的便利,命令行 软件的优势在于 ...

  7. Xcode下 gdb 调试命令

    Xcode的调试器为用户提供了一个GDB的图形化界面,GDB是GNU组织的开放源代码调试器.您可以在Xcode的图形界面里做任何事情:但是,如果您需要您可以在命令行里使用GDB的命令,且gdb可以在终 ...

  8. Linux C : GDB调试命令汇总

    GDB 是GNU的一个交互式调试工具,可以调试C.C++ 和其他几种语言编写的程序 利用  gcc   -g   [源文件列表]  -o  [调试文件.x]  来生成调试文件 生成调试文件后   gd ...

  9. 转:Xcode下的GDB调试命令

    Xcode的调试器为用户提供了一个GDB的图形化界面,GDB是GNU组织的开放源代码调试器.您可以在Xcode的图形界面里做任何事情:但是,如果您需要您可以在命令行里使用GDB的命令,且gdb可以在终 ...

最新文章

  1. friend之友元函数和友元类
  2. 晚安科大20211130
  3. apache站点优化--限速
  4. ExtJs学习笔记(21)-使用XTemplate结合WCF显示数据
  5. MVC应用程序显示RealPlayer(rm)视频
  6. el-table某列的列宽自适应,其他列按比例分配。
  7. JAVA入门级教学之HTTP
  8. 【最全资料下载】Kubernetes and Cloud Native Meetup (北京站)
  9. java中文件如何加密压缩?
  10. Spring技术原理之Spring IOC
  11. qwtqplot用法
  12. 查询某表所有列名的SQL语句
  13. php mysql cpu100_mysql进程占服务器cpu100%的解决方法
  14. 《Axure RP 8 实战手册》pdf
  15. Chrome插件--》油猴的使用
  16. 数据结构之图的基础知识(二)
  17. html 输出helloworld,以及基本结构详解
  18. 【进大厂必学】面完 10 多家大厂后,总结了这些太容易被考的算法
  19. 广西清华计算机专业兄弟,2017年清华大学清华在广西录取圆满结束
  20. Mybatis下传入时间条件,查询慢的优化方法

热门文章

  1. docker mysql默认ip_Docker设置固定ip地址
  2. 1 ZigBee是什么?有什么特点?有什么用?
  3. 青岛新媒体运营教程:手把手教你从0到1,如何构建用户画像体系
  4. 技术世界的未来——机器人会控制人类吗?
  5. iframe target属性
  6. 卷积码编码及维特比译码(Viterbi)算法的原理及其FPGA实现
  7. windows10安装kerberos时候遇到的问题
  8. 你是否适合从标准键盘布局转向德沃夏克布局?
  9. JS WebSocket工具类
  10. 约数大合集(超详细!!!)