Linux的GDB调试

系统命令

  • ulimit -c unlimited 程序dump时,在当前目录下生成core.pid(pid为进程号)的文件
  • gcore pid(调试进程的pid)手动生成core文件
  • ps aux | grep Name 查看进程Name
  • ps -aL | grep Name 查看Name进程的线程
  • pstree -p 主线程id 查看主线程与线程的关系

用法

  • 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, -ix Like -x but execute commands before loading inferior.
    –eval-command= COMMAND, -ex Execute a single GDB command;May be used multiple times and in conjunction;with --command.
    –init-eval-command= COMMAND, -iex Like -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= INTERP Select 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.
    -q, --quiet, --silent 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-result GDB 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.
    –data-directory= DIR, -DSet GDB’s data-directory to DIR.

常用的GDB命令

  • backtrace 显示程序中的当前位置和表示如何到达当前位置的栈追踪
  • breakpoint 在程序中设置一个断点
  • cd 改变当前工作目录
  • clear 删除刚才停止处的断点
  • commands 命中断点时,列出将要执行的命令
  • continue 从断点开始继续执行
  • delete 删除一个断点或监测点
  • display 程序停止时显示变量和表达式
  • down 下移栈帧,使得另一个函数成为当前函数
  • up 上移栈帧,使另一个函数成为当前函数
  • frame 选择下一条continue命令的帧
  • info 显示与该程序有关的各种信息
  • jump 在源程序中的另一点开始执行
  • kill 异常终止在gdb,控制下运行的程序
  • list 列出相应于正在执行的程序的源代码文件内容
  • next 执行下一个源程序行,从而执行其整体中的一个函数
  • print 显示变量或表达式的值
  • pwd 显示当前工作目录
  • pype 显示一个数据结构(如结构体或C++类)的内容
  • quit 退出gdb
  • reverse-search 在源文件中反向搜索正则表达式
  • run 执行该程序
  • search 在源文件中搜索正则表达式
  • set variable 给变量赋值
  • step 执行下一个源程序行,必要时进入一个函数
  • undisplay display命令的反命令,不要显示表达式
  • watch 在程序中设置一个检测点(即数据断点)
  • whatis 显示变量或函数类型

启动GDB

  • gdb program
    program就是可执行文件,一般在当前目录下
  • gdb program core
    用gdb同时调试一个运行程序和core文件,core是程序非法执行后core dump后产生的文件
  • gdb program pid
    如果程序是一个服务程序,那么可以指定这个服务程序运行时的进程ID,gdb自动attach,并调试,其中program应该在PATH环境变量中搜索得到

调试core dumped

生成CoreDump文件

  • ulimit -a 查看核心存储信息,如果core file size为0,表示core文件大小是0字节,默认不产生core文件
  • ulimit -c 1024 改变core file size大小
  • ulimit -c unlimited 设置core文件不做限制

设置CoreDump的核心转储文件目录和命名规则

  • /proc/sys/kernel/core_uses_pid 控制产生的core文件的文件名是否添加pid作为后缀,如果添加则文件内容为1,否则为0
  • /proc/sys/kernel/core_pattern 控制core文件保存位置和文件名格式,如echo ”/corefile/core-%e-%p-%t" > proc/sys/kernel/core_pattern,生成core文件到/corefile目录下,文件名为“core-命令名-pid-时间戳”
参数含义
%pinsert pid into filename 添加 pid
%uinsert current uid into filename 添加当前 uid
%ginsert current gid into filename 添加当前 gid
%sinsert signal that caused the coredump into the filename 添加导致产生 core 的信号
%tinsert UNIX time that the coredump occurred into filename 添加 core 文件生成时的 unix 时间
%hinsert hostname where the coredump happened into filename 添加主机名
%einsert coredumping executable name into filename 添加命令名
  • core文件生成位置一般位于运行程序的路径相同,文件名一般为core.PID,如果通过脚本启动,则脚本可能修改当前目录,这是进程真正的当前目录与脚本执行目录不同,可以查看”/proc/<进程pid>/cwd“符号链接的目标确定进程真正的当前目录地址。
  • /var/log/apport.log 记录core文件生成路径,一般是”运行路径/core“

调试CoreDump

  • gdb program core.PID 调试core文件
  • 进入gdb界面,输入where 或 btrace,跳转core发生位置
  • file core.pid 查看core文件由那个运行程序产生
  • kill -s SIGSEGV pid 让一个正常的程序core down

GDB中运行shell

在gdb环境中,可以执行shell命令,使用gdb的shell命令完成
(gdb) shell

程序在GDB中运行

程序运行参数

  • set args 可指定运行时参数,如:set args 10 20 30
  • show args 命令可以查看设置好的运行参数

运行环境

  • path <dir> 可设定程序的运行路径
  • show paths 查看程序的运行路径
  • set environment varname [=value] 设置环境变量,如:set env USER=hchen
  • show environment [varname] 查看环境变量

工作目录

  • cd <dir> 相当于shell的cd命令
  • pwd 显示当前所在目录

程序的输入输出

  • info terminal 显示程序使用到的终端模式
  • run > outfile 使用重定向控制程序的输出
  • tty /dev/ttyb 指定输入输出的终端设备

GDB显示数据

print

print <expr>
print /<f> <expr>
<expr>是表达式,<f>是输出格式

  • @ 一个和数组有关的操作符
  • :: 指定一个在文件或一个函数中的变量,例如print file::variable 或 print function::variable
  • {<type>} 表示一个指向内存地址<addr>的类型为type的一个对象
  • 每一个print被GDB以$1,$2,$3 …这样方式记录下来,可以直接使用这个编号访问

使用方法

  • 检查变量的值
    (gdb)print p(p为变量名)
  • 对程序中函数的调用
    (gdb)print find_entry(1, 0)
  • 显示数据结构和其他复杂对象
    (gdb) print *table_start
  • 显示数组
    (gdb) print base@length,其中base使地址,length是显示的长度

whatis

  • 显示某个变量的类型
    (gdb) whatis p

examine

使用examine命令(简称x)来查看内存地址中的值,语法如下:
x/<n/f/u> <addr> 或 examine/<n/f/u> <addr>
其中:

  • <addr>表示一个内存地址
  • <n/f/u>都是可选的参数
参数说明
n表示显示内存的单位长度
f表示显示的格式s:地址所指的是字符串 i:地址所指的是指令
u表示以多少字节为一个单位默认是4字节,b:单字节 h:双字节 w:四字节 g:八字节
print和examine显示格式:
x:按16进制格式显示变量
d:按10进制格式显示变量
u:按16进制格式显示无符号整型
o:按8进制格式显示变量
t:按2进制格式显示变量
a:按16进制格式显示变量
c:按字符格式显示变量
f:按浮点数格式显示变量

自动显示

当程序停止时,或单步调试跟踪时,这些变量会自动显示
display <expr>
display/<f> <expr>
display/<f> <addr>
expr是一个表达式,f表示显示的格式,addr表示内存地址,其中格式i和s同样被display支持

  • 删除自动显示:undisplay <dnums …> 或 delete display <dnums …>
  • 使其失效和恢复自动显示:disable display <dnums …> 或 enable display <dnums …>
  • 查看自动显示的信息:info display

断点

break设置断点

  • break line-number
    使程序执行到指定行停止
  • break function-name
    使程序执行到指定函数前停止
  • break line-or-function if condition
    如果condition条件为真,程序执行到指定行或函数处停止
  • break routine-name
    在指定例程的入口处设置断点
  • break filename:line-number
    使程序执行到指定源文件中的行停止
  • break filename:function-name
    使程序执行到指定源文件中的函数停止

watchpoint设置观察点

  • watch <expr>
    为表达式或变量expr设置一个观察点,一旦表达式值有变化时,马上停止程序
  • rwatch <expr>
    当表达式或变量expr被读取时,停止程序
  • awatch <expr>
    当表达式或变量expr被读时,停止程序
  • info watchpoint
    列出当前所设置的所有观察点

catchpoint设置捕捉点

捕捉程序运行时的一些事件,如:载入共享库(动态链接库)或是C++的异常。
catch <event>
tcatch <event> 只设置一次捕捉点,当程序停止之后,该捕捉点自动删除
当event发送时,停止程序,其中event可以是下面的内容:

  • throw 一个C++抛出的异常(throw为关键字)
  • catch 一个C++捕捉到的异常(catch为关键字)
  • exec 调用系统调用exec时(exec为关键字,此功能只在HP-UX下有用)
  • fork 调用系统调用fork时(fork为关键字,此功能只在HP-UX下有用)
  • vfork 调用系统调用cfork时(vfork为关键字,此功能只在HP-UX下有用)
  • load 或 load 载入共享库(动态链接库)时(load为关键字,此功能只在HP-UX下有用)
  • unload 或 unload 卸载共享库(动态链接库)时(unload为关键字,此功能只在HP-UX下有用)

断点管理

  • 显示当前gdb的断点信息
    info break
  • 删除指定的某个断点
    delete breakponit break_number
  • 禁止使用某个断点
    disable breakpoint break_number
  • 允许使用某个断点
    enable breakpoint break_number
  • 清除源文件中某一行上的所有断点
    clear number (number为源文件的某代码行的行号)

停止条件维护

设置断点时,可以设置条件,当条件成立时,程序自动停止;并且条件设置好之后,可以使用condition命令修改断点的条件(只有break和watch命令支持if)

  • condition <bnum> <expression>
    修改断点号为bnum的停止条件为expression
  • condition <bnum>
    清除断点号为bnum的停止条件
  • ignore <bnum> <count>
    表示忽略断点号为bnum的停止条件count次

停止点设定运行命令

使用command命令设置停止点的运行命令,也就是当运行的程序被停止时,可以让其自动运行一些别的命令
commands [bnum]
… command-list
end

为断点号bnum指定一个命令列表,当程序被该断点停止时,gdb依次运行命令列表中的命令
案例:
break foo if x>0
commands
printf “x is %d\n”,x
continue
end

单步执行

  • next 不进入函数的单步执行
  • step 进入函数的单步执行
  • stepi 或 nexti 单步跟踪一条机器指令
  • finish 如果进入了函数,退出该函数返回调用函数中,即结束执行当前函数,显示其返回值
  • until 运行程序直到退出循环体

函数调用

  • call name 调用和执行某个函数

机器语言工具

  • $pc 程序计数器
  • $fp 帧指针
  • $sp 栈指针
  • $ps 处理器状态

信号

捕获信号

handle <signal> <keywords …>
handle 命令可控制信号的处理。有两个参数,一个是信号名,另一个是接收到信号时的处理,其处理有:

  • nostop 接收到信号时,不要将信号发送给程序,也不要停止程序
  • stop 接收到信号时停止程序的执行,从而允许程序调试;显示一条表示已接收到信号的消息(禁止使用消息除外)
  • print 接收到信息时显示一条信息
  • noprint 接收到信号时不要显示消息(而且隐含着不停止程序运行)
  • pass 或 ignore 将信号发送给程序,从而允许程序去处理、停止或采取别的动作
  • nopass 或 noignore 停止程序运行,但不要将信号发送给程序

info signals
info handle
查看哪些信号在被GDB检测中
案例:
捕获SIGPIPE信号,防止正在调试程序去处理该信号。而且该信号一到达,该程序就停止,并通知(可以用信号编号代替信号名)
(gdb) handle SIGPIPE stop print

发送信号

signal命令将信号发送给程序的简单方法,该命令的参数是一个数字或一个名字,如SIGINT

案例:
发送一个SIGINT信号(键盘输入,或CTRL-C,信号2)给程序,触发程序的信号处理函数(信号处理函数内应该设置断点),该程序继续执行,但是立即传输该信号,而且处理程序开始运行。
(gdb) signal 2

调试多线程

break <linespec> thread <thread-num>
break <linespec> thread <thread-num> if …
GDB多线程调试的基本命令

  • 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或command命令调试当前被调试线程时,其他线程也是同时执行的,怎么只让被调试程序执行呢?通过该命令可以实现该需求,off不锁定任何线程,也就是所有线程都执行,这是默认值;on只有当前被调试程序会执行;step在单步的时候,除了next过一个函数的情况以外,只有当前线程会执行

调试多进程

  • 调试父进程(缺省):set follow-fork-mode parent
  • 调试子进程:set follow-fork-mode child
  • 设置调试模式:set detach-on-fork [on | off] 缺省on,表示调试当前进程的时候,其他进程继续运行,如果用off,调试当前进程的时候,其他进程被GDB挂起
  • 查看调试的进程:info inferiors
  • 切换当前调试的进程:inferior pid.id

查看栈信息

backtrace

  • backtrace 打印当前函数调用栈的所有信息
  • backtrace <n> 表示只打印栈顶上n层的栈信息
  • bachtrace <-n> 表示只打印栈底下n层的栈信息

切换栈

  • frame <n> 切换栈,n是一个从0开始的整数,是栈的层编号,比如:frame 0 表示切换到栈定,frame 1 表示切换到栈的第二层
  • up <n> 表示向栈的上面移动n层,如果没有n,表示向上移动一层
  • down <n> 表示向栈的下面移动n层,如果没有n,表示向下移动一层

info frame 打印详细的当前栈的信息
info args 打印当前函数的参数及其值
info locals 打印当前函数中所有局部变量及其值
info catch 打印当前的函数中的异常处理信息

指定源文件的路径

某些时候,用-g编译后的执行程序只包含了源文件的名字,没有路径名
directory <dirname … >
添加一个源文件路径到当前路径,如果指定多个路径,UNIX下使用“:”分隔

  • directory 清除所有的自定义的源文件搜索路径信息
  • show directorues 显示定义的源文件搜索路径

源代码的内存

  • 使用info line命令查看源文件代码在内存中的地址,info line后面可以跟“行号”,“函数名”,“文件名:行号”,“文件名:函数名”,打印出所指定的源代码在运行时的内存地址,如:
    (gdb)info line tst.c:func
  • disassemble 查看源程序的当前执行时的机器码,这个命令把当前内存中的指令dump出来,如:
    (gdb)disassemble func

GDB变量

在GDB调试环境中定义自己的变量,用来保存一些调试程序中的运行数据,和UNIX一样,以$开头,如
*set $foo=object_ptr

  • show convenience 该命令查看当前所设置的所有变量

查看寄存器

  • info registers 查看寄存器的情况(除了浮点寄存器)
  • info all-registers 查看所有寄存器的情况(包括浮点寄存器)
  • info registers <regname …> 查看所指定的寄存器的情况

改变程序的执行

修改变量值

  • print x=4 把变量x的值修改为4
  • set var with=47 使用set var命令告诉GDB,width不是GDB的变量,而是程序的变量名

跳转执行

jump命令不会改变当前程序栈的内容

  • jump <linespec> 指定下一条语句的运行点
  • jump <address> 跳转到指定的内存地址执行
  • set $pc = 0x485 更改跳转地址

强制函数返回

  • return
  • return <expression>
    使用return命令取消当前函数的执行,并立即返回,如果指定了expression,那么该表达式的值被认作函数的返回值
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值