基本调试命令
set args。用途:设置主程序的参数。
例如:./book119 /oracle/c/book1.c /tmp/book1.c
设置参数的方法是:
gdb book119
(gdb) set args /oracle/c/book1.c /tmp/book1.c
2.break,缩写:b。用途:设置断点
break <function>,在进入指定函数时停住,C++中可以使用class::function或function(type, type)格式来指定函数名。
break <linenum>,在指定行号停住。
break +offset / break -offset,在当前行号的前面或后面的offset行停住,offiset为自然数。
break filename:linenum,在源文件filename的linenum行处停住。
break filename:function,在源文件filename的function函数的入口处停住。
break *address,在程序运行的内存地址处停住。
break,break命令没有参数时,表示在下一条指令处停住。
break ... if <condition>,“...”可以是上述的break <linenum>、break +offset / break –offset中的参数,condition表示条件,在条件成立时停住。比如在循环体中,可以设置break if i=100,表示当i为100时停住程序。
info break,查看断点,例如:查看断点时,可使用info命令,如info breakpoints [n]、info break [n](n表示断点号)。
delete 断点号,删除断点号
3.run,缩写:r。用途:开始运行程序, 程序运行到断点的位置会停下来,如果没有遇到断点,程序一直运行下去。
在gdb中,运行程序使用run命令。在程序运行前,我们可以设置如下4方面的工作环境
1. 程序运行参数
set args 可指定运行时参数,如:set args 10 20 30 40 50;
show args 命令可以查看设置好的运行参数。
2. 运行环境
path <dir> 可设定程序的运行路径;
how paths可查看程序的运行路径;s
et environment varname [=value]用于设置环境变量,如set env USER=baohua;
show environment [varname]则用于查看环境变量。
3. 工作目录
cd <dir> 相当于shell的cd命令;
pwd 显示当前所在的目录。
4. 程序的输入输出
info terminal 用于显示程序用到的终端的模式;gdb中也可以使用重定向控制程序输出,如run > outfile;
tty命令可以指定输入输出的终端设备,如:tty /dev/ttyS1。
4.next,缩写:n。用途:执行当前行语句,如果该语句为函数调用,不会进入函数内部执行。
next <count>
单步跟踪,如果有函数调用,它不会进入该函数。同样地,next后面不加count表示一条条地执行,加表示执行后面的count条指令,然后再停住。
5.step,缩写:s。用途:执行当前行语句,如果该语句为函数调用,则进入函数执行其中的第一条语句。
step <count>
单步跟踪,如果有函数调用,则进入该函数(进入函数的前提是,此函数被编译有debug信息)。step后面不加count表示一条条地执行,加表示执行后面的count条指令,然后再停住。
set step-mode
set step-mode on用于打开step-mode模式,这样,在进行单步跟踪时,程序不会因为没有debug信息而不停住,这个参数的设置可便于查看机器码。set step-mod off用于关闭step-mode模式。
step注意了,如果函数是库函数或第三方提供的函数,用s也是进不去的,因为没有源代码,如果是您自定义的函数,只要有源码就可以进去。
6.continue,缩写:c/fg。用途:继续程序的运行,直到遇到下一个断点。
continue [ignore-count]
c [ignore-count]
fg [ignore-count]
ignore-count表示忽略其后多少次断点。 假设我们设置了函数断点add(),并watch i,则在continue过程中,每次遇到add()函数或i发生变化,程序就会停住
7.set var name=value。用途:设置变量的值。
假设程序有两个变量:int ii; char name[21];
set var ii=10 把ii的值设置为10;
set var name="西施" 把name的值设置为"西施"
8.print,缩写:p。用途:显示表达式的值。
在函数中定义了name
char name[30];
在gdb中使用
set var name="nihao"
p name //会输出name的值
p strcpy(name,"www.baidu.com")//会出书strcpy表达式执行后的返回值,同时也把name值改掉了——由于表达式改的
print <expr>
print /<f> <expr>
<expr>是表达式,是被调试的程序中的表达式,<f>是输出的格式,比如,如果要把表达式按16进制的格式输出,那么就是/x。在表达式中,有几种GDB所支持的操作符,它们可以用在任何一种语言中,“@”是一个和数组有关的操作符,“::”指定一个在文件或是函数中的变量,“{<type>} <addr>”表示一个指向内存地址<addr>的类型为type的一个对象。
9.quit,缩写:q。用途:退出gdb环境。
10.list [linenum|function],缩写:l。用途:显示第linenum周围的源程序/显示函数名为function的函数的源程序
list,显示当前行后面的源程序。
list - ,显示当前行前面的源程序。
11.finish,用途:运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息。
12.until,缩写:u。用途:一直在循环体内执行单步,退不出来是一件令人烦恼的事情,until命令可以运行程序直到退出循环体。
13.stepi(缩写si)和nexti(缩写ni)。用途:stepi和nexti用于单步跟踪一条机器指令,一条程序代码有可能由数条机器指令完成,stepi和nexti可以单步执行机器指令。 另外,运行“display/i $pc”命令后,单步跟踪会在打出程序代码的同时打出机器指令,即汇编代码。
14.watch。用途:watch一般来观察某个表达式(变量也是一种表达式)的值是否有变化了,如果有变化,马上停住程序。
watch <expr>:为表达式(变量)expr设置一个观察点。一量表达式值有变化时,马上停住程序
rwatch <expr>:当表达式(变量)expr被读时,停住程序
awatch <expr>:当表达式(变量)的值被读或被写时,停住程序
info watchpoints:列出当前所设置了的所有观察点
15.examine。用途:查看内存地址中的值
x/<n/f/u> <addr>
/<n/f/u> <addr>
<addr>表示一个内存地址。“x/”后的n、f、u都是可选的参数,n 是一个正整数,表示显示内存的长度,也就是说从当前地址向后显示几个地址的内容;f 表示显示的格式,如果地址所指的是字符串,那么格式可以是s,如果地址是指令地址,那么格式可以是i;u 表示从当前地址往后请求的字节数,如果不指定的话,GDB默认是4字节。u参数可以被一些字符代替:b表示单字节,h表示双字节,w表示四字节,g表示八字节。当我们指定了字节长度后,GDB会从指定的内存地址开始,读写指定字节,并把其当作一个值取出来。n、f、u这3个参数可以一起使用,例如命令“x/3uh 0x54320”表示从内存地址0x54320开始以双字节为1个单位(h)、16进制方式(u)显示3个单位(3)的内存
16.set
修改寄存器:
(gdb) set $v0 = 0x004000000
(gdb) set $epc = 0xbfc00000
修改内存:
(gdb) set {unsigned int}0x8048a51=0x0
jump
一般来说,被调试程序会按照程序代码的运行顺序依次执行,但是GDB也提供了乱序执行的功能,也就是说,GDB可以修改程序的执行顺序,从而让程序随意跳跃。这个功能可以由GDB的jump命令:jump <linespec> 来指定下一条语句的运行点。<linespec>可以是文件的行号,可以是file:line格式,也可以是+num这种偏移量格式,表示下一条运行语句从哪里开始。jump <address> 这里的<address>是代码行的内存地址。 注意,jump命令不会改变当前的程序栈中的内容,所以,如果使用jump从一个函数跳转到另一个函数,当跳转到的函数运行完返回,进行出栈操作时必然会发生错误,这可能导致意想不到的结果,所以最好只用jump在同一个函数中进行跳转。
18.signal
使用singal命令,可以产生一个信号量给被调试的程序,如中断信号“Ctrl+C”。这非常方便于程序的调试,可以在程序运行的任意位置设置断点,并在该断点用GDB产生一个信号量,这种精确地在某处产生信号的方法非常有利于程序的调试。 signal命令的语法是:signal <signal>,UNIX的系统信号量通常从1到15,所以<signal>取值也在这个范围。
19.return
如果在函数中设置了调试断点,在断点后还有语句没有执行完,这时候我们可以使用return命令强制函数忽略还没有执行的语句并返回。
return
return <expression>
上述return命令用于取消当前函数的执行,并立即返回,如果指定了<expression>,那么该表达式的值会被作为函数的返回值。
20.call
call命令用于强制调用某函数: call <expr> 表达式中可以一是函数,以此达到强制调用函数的目的,它会显示函数的返回值(如果函数返回值不是void)。 其实,前面介绍的print命令也可以完成强制调用函数的功能。
21.info
info命令可以在调试时用来查看寄存器、断点、观察点和信号等信息。要查看寄存器的值,可以使用如下命令:
info registers (查看除了浮点寄存器以外的寄存器)
info all-registers (查看所有寄存器,包括浮点寄存器)
info registers <regname ...> (查看所指定的寄存器)
info break 要查看断点信息
info watchpoints 列出当前所设置的所有观察点
info signals 查看有哪些信号正在被GDB检测
info line/handle 查看源代码在内存中的地址
info threads 看多线程
info line 后面可以跟行号、函数名、文件名:行号、文件名:函数名等多种形式
22.disassemble。命令用于反汇编,它可被用来查看当前执行时的源代码的机器码,其实际上只是把目前内存中的指令dump出来
GDB调试进程
1.set follow-fork-mod parent,默认模式。用途:用于调试父进程
2.set follow-fork-mod child。用途:用于调试子进程
3.set detach-on-fork [on|off]。默认是on,用途:on——表示调试当前进程的时候,其它进程继续执行;off——表示调试当前进程的时候,其它进程被gdb挂起
4.info inferiors。用途:查看调试的进程
5.inferiors 进程id。用途:切换当前调试的进程
GDB调试线程
在shell中执行:
ps aux | grep book 查看当前运行的进程
ps -aL | grep book 查看当前运行的轻量级进程
pstree -p 主线程id 查看主线程和新线程的关系
1.info threads。用途:查看线程
2.thread 线程id。用途:切换线程
3.set scheduler-locking [on|off],默认为off。用途:on--表示只运行当前线程,其它线程被gdb挂起;off——运行全部线程
4.thread apply 线程id cmd。用途:指定某个线程执行gdb中的命令,例如next命令
5.thread apply all cmd。用途:所有线程执行gdb中的命令,例如next命令
6. break [linenum] thread all,在所有线程中相应的行上设置断点
break thread_test.c:123 thread all