Gdb调试程序常用命令
记得用gcc 加-g 参数编译程序,以便生成的程序中带有调试信息。
1。gdb载入程序
gdb a.out
2。运行程序
run 加程序需要的参数
3。设置源代码目录
gdb directory /代码目录
4。查看函数名字用 info
gdb info functions
类似的有
gdb info files
查看函数所在的源代码行数
gdb info line 函数名字
(gdb) info line *0xb6779198
(gdb) list *0xb6779198
5。下断点
(gdb) br net.c:911 在源代码的 net.c 文件911行下断点 Breakpoint 2 at 0x4163fc: file net.c, line 911.
在改函数上下断点 br 函数名字
6。 查看寄存器 内容
info regiseter 查看寄存器 简写 i reg
7.查看堆栈
bt
8.查看变量的值 用 print 加表达式
(gdb) print (struct intfconfig_s *) 0x7fff2d15f878
$21 = (struct intfconfig_s *) 0x7fff2d15f878
9。查看类型 用ptype
(gdb) ptype struct intfconfig_s
type = struct intfconfig_s {
newtComponent ipv4Entry;
newtComponent cidr4Entry;
newtComponent ipv6Entry;
newtComponent cidr6Entry;
newtComponent gwEntry;
newtComponent nsEntry;
const char *ipv4;
const char *cidr4;
const char *ipv6;
const char *cidr6;
const char *gw;
const char *ns;
}
打印结构和成员的地址偏移
(gdb) ptype /o struct intfconfig_s
10。 查看结构的子成员
(gdb) print ((struct intfconfig_s *) 0x7fff2d15f878)->ipv6
$25 = 0x1bf63740 " \025- \177"
(gdb) print ((struct intfconfig_s *) 0x7fff2d15f878)->ipv4
$26 = 0x0
(gdb) print ((struct intfconfig_s *) 0x7fff2d15f878)->ipv6Entry
$27 = (newtComponent) 0x1bf916e0
(gdb) print ((struct intfconfig_s *) 0x7fff2d15f878)->ipv4Entry
$28 = (newtComponent) 0x7fff2d15fb90
(gdb) print ((struct intfconfig_s *) 0x7fff2d15f878)->cidr6
$29 = 0x30687465 <Address 0x30687465 out of bounds>
(gdb) print ((struct intfconfig_s *) 0x7fff2d15f878)->cidr4
$30 = 0x1bf91580 " \027 \033"
(gdb) print ((struct intfconfig_s *) 0x7fff2d15f878)->gw
$31 = 0x1bf92410 "\004"
11 执行下一句
next nexti
12。运行时修改数据
set
-
查看 详细的堆栈内容。
```text info frame 会打印出这些信息:栈的层编号,当前的函数名,函数参数值,函数所在文件及行号,函数执行到的语句。 info args 打印出当前函数的参数名及其值。 info locals 打印出当前函数中所有局部变量及其值。
(gdb) x/12a 0xbffff478 解析栈上可能的地址。
没有符号时,查看栈上的变量
(gdb) info frame Stack level 0, frame at 0xbffff480: eip = 0x805081a in TiXmlString::append (tinystr.cpp:75); saved eip 0x804e37a called by frame at 0xbffff4d0 source language c++. Arglist at 0xbffff478, args: this=0xbffff550, str=0xbffff4b4 “1”, len=1 Locals at 0xbffff478, Previous frame’s sp is 0xbffff480 Saved registers: ebp at 0xbffff478, eip at 0xbffff47c
(gdb) x/10x 0xbffff478 (使用info frame 里面 ebp at 0xbffff478的地址) 0xbffff478: 0xbffff4c8(ebp) 0x0804e37a(eip) 0xbffff550(参数1) 0xbffff4b4(参数2) 0xbffff488: 0x00000001 (参数3) 0x00000000 0xb7cd4134 0x00000000 0xbffff498: 0xbffff400 0x0804dc00
14. 应用程序的崩溃的core文件或者崩溃syslog日志分析
----------------------------------
查看加载的模块地址
```text
(gdb) info proc mappings
要先run运行起来才能看到,然后想下面这样的崩溃日志里面 ip:7f806117b8d3 是运行时地址,[7f8060da5000+52d000]是 加载的地址,7f806117b8d3 减去7f8060da5000得到文件偏移, 然后根据mappings里面的 “ Start Addr ”文件其实地址+ 文件偏移才能 info line *0xXXXXXX 来查找符号吧
[ 63.359528] traps: grpc_global_tim[848] trap invalid opcode ip:7f806117b8d3 sp:7f8057d70c30 error:0 in libgrpc.so.15.0.0[7f8060da5000+52d000]
好像直接用文件偏移info line查找也可以,不用run运行再算实时地址
(gdb) info line *0x3d6750 #文件偏移
(gdb) disassemble 0x3d6750 #文件偏移地址
另外有一个addr2line的命令行,应该跟gdb是一样的。
-
linux内核崩溃的oops位置
直接用oops打印的函数名加偏移用info line获取对应的源码行号
(gdb) info line *function_name+0xa disassemble /r function_name 对比oops打印的code, code的十六进制机器码里面用尖括号标出来的就是崩溃的那一条机器指令,对应堆栈第一行的函数崩溃地址吧
-
打印内存
x/64x 0xb60d3158