Running Programs Under GDB

4.1 产生调试信息
当你用GDB调试程序时候,被调试程序里边必须有Debug信息。这些debug信息被包含在object文件里边。它描述了数据类型和函数以及源代码和执行文件之间的对应关系。
-g 选项在编译程序时候将产生调试信息。

有些编译器不同时支持 -0 和 -g 选项,也就意味着不能产生含调试信息的优化代码
gcc 编译器 同时支持-g 和-0选项。

一些更老的GNU C 编译器 支持-gg选项产生调试信息。GDB不在支持这种格式,我么尽量不要使用这个选项。

GDB能知道预处理宏和展示它的表达式。大部分的编译器在-g选项时,在DEBUG infomation里边不产生这种信息。
GCC 3.1 或者以后的版本 假如用-g3选项能产生DWARF格式的调试信息,调试信息里边包含这种信息。

4.2开始你的程序
run
r 启动你的程序,在启动之前 你可以通过 GDB program 或 file program 或 exec-file program来指定要
执行的文件
假如在一个支持进程的环境里运行程序,run创建一个inferior进程,然后使这个进程跑你的程序。但是在一些木有进程的环境里,run命令跳到程序的开始处执行。

被执行起来的程序受superior特定的信息影响。为了改变这些信息,你必须在开始程序之前。如果程序跑起来以后,这些更改在你第二次跑的时候生效。 这些信息被分为下边四大类:

参数:set args可以指定
环境变量: 默认是继承GDB默认的环境变量,但是你也可以用 set enviroment 和 unset environment来改变
部分环境变量。
工作目录: 默认是继承GDB的工作目录,可以用CD来改变工作目录
标准输入输出:程序默认用GDB正在使用的标准输入输出作为程序的标准输入和输出。我们也可
以通过run,tty命令来重定向你的程序。
输入输出:

警告:当输入输出重定向工作,你不能用pipe 传正在调试程序的输出到其他程序。

假如GDB已经读了你的符号表,但是你的符号文件已经改变,GDB会重新加载符号表。并且读了以后,会重新设置你的断点。

start:停在可执行代码的第一行 只是一个临时的断点
set exec-wrapper wrapper
show exec-wrapper
unset exec-wrapper 先执行wrapper 在执行可执行程序

set disable-randomization
set disable-randomization on
set disable-randomization off 禁止虚拟地址空间随机化
show disble-randomization

4.3 程序的参数
如果run命令不带参数 默认使用上次使用的参数
set args
show args

4.4 环境变量
path directory:在path环境变量的前面加一个目录 (GDB用的PATH变量不变)多个目录用空格或系统分隔符隔
开,假如目录已经在path,它会被移到最前面
show paths
show environment [varname]
set environment varname[=value] 设置环境变量,这个环境变量只对跑的program起作用,对GDB无效
unset environment varname 从环境变量中移除varname,注意和 set environment varname=区分

4.5 你程序的工作目录
cd [directory]
pwd 打印GDB当前的工作目录

4.6程序的输入和输出
info terminal
run > outfile
tty /dev/ttyb
set inferior-tty /dev/ttyb
show inferor-tty

4.7 调试一个正在跑的进程
attach process-id attach之后进被调试进程会被暂停
detach 和attach相反 被调试进程继续执行 ,和 GDB脱离关系
假如你退出正在被attach的GDB,进程会被detach,
假如你run正在被attach的进程,该进程会被杀掉,在这两个动作之前一般都有提示,相关指令:set confirm

4.8杀死子进程
kill 杀掉在GDB下边跑的进程

4.9 调试多inferiors 和程序
GDB允许在一个会话下边跑多个进程。
GDB用inferior来展示各个程序的状态。一个inferior对应一个进程。
info inferiors 打印出GDB目前管理的inferiors
带有*号的是GDB正在执行的inferior
该命令有三列构成:
info inferiors
Num Description Executable
2 process 2307 hello
* 1 process 3401 goodbye

inferior infno 在不同inferior 间切换

可以用add-inferior 和clone-inferior命令来增加进程。在一些平台上如果执行fork,exec可以自动添加inferior.可以用remove-iferiors来移除inferior

add-inferior [-copies n] [-exec executable] 添加inferior n 用executable可执行程序。
clone-inferior [-copies n ][infno] 用 inferior n 来复制 infno 的可执行程序。也就是给一个程序跑
第二个实例

remove-inferiors infno… 不能移除当前正在跑的inferior

可以用detach inferior 或者 kill inferiors命令来停止一个非当前正在跑的inferior

detach inferior infno…
kill inferior infno… detach 或者kill inferior ,注意 inferior仍然在 info inferiors的列表中,只是Description将会显示

set print inferior-evnets
set print inferior-events on
set print inferior-events off
show print inferior-events 当 inferior启动或停止时候是否显示通知消息

maint info program-spaces

maint info program-spaces
Id Executable
2 goodbye
Bound inferiors: ID 1 (process 21561)
* 1 hello
由上可以看出当前的inferior是1,但是木有进程在跑

maint info program-spaces
Id Executable
* 1 vfork-test
Bound inferiors: ID 2 (process 18050), ID 1 (process 18045)

调用vfork可能会出现多个进程ID绑定同一个inferior

4.10调试多线程
GDB为多线程提供了如下方法:
1.新线程发送自动通知
2.thread threadno 切换线程
3.info threads 查询存在的线程
4.thread apply [threadno][all] args 提供一个命令给所有的线程
5.线程断点
6.set print thread-events 打印线程开始或退出信息
7.set libthread-db-search-path path 让使用者选择使用那一个 libthread-db

正在被调式的线程成为当前线程,系统为每个线程指定了一个数字

info threads[id…] 打印线程信息 id可选, 多个ID用空格分隔
最左边的*指示当前活动的线程
(gdb) info threads
Id Target Id Frame
3 process 35 thread 27 0x34e5 in sigpause ()
2 process 35 thread 23 0x34e5 in sigpause ()
* 1 process 35 thread 13 main (argc=1, argv=0x7ffffff8)

maint info sol-threads 显示Solaris平台线程信息
thread threadno 使thread number threadno为当前的线程
thread apply [threadno|all] command 在所有指定线程或所有线程上运用command。 2-4表示线程2到线程4
thread name[name] 这条命令赋值一个名字给当前的线程。假如木有参数名字被移除,这个时候可能是还原成                                    系统原来的名字

thread find [regexp]  在线程的名字或者systag里查找正则表达式,然后打印出线程IDS

set print thread-events
set print thread-events on
set print thread-events off
show print thread-events 线程退出开始时,GDB是否给出提示信息

set libthread-db-search-path [path]:
show libthread-db-search-path
set debug libthread-db
show debug libthread-db

4.11 调试forks
一种常用的方法是在子进程被fork之后增加sleep代码 ,然后子进程就会睡去,然后通过PS命令找到PID,然后用attach命令来调试。
一些平台也支持调试forks起来的进程,默认的方式是 GDB继续调父进程,然后子进程不受控制,继续运行。
set follow-fork-mode mode: mode可以是parent child
parent fork 或者vfork 之后 调试父进程
child fork 或者vfork之后 调试子进程
show follow-fork-mode

set detach-on-fork mode:mode 可以是 on 或者是off
on:默认情况只跑一个进程
off:同时调试两个进程,一个被GDB调试,另外一个处
于挂起状态,调试那一个取决于上边的设置。

show detach-on-fork

假如在exec -call执行之后 你提交了一个run命令,这个新的进程重新启动,为了重新启动父进程,用file命令 并且加上父进程的可执行名字作为它的参数。在默认情况下 在exec执行完之后,GDB忽略前一个可执行镜像的符号链接。可以用set follow-exec-mode 命令来改变这种行为。
set follow-exec-mode mode , mode 可以是new 或者same
new:为新进程绑定一个新的inferior.在调用exec call之前 重启 老的inferior正在跑
的进程将会被重启
same:新的进程也使用同一个inferior.在调用exec call之后 重启inferior,正在跑的进
程将会被重启

你可以使用catch命令使GDB暂停在调用了 fork, vfork, exec.

4.12 设置保存点
checkpoing 保留正在被调试程序的快照。这个checkpoing木有参数,但是各个
checkpoing被赋予一个整型的数。
info checkpoints:打印checkpoint相关的信息;
Checkpoing ID ProcessID Code Address Source line, or label
restart checkpoint-id 回到保存点,每次回到保存点的时候pID是不一样的。
delete checkpoint checkpoint-id

4.12.1 Checkpoint 的好处
在代码的一开始 设置一个保存点,可以防止地址空间随机化。(由于安全的原因在一些操作系统 程序一开始执行的时候 地址空间是可以随机化的)

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据