gdb

2023-11-17

100个gdb技巧

Debugging with GDB

 

gdb调试基础

-g选项

在编译时要加上-g选项,生成的可执行文件才能用gdb进行源码级调试。-g选项的作用是在可执行文件中加入源代码的信息,比如可执行文件中第几条机器指令对应源代码的第几行,但并不是把整个源文件嵌入到可执行文件中,所以在调试时必须保证gdb能找到源文件。

启动调试与退出调试

编译生成bin.out文件之后,进入gdb调试环境:

gdb bin.out

开始执行程序,停在main函数第一行语句前面等待命令:

start

从头开始连续运行程序:

run(或r)

退出调试:

quit

信息显示

1.        显示gdb版本信息

show version

2.        显示gdb版权相关信息

show copying

3.        启动时不显示提示信息

gdb -q

4.        gdb退出时不显示提示信息

set confirm off

5.        输出信息多时不会暂停输出

set pagination off

set height 0

函数

6.        列出函数的名字

列出可执行文件的所有函数名称:

info functions

列出名字里包含“thre”的函数:

info functions thre*

7.        是否进入带调试信息的函数

进入函数(函数必须有调试信息):

step(缩写为s)

不进入函数,等函数执行完,再显示下一行要执行的程序代码:

next(缩写为n)

8.        进入不带调试信息的函数

默认情况下,gdb不会进入不带调试信息的函数,若想进入没有调试信息的函数:

set step-mode on

9.        退出正在调试的函数

当单步调试一个函数时,如果不想继续跟踪下去了,可以有两种方式退出。

函数继续执行完,并且打印返回值,然后等待输入接下来的命令:

finish

函数不继续执行下面的语句,而是直接返回:

return

也可以指定函数的返回值:

return expression

10.     直接执行函数

直接调用fun()函数执行

call fun()

print fun()

11.     打印函数堆栈帧信息

显示函数堆栈帧信息:

i frame(i是info命令缩写)

输出当前函数堆栈帧的地址,指令寄存器的值,局部变量地址及值等信息。

12.     打印尾调用堆栈帧信息

当一个函数最后一条指令是调用另外一个函数时,开启优化选项的编译器常常以最后被调用的函数返回值作为调用者的返回值,这称之为“尾调用(Tail call)。

查看栈帧时,尾调用只会看到最后被调用函数的栈帧信息,看不到尾调用的相关信息,为了输出尾调用的相关信息:

debug entry-values num(num设置成一个非0的值)。

13.     选择函数堆栈帧

用gdb调试程序时,当程序暂停后,选择函数堆栈帧

frame n (n是层数, 查看层数使用bt命令)

也可以用:

frame addr (addr是堆栈地址)

14.     向上或向下切换函数堆栈帧

用gdb调试程序时,当程序暂停后,向上或向下选择函数堆栈帧:

up n或down n (n是层数)

如果不指定n,则n默认为1。

断点

15.     在匿名空间设置断点

如果要对namespace 为FUN中的函数fun设置断点:

b Foo::foo

如果要对未命名的namespace 中的函数fun设置断点:

b (anonymous namespace):: fun

16.     在程序地址上打断点

当调试汇编程序,或者没有调试信息的程序时,经常需要在程序地址上打断点:

b *address

17.     在程序入口处打断点

当调试没有调试信息的程序时,直接运行start命令是没有效果的。如果不知道main在何处,那么可以在程序入口处打断点,进入gdb:

info files (获得入口地址)

b *address (address为入口地址)

r (启动调试)

18.     在文件行号上打断点

如果要在当前文件中的某一行打断点:

b linenum (linenum为想要打断点的行号)

也可以显式指定文件:

b file:linenum (file为文件名)

可以通过指定(部分)路径,来区分相同的文件名:

b directory/file:linenum (directory为文件的路径名)

通过行号进行设置断点的一个弊端是,如果你更改了源程序,那么之前设置的断点就可能不是你想要的了。

19.     保存已经设置的断点

可以使用如下命令将设置的断点保存下来:

save breakpoints file-name-to-save

下此调试时,可以使用如下命令批量设置保存的断点:

source file-name-to-save

20.     设置临时断点

如果想让断点只生效一次:

tbreak(缩写为:tb): linenum

21.     设置条件断点

gdb可以设置条件断点,也就是只有在条件满足时,断点才会被触发:

break … if condition

22.     忽略断点

在设置断点以后,可以忽略断点:

ignore bnum count

意思是接下来count次编号为bnum的断点触发都不会让程序中断,只有第count + 1次断点触发才会让程序中断。

观察点

23.     设置观察点

设置观察点,也就是当一个变量值发生变化时,程序会停下来:

watch expr (watch 可以简写为wa,expr为变量名称)

也可以使用

watch *(data type*)address (data type为变量的名称,addres为变量的地址)

如果系统支持硬件观测的话,当设置观测点是会打印如下信息:

Hardware watchpoint num: expr

如果不想用硬件观测点的话可如下设置:

set can-use-hw-watchpoints

查看观察点,列出当前所设置了的所有观察点:

info watchpoints

watch 所设置的断点也可以用控制断点的命令来控制,如 disable、enable、delete等。

24.     设置观察点只针对特定线程生效

设置观察点只针对特定线程生效,也就是只有指定编号的线程改变了变量的值,程序才会停下来,其它编号线程改变变量的值不会让程序停住。

watch expr thread threadnum (expr为变量名称,threadnum为线程编号)

需要注意的是这种针对特定线程设置观察点方式只对硬件观察点才生效。

25.     设置读观察点

设置读观察点,也就是当发生读取变量行为时,程序就会暂停住:

rwatch  expr(rwatch可以简写为rw,expr为变量名称)

需要注意的是rwatch命令只对硬件观察点才生效。

26.     设置读写观察点

设置读写观察点,也就是当发生读取变量或改变变量值的行为时,程序就会暂停住:

awatch expr(awatch可以简写为aw,expr为变量名称)

Catchpoint

27.     让catchpoint只触发一次

设置catchpoint只触发一次:

tcatch fork

28.     为fork调用设置catchpoint

为fork调用设置catchpoint:

catch fork

当fork调用发生后,gdb会暂停程序的运行。

29.     为vfork调用设置catchpoint

为vfork调用设置catchpoint:

catch vfork

当vfork调用发生后,gdb会暂停程序的运行。

30.     为exec调用设置catchpoint

为exec系列系统调用设置catchpoint:

catch exec

31.     为系统调用设置catchpoint

为关注的系统调用设置catchpoint:

catch syscall [name | number] (name为系统调用函数名,number为系统调用编号)

如果不指定具体的系统调用,则会为所有的系统调用设置catchpoint。

32.     通过为ptrace调用设置catchpoint破解anti-debugging的程序

有些程序不想被gdb调试,它们就会在程序中调用“ptrace”函数,一旦返回失败,就证明程序正在被gdb等类似的程序追踪,所以就直接退出。破解这类程序的办法就是为ptrace调用设置catchpoint,通过修改ptrace的返回值达到目的:

catch syscall ptrace

set $rax = 0 (通过修改rax寄存器的值,达到修改返回值的目的)

打印

33.     打印ASCII和宽字符字符串

打印ASCII字符串:

x/s str (str为ASCII字符串)

打印宽字符字符串时,要根据宽字符的长度决定如何打印:

p sizeof(wchar_t)

用上述命令查看wchar_t占的字节数,当前平台宽字符的长度为4个字节:

x/ws str

如果是2个字节:

x/hs str

34.     打印大数组中的内容

p array

如果要打印大数组的内容,缺省最多会显示200个元素:

设置这个最大限制数:

set print elements number-of-elements (number-of-elements为限制的最大数目)

也可以使用如下命令,设置为没有限制:

set print elements 0

set print elements unlimited

35.     打印数组中任意连续元素值

打印数组中任意连续元素的值:

p array[index]@num(p是print命令的缩写;其中index是数组索引,从0开始计数;num是连续多少个元素。

如果要打印从数组开头连续元素的值:

p *array@num

36.     打印数组的索引下标

当打印一个数组时,缺省是不打印索引下标的,如果要打印索引下标,则可以通过如下命令进行设置:

set print array-indexes on

37.     格式化打印数组

将格式化输出写成一个函数,调试时调用函数控制数组的输出格式。

38.     打印函数局部变量的值

首先应该给函数打上断点,当程序断住时:

bt (显示调用栈信息)

显示各个函数的局部变量值:

bt full

从内向外显示n个栈桢,及其局部变量:

bt full n

从外向内显示n个栈桢,及其局部变量:

bt full -n

如果只是想打印当前函数局部变量的值,可以使用如下命令:

info locals

39.     打印进程内存信息

想查看进程的内存映射信息,可以使用:

i proc mappings(i是info命令缩写)

更详细地输出进程的内存信息,包括引用的动态链接库等:

i files

i target

40.     打印静态变量的值

如果直接打印静态变量,则结果并不一定是你想要的,可以显式地指定文件名(上下文):

p 'file'::var (file为文件名称,var为静态变量名称)

41.     打印变量的类型和所在文件

查看变量的类型:

whatis var (var为变量名称)

查看详细的类型信息:

ptype var  (var为变量名称)

查看定义该变量的文件:

i variables var  (var为变量名称)

gdb会显示所有包含(匹配)该表达式的变量。如果只想查看完全匹配给定名字的变量:

i variables ^he$

需要注意的是:info variables不会显示局部变量,即使是static的也没有太多的信息。

42.     打印内存的值

打印内存的值:

x/nfu addr

含义为以f格式打印从addr开始的n个长度单元为u的内存值。参数具体含义如下:

n:输出单元的个数。

f:是输出格式。比如x是以16进制形式输出,o是以8进制形式输出,等等。

u:标明一个单元的长度。b是一个byte,h是两个byte(halfword),w是四个byte(word),g是八个byte(giant word)。

以16进制格式打印数组a前16个byte的值:

x/16xb a

以无符号10进制格式打印数组a前16个byte的值:

x/16ub a

43.     打印源代码行

在gdb中可以使用list(简写为l)命令来显示源代码以及行号:

l fun (从fun函数开始打印)

l linenum (从linenum行开始打印,默认打印10行)

l – (向前打印)

l + (向前打印)

l line1,line2 (指定打印line1和line2之间的代码)

44.     每行打印一个结构体成员

默认情况下,gdb以一种“紧凑”的方式打印结构体,构体的显示很混乱,尤其是结构体里还嵌套着其它结构体时,每行只显示结构体的一名成员,而且还会根据成员的定义层次进行缩进:

set print pretty on

45.     按照派生类型打印对象

缺省按照派生类型进行打印对象,则可以通过如下命令进行设置:

set print object on

46.     指定程序的输入输出设备

在gdb中,缺省情况下程序的输入输出是和gdb使用同一个终端。你也可以为程序指定一个单独的输入输出终端。

首先,打开一个新终端,使用如下命令获得设备文件名:

tty

在gdb中,使用命令进行设置:

tty tername (tername为上面使用tty获得的终端命令)

47.     使用“$_”和“$__”变量

"x"命令会把最后检查的内存地址值存在“$_”这个“convenience variable”中,并且会把这个地址中的内容放在“$__”这个“convenience variable”。

另外要注意有些命令(像“info line”和“info breakpoint”)会提供一个默认的地址给"x"命令检查,而这些命令也会把“$_”的值变为那个默认地址值。

48.     打印程序动态分配内存的信息

用gdb调试程序时,可以用下面的自定义命令,打印程序动态分配内存的信息:

define mallocinfo

  set $__f = fopen("/dev/tty", "w")

  call malloc_info(0, $__f)

  call fclose($__f)

end

49.     打印调用栈帧中变量的值

如果想查看调用栈帧中的变量,可以先切换到该栈帧中,然后打印:

bt (列出栈帧)

f num (进入栈帧,f是frame的缩写,num是栈帧号)

p var (var为变量名)

也可以不进行切换,直接打印:

p fun::var (fun为函数名,var为变量名)

注意,对于C++的函数名,需要使用单引号括起来。

多进程/线程

50.     调试已经运行的进程

调试已经运行的进程有两种方法:一种是gdb启动时,指定进程的ID:

gdb program processID (processID为进程的ID)

也可以用-p或者--pid指定进程ID:

gdb program -p=processID

另一种是先启动gdb,然后用“attach”命令“附着”在进程上:

attach processID

如果不想继续调试了, “脱离”进程:

detach

51.     调试子进程

在调试多进程程序时,gdb默认会追踪父进程,如果要调试子进程:

set follow-fork-mode child

52.     同时调试父进程和子进程

在调试多进程程序时,gdb默认只会追踪父进程的运行,而子进程会独立运行,gdb不会控制。

如果要同时调试父进程和子进程,并且在调试一个进程时,另外一个进程处于挂起状态:

:set detach-on-fork off(默认detach-on-fork是on)。

在使用“set detach-on-fork off”命令后,查看进程状态, 前面显示“*”是正在调试的进程:

i inferiors(i是info命令缩写)

如果想让父子进程都同时运行:

set schedule-multiple on(默认schedule-multiple是off)

53.     查看线程信息

用gdb调试多线程程序,查看所有线程的信息:

i threads(i是info命令缩写)

显示信息的意义:

第一项(Id):是gdb标示每个线程的唯一ID:1,2等等。

第二项(Target Id):是具体系统平台用来标示每个线程的ID,不同平台信息可能会不同。

第三项(Frame):显示的是线程执行到哪个函数。

前面带“*”表示的是“current thread”,可以理解为gdb调试多线程程序时,选择的一个“默认线程”。

指定打印某些线程的信息

i threads threadId1 threadId2

54.     打印所有线程的堆栈信息

打印所有线程的堆栈信息

thread apply all bt

对指定的线程ID列表大姨堆栈信息:

thread apply threadid1- threadidn bt

55.     不显示线程启动和退出信息

默认情况下,gdb检测到有线程产生和退出时,会打印提示信息,如果不想显示这些信息:

set print thread-events off

56.     只允许一个线程运行

如果想在调试一个线程时,让其它线程暂停执行:

set scheduler-locking on

此外,“set scheduler-locking”命令除了支持off和on模式外(默认是off),还有一个step模式。含义是:当用"step"命令调试线程时,其它线程不会执行,但是用其它命令(比如"next")调试线程时,其它线程也许会执行。

这个命令依赖于具体操作系统的调度策略,使用时需注意。

57.     使用“$_thread”变量

gdb从7.2版本引入了$_thread这个“convenience variable”,用来保存当前正在调试的线程号。这个变量在写断点命令或是命令脚本时会很有用。

58.     一个gdb会话中同时调试多个程序

gdb支持在一个会话中同时调试多个程序,启动一个程序之后,使用:

add-inferior -copies n  -exec executable (其中n默认为1)

也可用克隆现有的inferior:

clone-inferior -copies n  infno (其中n默认为1,infno默认为当前的inferior)

59.     打印程序进程空间信息

使用gdb调试多个进程时,打印当前所有被调试的进程信息:

maint info program-spaces

60.     使用“$_exitcode”变量

当被调试的程序正常退出时,gdb会使用$_exitcode这个“convenience variable”记录程序退出时的“exit code”。

core dump文件

61.     为调试进程产生core dump文件

在用gdb调试程序时,我们有时想让被调试的进程产生core dump文件,记录现在进程的状态,以供以后分析:

generate-core-file

也可使用:

gcore

62.     加载可执行程序和core dump文件

用gdb调试core dump文件,通常用这个命令形式:

gdb path/to/the/executable path/to/the/coredump

gdb会显示程序crash的位置。

有时我们想在gdb启动后,动态加载可执行程序和core dump文件,这时可以用“file”和“core”(core-file命令缩写)命令。“file”命令用来读取可执行文件的符号表信息,而“core”命令则是指定core dump文件的位置:

file path/to/the/executable

core path/to/the/coredump

可以看到gdb同样显示程序crash的位置。

汇编

63.     设置汇编指令格式

在Intel x86处理器上,gdb默认显示汇编指令格式是AT&T格式,将命令将格式改为intel格式:

set disassembly-flavor

目前“set disassembly-flavor”命令只能用在Intel x86处理器上,并且取值只有“intel”和“att”。

64.     在函数的第一条汇编指令打断点

通常给函数打断点的命令:“b func”(b是break命令的缩写),不会把断点设置在汇编指令层次函数的开头。如果要把断点设置在汇编指令层次函数的开头,要使用如下命令:

b *func

65.     自动反汇编后面要执行的代码

如果要在任意情况下反汇编后面要执行的代码:

set disassemble-next-line on

如果要在后面的代码没有源码的情况下才反汇编后面要执行的代码:

set disassemble-next-line auto

关闭这个功能:

set disassemble-next-line off

66.     将源程序和汇编指令映射起来

将函数代码和汇编指令映射起来:

disas /m fun(disas是disassemble命令缩写)

如果只想查看某一行所对应的地址范围,可以:

i line linenum

如果只想查看这一条语句对应的汇编代码,可以使用:

disassemble [addressStart],[addressEnd]

67.     显示将要执行的汇编指令

使用gdb调试汇编程序时,显示当程序停止时,将要执行的汇编指令

display /i $pc

此外也可以一次显示多条指令:

display /ni $pc

取消显示:

undisplay

68.     打印寄存器的值

用gdb调试程序时,如果想查看寄存器的值:

i registers(i是info命令缩写)

以上输出不包括浮点寄存器和向量寄存器的内容, 输出所有寄存器的内容:

i all-registers

要打印单个寄存器的值:

i registers regname

p $regname

69.     显示程序原始机器码

用16进制形式显示程序的原始机器码:

disassemble /r

改变程序的执行

70.     改变字符串的值

set  fun::str = " " (fun为函数名,str为字符串的名)

也可以通过访问内存地址的方法改变字符串的值:

p & str (先查看一下字符串的内存地址)

set address = " "

在改变字符串的值时候,一定要注意内存越界的问题。

71.     设置变量的值

set var variable=expr

set {datatype}address=expr (address为存储地址,datatype为变量类型)

另外寄存器也可以作为变量,因此同样可以修改寄存器的值:

set var $reg= expr (reg表示寄存器)

72.     修改PC寄存器的值

PC寄存器会存储程序下一条要执行的指令,通过修改这个寄存器的值,可以达到改变程序执行流程的目的。

73.     跳转到指定位置执行

jump linenum (linenum要跳转到的行号)

jump命令只改变pc的值,所以改变程序执行可能会出现不同的结果。

74.     使用断点命令改变程序的执行

如果你在调试一个大程序,重新编译一次会花费很长时间,可以用这种方式在gdb中先实验性的修改下试试,而不需要修改源码,重新编译。

75.     修改被调试程序的二进制文件

gdb不仅可以用来调试程序,还可以修改程序的二进制代码。

缺省情况下,gdb是以只读方式加载程序的。可以通过命令行选项指定为可写:

gcc -write ./bin.out (bin.out为某个编译之后的文件名)

show write

也可以在gdb中,使用命令设置并重新加载程序:

set write on

file ./ bin.out

接下来,查看反汇编:

disassemble /mr fun (fun为函数名)

修改二进制代码(注意大小端和指令长度):

set variable *(datatype*)address=expr

disassemble /mr fun (fun为函数名)

信号

76.     查看信号处理信息

用gdb调试程序时,查看gdb如何处理进程收到的信息:

i signals(或者“i handle”命令,i是info命令缩写)

第一项(Signal):标示每个信号。

第二项(Stop):表示被调试的程序有对应的信号发生时,gdb是否会暂停程序。

第三项(Print):表示被调试的程序有对应的信号发生时,gdb是否会打印相关信息。

第四项(Pass to program):gdb是否会把这个信号发给被调试的程序。

第五项(Description):信号的描述信息。

77.     信号发生时是否暂停程序

用gdb调试程序时,当信号发生时,是否暂停程序的执行:

handle signal stop/nostop

78.     信号发生时是否打印信号信息

用gdb调试程序时,设置当信号发生时,是否打印信号信息:

handle signal print/noprint

79.     信号发生时是否把信号丢给程序处理

用gdb调试程序时,设置当信号发生时,是否把信号丢给程序处理

handle signal pass(noignore)/nopass(ignore)”

其中pass和noignore含义相同,nopass和ignore含义相同。

80.     给程序发送信号

用gdb调试程序的过程中,当被调试程序停止后,让程序继续运行,并且立即给程序发送信号:

signal signal_name

可以使用“signal 0”命令使程序重新运行,但不发送任何信号给进程。

81.     使用“$_siginfo”变量

在某些平台上(比如Linux)使用gdb调试程序,当有信号发生时,gdb在把信号丢给程序之前,可以通过$_siginfo变量读取一些额外的有关当前信号的信息,这些信息是kernel传给信号处理函数的:

ptype $_siginfo

共享库

82.     显示共享链接库信息

显示程序加载的共享链接库信息

info sharedlibrary regex

其中regex可以是正则表达式,意为显示名字符合regex的共享链接库。如果没有regex,则列出所有的库。

脚本

83.     配置gdb init文件

当gdb启动时,会读取HOME目录和当前目录下的的配置文件,执行里面的命令。这个文件通常为“.gdbinit”。

可以放在“.gdbinit”中的一些配置:

# 打印STL容器中的内容

python

import sys

sys.path.insert(0, "/home/xmj/project/gcc-trunk/libstdc++-v3/python")

from libstdcxx.v6.printers import register_libstdcxx_printers

register_libstdcxx_printers (None)

end

 

# 保存历史命令

set history filename ~/.gdb_history

set history save on

 

# 退出时不显示提示信息

set confirm off

 

# 按照派生类型打印对象

set print object on

 

# 打印数组的索引下标

set print array-indexes on

 

# 每行打印一个结构体成员

set print pretty on

84.     按何种方式解析脚本文件

gdb支持的脚本文件分为两种:一种是只包含gdb自身命令的脚本,例如“.gdbinit”文件,当gdb在启动时,就会执行“.gdbinit”文件中的命令;此外,gdb还支持其它一些语言写的脚本文件(比如python)。

gdb用“set script-extension”命令来决定按何种格式来解析脚本文件。它可以取3个值:

1)       off:所有的脚本文件都解析成gdb的命令脚本;

2)       soft:根据脚本文件扩展名决定如何解析脚本。如果gdb支持解析这种脚本语言(比如python),就按这种语言解析,否则就按命令脚本解析;

3)       strict:根据脚本文件扩展名决定如何解析脚本。如果gdb支持解析这种脚本语言(比如python),就按这种语言解析,否则不解析。

85.     保存历史命令

在gdb中,缺省是不保存历史命令的。你可以通过如下命令来设置成保存历史命令:

set history save on

但是,历史命令是缺省保存在了当前目录下的.gdb_history文件中。可以通过如下命令来设置要保存的文件名和路径:

set history filename fname

我们把这两个命令放到$HOME/.gdbinit文件中:

set history filename ~/.gdb_history

set history save on

下次启动gdb时,你就可以直接查找使用之前的历史命令了。

源文件

86.     设置源文件查找路径

有时gdb不能准确地定位到源文件的位置(比如文件被移走了,等等),设置查找源文件的路径:

directory (简写dir) folder

如果希望在gdb启动时,加载code的位置,避免每次在gdb中再次输入命令,可以使用gdb的-d 参数:

 

gdb -q bin.out -d folder

87.     替换查找源文件的目录

有时调试程序时,源代码文件可能已经移到其它的文件夹了,设置新的文件夹

set substitute-path from folderold to foldernew

即用foldernew目录替换folderold目录。

图形化界面

88.     进入和退出图形化调试界面

进入图形化调试界面:

gdb -tui program

或者运行gdb过程中使用“Crtl+X+A”组合键,退出图形化调试界面也是用“Crtl+X+A”组合键。

89.     显示汇编代码窗口

使用gdb图形化调试界面时,显示汇编代码窗口:

layout asm

显示汇编代码:

layout split

90.     显示寄存器窗口

使用gdb图形化调试界面时,显示通用寄存器窗口

layout regs

查看浮点寄存器:

tui reg float

显示系统寄存器:

tui reg system

想切换回显示通用寄存器内容:

tui reg general

91.     调整窗口大小

使用gdb图形化调试界面时,调整窗口大小

winheight <win_name> + | - count

(winheight缩写为win。win_name可以是src、cmd、asm和regs)。

其它

92.     命令行选项的格式

gdb的帮助信息和在线文档对于长选项的形式使用了不同的风格,这两种方式都可以。例如:

gdb -help

gdb --help

93.     支持预处理器宏信息

使用gcc -g编译生成的程序,是不包含预处理器宏信息的,如果想在gdb中查看宏信息,可以使用gcc -g3进行编译。

94.     保留未使用的类型

使用gcc -g编译生成的程序,是不包含未使用的类型信息的,如果想让gcc保留这些没有被使用的类型信息,则可以使用:

gcc -g -fno-eliminate-unused-debug-types

95.     使用命令的缩写形式

在gdb中,你不用必须输入完整的命令,只需命令的(前)几个字母即可。规则是,只要这个缩写不会和其它命令有歧义,也可以使用tab键进行命令补全。

其中许多常用命令只使用第一个字母就可以,比如:

b -> break

c -> continue

d -> delete

f -> frame

i -> info

j -> jump

l -> list

n -> next

p -> print

r -> run

s -> step

u -> until

也有使用两个或几个字母的,比如:

aw -> awatch

bt -> backtrace

dir -> directory

disas -> disassemble

fin -> finish

ig -> ignore

ni -> nexti

rw -> rwatch

si -> stepi

tb -> tbreak

wa -> watch

win -> winheight

另外,如果直接按回车键,会重复执行上一次的命令。

96.     在gdb中执行shell命令和make

可以不离开gdb,直接执行shell命令,比如:

shell ls

或:

!ls ("!"和命令之间不需要有空格(即,有也成)。)

特别是当你在构建环境(build目录)下调试程序的时候,可以直接运行make:

make CFLAGS="-g -O0"

97.     在gdb中执行cd和pwd命令

gdb确实支持这两个命令。

98.     设置命令提示符

当用gdb来调试gdb的时候,通过设置命令提示符,可以帮助你区分这两个gdb:

set prompt (main gdb)

99.     设置被调试程序的参数

可以在gdb启动时,通过选项指定被调试程序的参数:

gdb -args ./bin.out arg1 arg2 arg3

也可以在gdb中,通过命令来设置:

set args arg1 arg2 arg3

也可以在运行程序时,直接指定:

r arg1 arg2 arg3

想让参数为空:

set args

100.  设置被调试程序的环境变量

在gdb中, 设置被调试程序的环境变量

set env varname=value

101.  得到命令的帮助信息

使用help命令可以得到gdb的命令帮助信息, help命令不加任何参数会得到命令的分类。

当输入help class命令时,可以得到这个类别下所有命令的列表和命令功能。

也可以用help command命令得到某一个具体命令的用法。

用apropos regexp命令查找所有符合regexp正则表达式的命令信息。

102.  记录执行gdb的过程

用gdb调试程序时,把执行gdb的过程记录下来

set logging on

方便以后自己参考或是别人帮忙分析。默认的日志文件是“gdb.txt”, 改成别的名字:

set logging file file

输出覆盖之前的日志文件

set logging overwrite on

让gdb的日志不会打印在终端:

set logging redirect on

 

转载于:https://www.cnblogs.com/xiaojianliu/articles/8638871.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

gdb 的相关文章

随机推荐

  • radius认证服务

    radius认证服务 RADIUS是一种分布的 客户端 服务器系统 实现安全网络 反对未经验证的访问 在cisco实施中 RADIUS客户端运行在cisco路由器上上 发送认证请求到中心RADIUS服务器 服务器上包含了所有用户认证和网络服
  • cuda测试集编译linux,linux下使cmake编译cuda(附列子,亲测可用)

    在网上百度 并没有找到什么合适的教程 让我等小白着急不已 借助于GOOGLE的强大能力 发现原来cmake已经支持了cuda 于是乎 赶紧 http www cmake org 下载了最新的cmake 调用了里面的一个FindCUDA cm
  • ApiPost 开源接口调试工具使用大全

    ApiPost使用 简介 接口调试 API请求参数 Header 参数 Query 参数 Body 参数 API 请求响应 返回Headers 响应结果分屏展示 生成调试代码 参数 全局参数 目录参数 参数的优先级 变量 环境变量 环境变量
  • 运行 AppImage软件:Running AppImages (***)

    How to run an AppImage Running AppImages 使用 AppImage appImagetool 进行 Linux 软件包管理 带笔记 要点 1 需要运行权限 通常 linux软件的运行 都需要运行权限 B
  • 基于OpenCASCADE自制三维建模软件(一)介绍

    一 制作背景 目前工作的项目中 需要三维建模作为其中一个模块 而本人刚接触三维建模 因而借助制作一个简单的三维建模软件学习相关的知识 并在此作笔记 在调研过程中 我了解到开源的Open CASCADE软件平台 Open CASCADE简称O
  • ChatGPT 类 AI 软件供应链的安全及合规风险

    AIGC将成为重要的软件供应链 近日 OpenAI推出的ChatGPT通过强大的AIGC 人工智能生产内容 能力让不少人认为AI的颠覆性拐点即将到来 基于AI将带来全新的软件产品体验 而AI也将会成为未来软件供应链中非常重要的一环 在Ope
  • colab 导出csv文件

    生成之后download即可 from google colab import files files download train csv
  • 使用nodejs接入封装第三方短信验证码工具类

    简介 使用nodejs接入封装第三方短信验证码工具类 第三方短信运营商接入 安装axiosyarn add axios 1 1 3 配置 在项目的config文件夹新建一个文件 命名为接入短信验证码平台的名字 例如aliyunMessage
  • js实现5秒后跳转页面

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 一 使用js代码实现延时跳转 二 使用步骤 1 定时器 setInterval 2 location跳转 3 整体实现 总结 提示 以下是本篇文章正文内容 下面案例
  • 数据结构之 栈(C语言实现)

    数据结构之 栈 C语言实现 1 栈的模型 栈 stack 是限制插入和删除只能在一个位置上进行的表 该位置是表的末端 叫做栈的顶 top 对栈的基本操作有push 进栈 和pop 出栈 前者相当于插入 后者则是删除最后插入的元素 最后插入的
  • Shell脚本攻略:Linux防火墙(一)

    目录 一 理论 1 安全技术 2 防火墙 3 通信五元素和四元素 4 总结 二 实验 1 iptables基本操作 2 扩展匹配 3 自定义链接 一 理论 1 安全技术 1 安全技术 入侵检测系统 Intrusion Detection S
  • 一分钟秒懂公有云、私有云、混合云......

    近几年随着云计算技术的逐渐普及 越来越多的企业开始选择了部署云计算方案 当运营赖于数据结构和网络管理业务时 云计算的灵活性 易用性 定制性给企业带来的优势是毋庸置疑的 但是公有云 私有云 混合云等等到底都是什么呢 公有云 私有云 混合云 这
  • NPOI 单元格设置边框

    很多表格中都要使用边框 本节将为你重点讲解NPOI中边框的设置和使用 边框和其他单元格设置一样也是调用ICellStyle接口 ICellStyle有2种和边框相关的属性 分别是 边框相关属性 说明 范例 Border 方向 边框类型 Bo
  • SourceInsight保存文件时自动去除多余的空格

    在用source insight 写代码后提交git 如果有一些多余的空格不删除就提交会出现标红的界面 在source insight 中可以设置保存时自动去除多余的空格 Options gt gt Files gt gt Remove e
  • Yahoo(雅虎)宣布停止开发YUI

    转载至 http www infoq com cn news 2014 09 yahoo drop axe YUI utm campaign infoq content utm source infoq utm medium feed ut
  • DoTween使用

    using System Collections using UnityEngine using DG Tweening using UnityEngine UI DOTween真的比iTween好很多 1 编写方面更加人性化 2 效率高很
  • 供应链金融三大类模式

    供应链金融三类模式的最全对比分析 2017 08 25 15 56 供应链金融可以解决中小企业供应链中资金分配的不平衡问题 打通上下游物流链 资金链 商流 信息流 提升整个供应链的群体竞争力 因此 供应链金融 备受中小企业青睐 在 供应链金
  • V4l2框架基础知识(三)

    V4L2框架概述 V4L2框架主要部分组成 V4L2 device 管理所有设备 media device media device框架管理运行时的pipeline V4L2 device 这个是整个输入设备的总结构体 可以认为他是整个V4
  • ROS节点运行管理launch文件

    launch 文件是一个 XML 格式的文件 可以启动本地和远程的多个节点 还可以在参数服务器中设置参数 作用 可以简化节点的配置与启动 提高ROS程序的启动效率 一 新建 1 新建launch文件 如 turtlesim 在功能包下添加
  • gdb

    100个gdb技巧 Debugging with GDB gdb调试基础 g选项 在编译时要加上 g选项 生成的可执行文件才能用gdb进行源码级调试 g选项的作用是在可执行文件中加入源代码的信息 比如可执行文件中第几条机器指令对应源代码的第