gdb基本命令

文件分析指令

1
2
3
4
5
6
file xxx  # 查看文件格式信息
size *.o # 查看ELF各个段的长度
objdump -h *.o # 查看目标文件结构和信息 -h(段信息) -sd(以16进制打印并且反汇编)
readelf -S *.o
nm *.o # 查看符号表
c++filt "符号名" # 还原经过mangling后名称

基本命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
break/b 设置断点(函数名,代码行,a.cpp:20)
delete n 删除第n个断点
info b 显示设置的断点
delete breakpoints 删除所有断点
set args ... 设置程序参数
run/r 开始运行
continue/c 执行到下一个断点
next/n 下一行,遇到函数不会进入
step/s 下一步,遇到函数会进入
backtrace/bt 回溯出问题的调用
f x x为6显示的几号代码
until 运行到退出该函数体
finish 运行到当前函数返回,并打印堆栈地址和返回值

list/l 默认显示10行代码
list 行号 显示以行号为中心的前后10行代码
list 函数名
list 不带参数则接上次list继续显示剩下的

print/p

对于bazel编译或可执行程序不在源码目录下时,可用dir设置源码目录

1
dir /home/lirongyun/megvii/

运行

  • run:简记为 r ,其作用是运行程序,当遇到断点后,程序会在断点处停止运行,等待用户输入下一步的命令。
  • continue (简写c ):继续执行,到下一个断点处(或运行结束)
  • next:(简写 n),单步跟踪程序,当遇到函数调用时,也不进入此函数体;此命令同 step 的主要区别是,step 遇到用户自定义的函数,将步进到函数中去运行,而 next 则直接调用函数,不会进入到函数体内。
  • step (简写s):单步调试如果有函数调用,则进入函数;与命令n不同,n是不进入调用的函数的
  • until:当你厌倦了在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体。
  • until+行号: 运行至某行,不仅仅用来跳出循环
  • finish: 运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息。
  • call 函数(参数):调用程序中可见的函数,并传递“参数”,如:call gdb_test(55)
  • quit:简记为 q ,退出gdb

设置断点

    • break n (简写b n):在第n行处设置断点

      (可以带上代码路径和代码名称: b OAGUPDATE.cpp:578)
      
  • b fn1 if a>b:条件断点设置

  • break func(break缩写为b):在函数func()的入口处设置断点,如:break cb_button

  • delete 断点号n:删除第n个断点

  • disable 断点号n:暂停第n个断点

  • enable 断点号n:开启第n个断点

  • clear 行号n:清除第n行的断点

  • info b (info breakpoints) :显示当前程序的断点设置情况

  • delete breakpoints:清除所有断点:

查看源代码

  • list :简记为 l ,其作用就是列出程序的源代码,默认每次显示10行。
  • list 行号:将显示当前文件以“行号”为中心的前后10行代码,如:list 12
  • list 函数名:将显示“函数名”所在函数的源代码,如:list main
  • list :不带参数,将接着上一次 list 命令的,输出下边的内容。

打印表达式

  • print 表达式:简记为 p ,其中“表达式”可以是任何当前正在被测试程序的有效表达式,比如当前正在调试C语言的程序,那么“表达式”可以是任何C语言的有效表达式,包括数字,变量甚至是函数调用。
  • print a:将显示整数 a 的值
  • print ++a:将把 a 中的值加1,并显示出来
  • print name:将显示字符串 name 的值
  • print gdb_test(22):将以整数22作为参数调用 gdb_test() 函数
  • print gdb_test(a):将以变量 a 作为参数调用 gdb_test() 函数
  • display 表达式:在单步运行时将非常有用,使用display命令设置一个表达式后,它将在每次单步进行指令后,紧接着输出被设置的表达式及值。如: display a
  • watch 表达式:设置一个监视点,一旦被监视的“表达式”的值改变,gdb将强行终止正在被调试的程序。如: watch a
  • whatis :查询变量或函数
  • info function: 查询函数
  • 扩展info locals: 显示当前堆栈页的所有变量

查询运行信息

  • where/bt :当前运行的堆栈列表;
  • bt backtrace 显示当前调用堆栈
  • up/down 改变堆栈显示的深度
  • set args 参数:指定运行时的参数
  • show args:查看设置好的参数
  • info program: 来查看程序的是否在运行,进程号,被暂停的原因。

分割窗口

  • layout:用于分割窗口,可以一边查看代码,一边测试:
  • layout src:显示源代码窗口
  • layout asm:显示反汇编窗口
  • layout regs:显示源代码/反汇编和CPU寄存器窗口
  • layout split:显示源代码和反汇编窗口
  • Ctrl + L:刷新窗口

反向调试

1
set exec-direction [forward | reverse] # 设置程序运行方向,然后可用s,n等调试

megvii wiki

gdb命令调试技巧

一、信息显示
1、显示gdb版本 (gdb) show version
2、显示gdb版权 (gdb) show version or show warranty
3、启动时不显示提示信息gdb -q exe 或者.bashrc 添加alias gdb=”gdb -q”,重启shell
4、退出时不显示提示信息(gdb) set confirm off
5、输出信息多时不会暂停输出(gdb)set pagination off

二、函数
1、列出函数的名字(gdb) info functions
2、是否进入待调试信息的函数(gdb)step s
3、进入不带调试信息的函数(gdb)set step-mode on
4、退出正在调试的函数(gdb)return expression 或者 (gdb)finish
5、直接执行函数(gdb)start 函数名 call函数名
6、打印函数堆栈帧信息(gdb)info frame or i frame
7、查看函数寄存器信息(gdb)i registers
8、查看函数反汇编代码(gdb)disassemble func
9、打印尾调用堆栈帧信息(gdb)set debug entry-values 1
10、选择函数堆栈帧(gdb)frame n
11、向上或向下切换函数堆栈帧(gdb)up n down n

三、断点
1、在匿名空间设置断点(gdb)b Foo::foo (gdb) b (anonymous namespace)::bar
2、在程序地址上打断点(gdb)b address (gdb) b 0x400522
3、在程序入口处打断点$strip a.out $readelf -h a.out或者(gdb)info files定位Entry point: 0x400440 (gdb)b *0x400440
4、在文件行号上打断点(gdb)b linenum (gdb)b file.cpp:linenum (gdb)info breakpoints
5、保存已经设置的断点(gdb)save breakpoints file-breakpoints-to-save (gdb)source file-breakpoints-to-save
6、设置临时断点(gdb)tbreak linenum
7、设置条件断点(gdb)b linenum if cond b 11 if i==10
8、忽略断点(gdb)ignore bnum count

四、观察点
1、设置观察点(gdb)watch a wacth (type)adress info watchpoints disable、enable、delete
2、设置观察点只针对特定线程生效(gdb)info threads watch expr thread threadnum wa a thread 2
3、设置读观察点(gdb)rwatch
4、设置读写观察点(gdb)awacth

五、Catchpoint
1、让catchpoint只触发一次(gdb)tcatch
2、为fork调用设置catchpoint (gdb)catch fork
3、为vfork调用设置catchpoint (gdb)catch vfork
4、为exec调用设置catchpoint (gdb)catch exec
5、为系统调用设置catchpoint (gdb)catch syscall name or num
6、通过ptrace调用设置catchpoint破解anti-debugging的程序 (gdb)catch syscall ptrace set $rax=0

六、打印
1、打印ASCII和宽字符字符串 (gdb)x/s str x/ws 4_wstr x/hs 2_wstr
2、打印STL容器中的内容 (gdb)p vec
3、打印大数组中的内容 (gdb)set print elements number-of-elements set print elements 0 or set print elements unlimited
4、打印数组中任意连续的元素值(gdb)p array[index]@num
5、打印数组的索引下标(gdb)set print array-indexes on
6、打印函数局部变量的值(gdb)bt full info locals
7、打印进程的内存信息(gdb)i proc mappings i files
8、打印静态变量的值(gdb)p ‘static-1.c’::var
9、打印变量的类型和所在文件(gdb)whatis he ptype he i variables he
10、打印内存的值(gdb)16进制 x/16xb a 10进制x/16ub a 二进制x/16tb a
11、打印源代码行(gdb)l line l 函数 l - l + l 1,10
12、每行打印一个结构体成员(gdb)set print pretty on
13、按照派生类打印对象(gdb)set print object on
14、指定程序的输入输出设备(gdb)tty gdb -tty /dev/pts/2 ./a.out tty /dev/pts/2
15、使用”$\_“和”$\__”变量(gdb) x “命令会把最后检查的内存地址值存在“ $_ ”这个“convenience variable”中,并
且会把这个地址中的内容放在“ $ ”这个“convenience variable”
16、打印程序动态分配内存的信息(gdb)define mallocinfo set $
f = fopen(“/dev/tty”, “w”) call malloc_info(0, $f)call fclose($f)end mallocinfo
17、打印调用栈帧中变量的值(gdb)b func_1 r bt f 1 p b f 2 p b p func2::b p func_3::b

七、多进程/线程
1、调试已经运行的进程gdb program -p=10210 (gdb)attach pid detach
2、调试子进程(gdb)set follow-fork-mode child
3、同时调试父进程和子进程(gdb)set detach-on-fork off i inferiors set schedule-multiple on
4、查看线程信息(gdb)i threads
5、在Solaris上使用maintenance命令查看线程信息(gdb)maint info sol-threads
6、不显示线程启动和退出信息(gdb)set print thread-events off
7、只允许一个线程运行(gdb)set scheduler-locking on
8、使用”$_thread”变量(gdb)command 2Type commands for breakpoint(s) 2, one per line.End with a line saying just “end”.>printf “thread id=%d\n”, $_thread >end
9、一个gdb会话中同时调试多个程序(gdb)add-inferior [ -copies n ] [ -exec executable ]
10、打印程序进程空间信息(gdb)maint info program-spaces
11、使用”$_exitcode”变量(gdb)p $_exitcode

1
2
3
ps aux | grep porg  # 查看进程
ps -aL | grep porg # 查看轻量级线程
pstree -p main_threadid # 查看与主线程相关的线程

八、core dump文件
1、为调试进程产生core dump文件(gdb)generate-core-file or gcore
2、加载可执行程序和core dump文件(gdb)gdb -q /data/nan/a /var/core/core.a.22268.1402638140

九、汇编
1、设置汇编指令格式(gdb)set disassembly-flavor intel disassemble main
2、在函数的第一条汇编指令打断点(gdb)b *main
3、自动反汇编后面要执行的代码(gdb)set disassemble-next-line on set disassemble-next-line auto set disassemble-next-line off
4、将源程序和汇编指令映射起来(gdb)disas /m main
5、显示将要执行的汇编指令(gdb)display /i $pc
6、打印寄存器的值(gdb)i registers i all-registers i registers eax
7、显示程序原始机器码(gdb)disassemble /r main

十、改变程序执行顺序
1、改变字符串的值(gdb)set main::p1=”Jil”
2、设置变量的值(gdb)set var variable=expr set var i = 8 set {int}0x8047a54 = 8 set var $eax = 8
3、修改PC寄存器的值(gdb)p $pc set var $pc=0x08050949
4、跳转到指定位置执行(gdb)j 15
5、使用断点命令改变程序的执行(gdb)(gdb) b drawing Breakpoint 1 at 0x40064d: file win.c, line 6.
(gdb) command 1
Type commands for breakpoint(s) 1, one per line.
End with a line saying just “end”.
>silent
>set variable n = 0
>continue
>end
(gdb) r
6、修改被调试程序的二进制文件gdb -write ./a.out (gdb)show write set write on disassemble /mr drawing set variable (short)0x400651=0x0ceb disassemble /mr drawing

十一、信号
1、查看信号处理信息(gdb)i signals
2、信号发生时是否暂停程序(gdb) handle signal stop/nostop
3、信号发生时是否打印信号信息(gdb)handle signal print/noprint
4、信号发生时是否把信息丢给程序处理(gdb)handle signal pass(noignore)/nopass(ignore)
5、给程序发送信息(gdb)signal signal_name
6、使用”$_siginfo”变量(gdb)ptype $_siginfo

十二、共享库
1、显示共享连接库信息(gdb)info sharedlibrary regex

十三、脚本
1、配置gdb init文件(gdb) home目录下的 .gdbinit
2、按何种方式解析脚本文件(gdb)set script-extension off soft strict
3、保存历史命令(gdb)set history filename ~/.gdb_history set history save on

十四、源文件
1、设置源文件查找路径(gdb)directory ../ki/
2、替换查找源文件的目录(gdb)set substitute-path from to

十五、图形化界面
1、进入和退出图形化调试界面(gdb)gdb -tui program
2、显示汇编代码窗口(gdb)layout asm
3、显示寄存器窗口(gdb)layout regs
4、调整窗口大小(gdb)winheight [+ | -]count

十六、其它
1、命令行选项的格式(gdb)gdb -help
2、支持预处理器宏信息(gdb)gcc -g3
3、使用命令的缩写形式(gdb)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
4、在gdb中执行shell命令和make(gdb)shell ls
5、在gdb中执行cd和pwd命令(gdb)pwd cd tmp
6、设置命令提示符(gdb)gdb -q `which gdb
7、设置被调试程序的参数(gdb)gdb -args ./a.out a b c set args a b c r a b
8、设置被调试程序的环境变量(gdb)set env varname=value
9、得到命令的帮助信息(gdb)help
10、记录执行gdb的过程(gdb)set logging file log.txt set logging on