菜鸟笔记
提升您的技术认知

gdb attach使用

进入调试:

ps命令查看进程id。
执行gdb attach pid即可调试正在运行的程序。
info proc显示当前程序可执行文件相关信息(name,pwd)

断点相关:

b pkt.c:22(在pkt.c文件的22行打断点)
b eth_rcv (在函数eth_rcv入口打断点)
info b;显示当前所有断点;
d num;删除断点num;
n num;向后执行num步

bt显示当前函数的调用过程;

打印变量值:

p temp;默认十进制打印
p /x temp;按十六进制打印
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量。
显示变量类型:whatis var;显示var变量的类型
显示变量的结构体成员: ptype var ;显示var类型结构体的成员

gdb中的变量:

程序的变量和gdb的变量是可以交互的,gdb中的变量以 开头,如 i。

set $i=0
print a[$i++]

即可实现打印以a地址起始的内存中的值。

条件进入断点:

如:b arp_rcv if index = 1234(当index=1234时进入断点,注意是单等号)

查看内存:

x /x 以十六进制输出
x /d 以十进制输出
x /c 以单字符输出
x /i 反汇编 – 通常,我们会使用 x/10i ip−20来查看当前的汇编( ip是指令寄存器)
x /s 以字符串输出

打印指定内存起始100字节内容:
x /100ua pkt->data

设置临时变量:

set i=msg−>msgdataprint i打印变量msg->msg_data指针;
ptype $i 打印msg->msg_data类型

command命令:

自动化调试,把一组gdb的命令打包。执行到断点处时自动执行一系列命令。
如:

(gdb) b ftm_pkt_rcv_from_app
Breakpoint 1 at 0x191a8: file ftm_pkt.c, line 204.
(gdb) command 1
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>p /x pmesg
>p /x pmesg->msg_data
>
>end
(gdb) c
Continuing.

Breakpoint 1, ftm_pkt_rcv_from_app (pmesg=pmesg@entry=0x45b2c) at ftm_pkt.c:204
204     ftm_pkt.c: No such file or directory.
$1 = 0x45b2c
$2 = {
  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55, 0x59, 0x6d, 0x38, 0x9c, 0x74, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x12, 0x0, 0x0, 0x0,
  0x0, 0x0, 0x10, 0x0, 0x12, 0x0, 0x0, 0x47, 0x1, 0x3d, 0x0, 0xa, 0x1, 0x0, 0x8, 0x4, 0x0, 0x1, 0x0, 0x0, 0x0, 0x64, 0x1e, 0x81, 0x1, 0x2, 0x3, 0x4c,
  0xcc, 0x6a, 0x70, 0xf4, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x45, 0x0 <repeats 71 times>, 0x68, 0x61, 0xa, 0x0, 0x76,
  0x61, 0xa, 0x0 <repeats 101 times>, 0x4c, 0xcc, 0x6a, 0x70, 0xf4, 0x17, 0x64, 0x1e, 0x81, 0x1, 0x2, 0x3, 0x8, 0x0, 0x45, 0x0, 0x0, 0x3d, 0x21, 0xd3,
  0x40, 0x0, 0x40, 0x6, 0x8, 0x76, 0xc0, 0xa8, 0xc7, 0x65, 0xc0, 0xa8, 0xc7, 0xbb, 0xa, 0x5a, 0x22, 0x43, 0x29, 0x29, 0xcd, 0x77, 0x80, 0x2b, 0x6b,
  0x57, 0x50, 0x18, 0x39, 0x8, 0xb5, 0x75, 0x0, 0x0, 0x47, 0x4e, 0x55, 0x20, 0x67, 0x64, 0x62, 0x20, 0x28, 0x47, 0x44, 0x42, 0x29, 0x20, 0x37, 0x2e,
  0x34, 0x2e, 0x31, 0xd, 0xa, 0x78, 0x0 <repeats 202 times>, 0x63, 0x82, 0x53, 0x63, 0x35, 0x1, 0x1, 0x3d, 0x7, 0x1, 0xd4, 0xee, 0x7, 0x27...}
(gdb)

调用函数:

(gdb) call func()
如:
(gdb) call printf(“hello world!\n”);

重定向标准输出stdout和stderr:

1)先关闭 stdout ,和 stderr 对应的文件描述符。
(gdb) call (int)close(1)
(gdb) call (int)close(2)
2)然后使用以下命令查看一下当前 gdb 窗口所在的虚拟终端。
(gdb) shell tty
/dev/pts/0
3)这时再重新打开 stdout 和 stderr , 把它们和 gdb 窗口所在的虚拟终端关联起来。
(gdb) p (int)open(“/dev/pts/0”, 2)
1=1(gdb)p(int)open(“/dev/pts/0”,2) 2 = 2
如果这两个命令执行结果不是如上结果(1和2),意味着 open 执行失败,需要重新进行 close 和 open.
4)接下来,重新执行如下命令:
call printf(“helllo world\n”);即可直接在gdb调试窗口看到打印信息。
5)即时刷新 stdout 和 stderr
调用 fflush强制刷新缓冲区:
(gdb)call (int)fflush(0)

另外,如果把这里的 ”/dev/pts/0” 替换成目标文件名,便可将 stderr 和 stdout 重定向到该文件。

使用shell模式下的命令:

(gdb) define tar
End with a line saying just “end”.

shell tar
end

(gdb)tar 即可使用shell模式下tar命令,类比可得到其他命令。

以下未验证:

watch div1==div2当变量div1yu div2相等时进入中断。
info thread 查看当前进程的线程
thread 切换调试的线程为指定ID的线程。
break file.c:100 thread all 在file.c文件第100行处为所有经过这里的线程设置断点。
set scheduler-locking off|on|step,这个是问得最多的。在使用step或者continue命令调试当前被调试线程的时候,其他线程也是同时执行的,怎么只让被调试程序执行呢?通过这个命令就可以实现这个需求。
off 不锁定任何线程,也就是所有线程都执行,这是默认值。
on 只有当前被调试程序会执行。
step 在单步的时候,除了next过一个函数的情况(熟悉情况的人可能知道,这其实是一个设置断点然后continue的行为)以外,只有当前线程会执行。