gnu gdb
【摘要】 如果编译时没有-g参数,则不能实现基于C源码的符号调试功能,看不到程序的函数名、变量名,显示的全是运行时的内存地址。strip - Discard symbols from object files.如果一个目标被strip了的话,在去dbg他,就不好了一些命令执行会抱怨没有符号表。Reading symbols from /root/pgm…(no debugging symbols fo...
如果编译时没有-g
参数,则不能实现基于C源码的符号调试功能,
看不到程序的函数名、变量名,显示的全是运行时的内存地址。
strip - Discard symbols from object files.
如果一个目标被strip了的话,在去dbg他,就不好了
一些gdb命令执行会抱怨没有符号表。
Reading symbols from /root/pgm...(no debugging symbols found)...done.
(gdb) b 20
No symbol table is loaded. Use the "file" command.
即使带了-g,没有strip,源码文件是需要在位的,否则
Reading symbols from /root/td...done.
(gdb) l
15 td.c: No such file or directory.
条件满足时,我们来dbg它。l看一下代码
22 int main (int argc, char **argv) {
23 char buf[BS], clear[BS];
24 struct ip *iph = (struct ip *) buf;
然后b main设置断点 再run起来
(gdb) b main
Breakpoint 1 at 0x409ad7: file td.c, line 24.
(gdb) r
Starting program: /root/td
Breakpoint 1, main (argc=1, argv=0x7fffffffe5b8) at td.c:24
24 struct ip *iph = (struct ip *) buf;
Missing separate debuginfos, use: debuginfo-install glibc-2.17-317.el7.x86_64
//然后再打一个断点,想继续运行到断点,但是却退出了。因为中间执行了fork
(gdb) b 65
Breakpoint 2 at 0x409c07: file td.c, line 65.
(gdb) c
Continuing.
[Detaching after fork from child process 2615]
[Inferior 1 (process 2604) exited normally]
//没关系,可以再attach上去子进程2615
//也可以再开始时就设置跟踪子进程 set follow-fork-mode child
(gdb) set follow-fork-mode child
(gdb) b 65
Breakpoint 2 at 0x409c07: file td.c, line 65.
(gdb) c
Continuing.
[Attaching after process 3687 fork to child process 3687]
[New inferior 2 (process 3687)]
[Detaching after fork from parent process 3682]
[Inferior 1 (process 3682) detached]
[Switching to process 3687]
Breakpoint 2, main (argc=1, argv=0x7fffffffe5a8) at td.c:65
65 FD_ZERO (&rfds);
有些程序是要带参数启动的,要这样使用-args参数来说明,如果不用,gdb把后面也看做要调试的程序
gdb -args ./mypgm -h xx -p yy
//看变量值的时候,可以指定想要的格式,比如p/c opt
(gdb) p opt
$2 = 104
(gdb) p/x opt
$4 = 0x68
(gdb) p /c opt
$5 = 104 'h'
/*可以执行一个shell命令,如 shell date
都是单步调试,二者区别;s 是step into 的意思;n 是 step over
变量的类型是什么?*/
(gdb) whatis opt
type = int
//修改变量的值。使用set var更好一下,可避免变量名和gdb自己的参数重名导致的意外情况
(gdb) print opt='h'
$4 = 104
(gdb) set var opt='h'
/*当ip是一个指针char *时,怎么查看;直接查看是没有问题的,但是当加上一些格式后,就要注意客体
涉及展示长度的选项 show print elements*/
(gdb) p /c ip
$12 = 240 '\360'
(gdb) p /x ip
$13 = 0x7fffffffe7f0
(gdb) whatis ip
type = char *
(gdb) p ip
$14 = 0x7fffffffe7f0 "h1"
(gdb) p/c *ip
$16 = 104 'h'
//不想在这个函数里纠缠了,继续执行完函数
(gdb) finish
Run till exit from #0 isip (ip=0x7fffffffe7f0 "h1") at ip.c:40
0x0000000000407a6e in resolve (host=0x7fffffffe7f0 "h1") at ip.c:20
20 if (isip (host))
Value returned is $17 = 1
//查看结构体
(gdb) p udh
$1 = (struct udp *) 0x7fffffffa3a4
(gdb) p *udh
$2 = {src = 8693, dst = 11631, len = 0, sum = 42922}
(gdb) set print pretty on
(gdb) p *udh
$3 = {
src = 8693,
dst = 11631,
len = 0,
sum = 42922
}
(gdb) ptype udh
type = struct udp {
u16 src;
u16 dst;
u16 len;
u16 sum;
} *
//看某变量或类型的大小
(gdb) p sizeof(unsigned long)
$19 = 8
一些其他的
info b/th (break thread)
bt 函数调用栈,当前在哪里
help 层层递进的帮助
记得开头不记得后续,或不想打时用TAB键
info locals 看本地变量,全部的
其他的其他
输入h1,用sscanf解析输入(预期点分数字的IP形式),然后判断输入是否为IP(错误的变成了0.0.0.0);
如果是IP,用inet_addr()来转换成binary data in network byte order(这个函数本就有缺陷,返回-1也是0xffffffff)
最终将h1错误的变成255.255.255.255
一个疑问,.h文件修改了,make没有检测到变化,因此没有进行重新编译
if (select (usock + 1, &rfds, NULL, NULL, NULL) < 1)
第1个参数 nfds is the highest-numbered file descriptor in any of the three sets, plus 1.
fd_set *readfds, fd_set *writefds, fd_set *exceptfds
Three independent sets of file descriptors are watched. 不要watch的就设置NULL
if (FD_ISSET (tsock, &rfds))
FD_ZERO() clears a set.
FD_SET() and FD_CLR() respectively add and remove a given file descriptor from a set.
FD_ISSET() tests to see if a file descriptor is part of the set; this is useful after select() returns.
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)