100个GDB小技巧
0. 常用
0.1 获取源代码行与程序地址之间的对应关系
(1)显示当前执行指令所在的源代码行:
info line
(2)显示特定函数或源代码行的地址信息:
info line <function-name> | <source-file>:<line-number>
例如,要查看函数myFunction
的起始地址,可以使用:
info line myFunction
或者要查看文件myfile.cpp
中的第10行对应的地址,可以使用:
info line myfile.cpp:10
(3)显示包含特定地址的源代码行信息:
info line *<address>
例如,要查看地址0x400567
所在的源代码行,可以使用:
info line *0x400567
0.2 查看C++对象的虚函数表
在GDB中,info vtbl
命令用于查看C++对象的虚函数表(Virtual Table,简称vtable)信息。虚函数表是一个数据结构,它包含了类的所有虚函数的地址。这个命令对于调试涉及多态性和虚函数调用的问题非常有用。
pwndbg> info vtbl cat_object
vtable for 'Cat' @ 0x555555557d10 (subobject @ 0x7fffffffe910):
[0]: 0x55555555536c <Cat::speak()>
[1]: 0x555555555330 <Animal::run()>
pwndbg> info vtbl dog_object
vtable for 'Dog' @ 0x555555557cf0 (subobject @ 0x7fffffffe918):
[0]: 0x5555555552f4 <Animal::speak()>
[1]: 0x5555555553a8 <Dog::run()>
0.3 反汇编指定的函数或内存地址范围
(1)反汇编特定函数:
disassemble <function-name>
这里,<function-name>
是你想要反汇编的函数的名称。这将显示该函数的机器指令。
(2)反汇编当前程序停止执行的位置周围的代码:
disassemble
如果不提供任何参数,GDB将默认反汇编当前程序计数器(Program Counter,PC)指向的指令及其周围的代码。
(3)反汇编特定内存地址范围内的指令:
disassemble <start-address> , <end-address>
这里,<start-address>
和<end-address>
是你想要反汇编的内存地址范围的开始和结束地址。
(4)显示指定数量的指令:
disassemble <address> , +<count>
这里,<address>
是起始地址,<count>
是要显示的指令数量。
例如,如果你想反汇编从地址0x55555555536c开始的10条指令,可以使用以下命令:
disassemble 0x55555555536c , +10
(5)查看当前函数的反汇编输出
disassemble /m
0.4 打印多个变量的值
对于局部变量和全局变量的查看:
- 查看全局变量和静态变量:
info variables
- 查看当前栈帧中的局部变量:
info locals
如果想在特定函数上下文查看全局变量或者其他函数内部的变量,则可能需要切换到对应的栈帧(使用 frame
或 f
命令)后再进行操作。
1. 信息显示
1.1 显示gdb版本信息
show version
1.2 显示gdb版权相关信息
show copying
1.3 启动时不显示提示信息
gdb -q
2. 函数
2.1 列出函数的名字
命令:
info functions
示例:
#include<stdio.h>
#include<stdlib.h>
int add(int a, int b) {
return a + b;
}
int sum(int a, int b) {
return a - b;
}
int main()
{
int a = 10;
int b =3;
int c = add(a, b);
int d = sum(a, b);
}
pwndbg> info functions
All defined functions:
File test1.c:
4: int add(int, int);
12: int main();
8: int sum(int, int);
Non-debugging symbols:
0x0000000000001000 _init
0x0000000000001030 __cxa_finalize@plt
0x0000000000001040 _start
0x0000000000001070 deregister_tm_clones
0x00000000000010a0 register_tm_clones
0x00000000000010e0 __do_global_dtors_aux
0x0000000000001120 frame_dummy
0x00000000000011a0 __libc_csu_init
0x0000000000001210 __libc_csu_fini
0x0000000000001218 _fini
pwndbg>
2.2 退出正在调试的函数
命令:
finish
2.3 打印函数堆栈帧信息
打印函数栈帧:
i frame
打印寄存器信息:
i registers
展示函数汇编代码:
disassemble func
示例:
#include<stdio.h>
#include<stdlib.h>
int func(void) {
int i = 0;
i += 2;
i *= 10;
return i;
}
int main()
{
func();
int a = 0;
int b = 0;
}
pwndbg> i frame
Stack level 0, frame at 0x7fffffffe960:
rip = 0x555555555150 in main (test3.c:12); saved rip = 0x7ffff7deb083
called by frame at 0x7fffffffea30
source language c.
Arglist at 0x7fffffffe950, args:
Locals at 0x7fffffffe950, Previous frame's sp is 0x7fffffffe960
Saved registers:
rip at 0x7fffffffe958
pwndbg> i registers
rax 0x555555555150 93824992235856
rbx 0x555555555180 93824992235904
rcx 0x555555555180 93824992235904
rdx 0x7fffffffea58 140737488349784
rsi 0x7fffffffea48 140737488349768
rdi 0x1 1
rbp 0x7fffffffe950 0x7fffffffe950
rsp 0x7fffffffe940 0x7fffffffe940
r8 0x0 0
r9 0x7ffff7fe0d60 140737354009952
r10 0xffffffff 4294967295
r11 0x0 0
r12 0x555555555040 93824992235584
r13 0x7fffffffea40 140737488349760
r14 0x0 0
r15 0x0 0
rip 0x55555555515c 0x55555555515c <main+12>
eflags 0x202 [ IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
pwndbg> disassemble func
Dump of assembler code for function func:
0x0000555555555129 <+0>: endbr64
0x000055555555512d <+4>: push rbp
0x000055555555512e <+5>: mov rbp,rsp
0x0000555555555131 <+8>: mov DWORD PTR [rbp-0x4],0x0
0x0000555555555138 <+15>: add DWORD PTR [rbp-0x4],0x2
0x000055555555513c <+19>: mov edx,DWORD PTR [rbp-0x4]
0x000055555555513f <+22>: mov eax,edx
0x0000555555555141 <+24>: shl eax,0x2
0x0000555555555144 <+27>: add eax,edx
0x0000555555555146 <+29>: add eax,eax
0x0000555555555148 <+31>: mov DWORD PTR [rbp-0x4],eax
0x000055555555514b <+34>: mov eax,DWORD PTR [rbp-0x4]
0x000055555555514e <+37>: pop rbp
0x000055555555514f <+38>: ret
End of assembler dump.
3. 断点
3.1 在程序地址上打断点
0x55555555518f <main> endbr64
0x555555555193 <main+4> push rbp
0x555555555194 <main+5> mov rbp, rsp
0x555555555197 <main+8> mov edi, 4
0x55555555519c <main+13> call func3
b *0x55555555519c
3.2 在程序入口处打断点
获取程序入口:
方法一:
ubuntu@niu0217:~/Dev/testGDB$ strip test4
ubuntu@niu0217:~/Dev/testGDB$ readelf -h test4
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x1040
Start of program headers: 64 (bytes into file)
Start of section headers: 12600 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 13
Size of section headers: 64 (bytes)
Number of section headers: 27
Section header string table index: 26
ubuntu@niu0217:~/Dev/testGDB$
得到入口处地址为0x1040
方法二:
pwndbg> info files
Symbols from "/home/ubuntu/Dev/testGDB/test4".
Local exec file:
`/home/ubuntu/Dev/testGDB/test4', file type elf64-x86-64.
Entry point: 0x1040
0x0000000000000318 - 0x0000000000000334 is .interp
0x0000000000000338 - 0x0000000000000358 is .note.gnu.property
0x0000000000000358 - 0x000000000000037c is .note.gnu.build-id
0x000000000000037c - 0x000000000000039c is .note.ABI-tag
0x00000000000003a0 - 0x00000000000003c4 is .gnu.hash
0x00000000000003c8 - 0x0000000000000458 is .dynsym
0x0000000000000458 - 0x00000000000004d5 is .dynstr
0x00000000000004d6 - 0x00000000000004e2 is .gnu.version
0x00000000000004e8 - 0x0000000000000508 is .gnu.version_r
0x0000000000000508 - 0x00000000000005c8 is .rela.dyn
0x0000000000001000 - 0x000000000000101b is .init
0x0000000000001020 - 0x0000000000001030 is .plt
0x0000000000001030 - 0x0000000000001040 is .plt.got
0x0000000000001040 - 0x0000000000001225 is .text
0x0000000000001228 - 0x0000000000001235 is .fini
0x0000000000002000 - 0x0000000000002004 is .rodata
0x0000000000002004 - 0x0000000000002058 is .eh_frame_hdr
0x0000000000002058 - 0x00000000000021a8 is .eh_frame
0x0000000000003df0 - 0x0000000000003df8 is .init_array
0x0000000000003df8 - 0x0000000000003e00 is .fini_array
0x0000000000003e00 - 0x0000000000003fc0 is .dynamic
0x0000000000003fc0 - 0x0000000000004000 is .got
0x0000000000004000 - 0x0000000000004010 is .data
0x0000000000004010 - 0x0000000000004018 is .bss
得到入口处地址为:0x1040
在获得的入口处地址打断点:
pwndbg> b *0x1040
Breakpoint 1 at 0x1040
3.3 保存已经设置的断点
将设置的断点保存起来:
save breakpoints file-name-to-save
批量设置保存的断点:
source file-name-to-save
示例:
保存设置的断点:
pwndbg> i b
Num Type Disp Enb Address What
1 breakpoint keep y 0x000000000000118f in main at test4.c:20
2 breakpoint keep y 0x0000000000001129 in func1 at test4.c:3
3 breakpoint keep y 0x000000000000113b in func2 at test4.c:7
pwndbg> save breakpoints file-name-to-save
Saved to file 'file-name-to-save'.
pwndbg>
加载:
pwndbg> source file-name-to-save
Breakpoint 1 at 0x118f: file test4.c, line 20.
Breakpoint 2 at 0x1129: file test4.c, line 3.
Breakpoint 3 at 0x113b: file test4.c, line 7.
pwndbg> i b
Num Type Disp Enb Address What
1 breakpoint keep y 0x000000000000118f in main at test4.c:20
2 breakpoint keep y 0x0000000000001129 in func1 at test4.c:3
3 breakpoint keep y 0x000000000000113b in func2 at test4.c:7
pwndbg>
3.4 设置临时断点
tb a.c:15
注解:tbreak
的简称为tb
临时断点的意思就是下次不会命中了。
3.5 设置条件断点
#include<stdio.h>
int main()
{
int i;
int sum = 0;
for(i = 0; i < 10; i++) {
sum += i;
}
printf("%d\n", sum);
}
pwndbg> b 9 if i==2
Breakpoint 1 at 0x1165: file test5.c, line 9.
3.6 禁用和启用断点
在GDB中,你可以使用以下命令让一个断点暂时失效:
disable breakpoint-number
将 breakpoint-number
替换为你想要禁用的断点编号。例如,如果你想要禁用编号为1的断点,可以使用以下命令:
disable 1
如果你想一次性禁用所有断点,可以使用:
disable breakpoints
当你想要重新启用一个被禁用的断点时,可以使用 enable
命令:
enable breakpoint-number
或者启用所有断点:
enable breakpoints
请注意,禁用断点并不会删除它,只是使其在当前调试会话中暂时失效。当你重新启用断点后,它将再次生效。
4. 观察点
设置watchpoints
:
watch expr
: 设置写watchpoint,当应用程序写expr, 修改其值时,程序停止运行rwatch expr
: 设置读watchpoint,当应用程序读表达式expr时,程序停止运行awatch expr
: 设置读写watchpoint, 当应用程序读或者写表达式expr时,程序都会停止运行
info watchpoints
:查看当前调试的程序中设置的watchpoints相关信息
4.1 设置观察点
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
int a = 0;
void* thread1_func(void *p_arg) {
while(1) {
a++;
sleep(10);
}
}
int main()
{
pthread_t t1;
pthread_create(&t1, NULL, thread1_func, "Thread 1");
sleep(1000);
return 0;
}
pwndbg> watch a
Hardware watchpoint 1: a
pwndbg> info watchpoints
Num Type Disp Enb Address What
1 hw watchpoint keep y a
pwndbg>
4.2 设置读观察点
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
int a = 0;
void* thread1_func(void *p_arg) {
while(1) {
printf("%d\n", a);
sleep(10);
}
}
int main()
{
pthread_t t1;
pthread_create(&t1, NULL, thread1_func, "Thread 1");
sleep(1000);
return 0;
}
pwndbg> rwatch a
Hardware read watchpoint 2: a
注解:
rwatch
也可以缩写为rw
- 每次访问
a
都会让程序停下来,rwatch
命令只对硬件观察点才生效
4.3 设置读写观察点
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
int a = 0;
void* thread1_func(void *p_arg) {
while(1) {
a++;
sleep(10);
}
}
void* thread2_func(void *p_arg) {
while(1) {
printf("%d\n", a);
sleep(10);
}
}
int main()
{
pthread_t t1;
pthread_t t2;
pthread_create(&t1, NULL, thread1_func, "Thread 1");
pthread_create(&t2, NULL, thread2_func, "Thread 2");
sleep(1000);
return 0;
}
pwndbg> awatch a
Hardware access (read/write) watchpoint 2: a
注解:
awatch
可以缩写为aw
- 每次读取或改变
a
的值都会让程序停下来
5. Catchpoint
什么是catchpoint
catch event
: 当事件event
发生的时候,程序停止运行,这里event
的取值有:
1)throw: C++抛出异常
2)catch: C++捕捉到异常
3)exec: exec被调用
4)fork: fork被调用
5)vfork: vfork被调用
6)load: 加载动态库
7)load libname: 加载名为libname的动态库
8)unload: 卸载动态库
9)unload libname: 卸载名为libname的动态库
10)syscall [args]: 调用系统调用,args可以指定系统调用号,或者系统名称
tcatch event
: 设置只停一次的catchpoint
,第一次生效后,该catchpoint
被自动删除
5.1 让catchpoint只触发一次
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<unistd.h>
int main()
{
pid_t pid;
int i = 0;;
for(; i < 2; i++) {
pid = fork();
if(pid < 0) {
exit(1);
}
else if(pid == 0) {
exit(0);
}
}
printf("Hello world\n");
return 0;
}
pwndbg> tcatch fork
Catchpoint 2 (fork)
pwndbg> i b
Num Type Disp Enb Address What
2 catchpoint del y fork
5.2 为fork设置catchpoint
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<unistd.h>
int main()
{
pid_t pid;
pid = fork();
if(pid < 0) {
exit(1);
}
else if(pid > 0) {
exit(0);
}
printf("Hello World\n");
}
pwndbg> catch fork
Catchpoint 1 (fork)
pwndbg> i b
Num Type Disp Enb Address What
1 catchpoint keep y fork
5.3 为exec调用设置catchpoint
#include<unistd.h>
int main()
{
execl("/bin/ls", "ls", NULL);
return 0;
}
pwndbg> catch exec
Catchpoint 1 (exec)
pwndbg> i b
Num Type Disp Enb Address What
1 catchpoint keep y exec
使用gdb调试程序时,可以用“catch exec
”命令为exec
系列系统调用设置catchpoint
5.4 为系统调用设置catchpoint
#include<stdio.h>
int main()
{
char p1[] = "Sam";
char *p2 = "Bob";
printf("p1 is %s, p2 is %s\n", p1, p2);
return 0;
}
pwndbg> catch syscall mmap
Catchpoint 1 (syscall 'mmap' [9])
pwndbg> i b
Num Type Disp Enb Address What
1 catchpoint keep y syscall "mmap"
pwndbg> catch syscall 9
Catchpoint 2 (syscall 'mmap' [9])
pwndbg> i b
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000555555555169 in main at test11.c:4
breakpoint already hit 1 time
2 catchpoint keep y syscall "mmap"
使用gdb调试程序时,可以使用catch syscall [name | number]
为关注的系统调用设置catchpoint
5.5 通过为ptrace调用设置catchpoint破解anti-debugging的程序
#include <sys/ptrace.h>
#include <stdio.h>
int main()
{
if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0 ) {
printf("Gdb is debugging me, exit.\n");
return 1;
}
printf("No debugger, continuing\n");
return 0;
}
pwndbg> catch syscall ptrace
Catchpoint 1 (syscall 'ptrace' [101])
pwndbg> i b
Num Type Disp Enb Address What
1 catchpoint keep y syscall "ptrace"
pwndbg> r
Starting program: /home/ubuntu/Dev/testGDB/test12
Catchpoint 1 (call to syscall ptrace), ptrace (request=PTRACE_TRACEME) at ../sysdeps/unix/sysv/linux/ptrace.c:45
45 ../sysdeps/unix/sysv/linux/ptrace.c: No such file or directory.
pwndbg> c
Continuing.
Catchpoint 1 (returned from syscall ptrace), ptrace (request=PTRACE_TRACEME) at ../sysdeps/unix/sysv/linux/ptrace.c:45
45 in ../sysdeps/unix/sysv/linux/ptrace.c
pwndbg> set $rax = 0
pwndbg> c
Continuing.
No debugger, continuing
[Inferior 1 (process 1835002) exited normally]
通过修改rax
寄存器的值,达到修改返回值的目的,从而让gdb可以继续调试程序(打印“No debugger, continuing
”)。
6. 打印
6.1 打印ASCII和宽字符字符串
x/s str1
x/ws str2
6.2 打印大数组中的内容
#include<iostream>
int main()
{
int array[201];
int i;
for (i = 0; i < 201; i++)
array[i] = i;
return 0;
}
pwndbg> p *array@10
$2 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
#设置最大限制
pwndbg> set print elements 10
pwndbg> p array
$3 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9...}
pwndbg>
6.3 打印数组中任意连续元素值
#include<iostream>
int main()
{
int array[201];
int i;
for (i = 0; i < 201; i++)
array[i] = i;
return 0;
}
#打印60~69号元素
pwndbg> p array[60]@10
$1 = {60, 61, 62, 63, 64, 65, 66, 67, 68, 69}
#打印0~9号元素
pwndbg> p *array@10
$2 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
在gdb中,如果要打印数组中任意连续元素的值,可以使用“p array[index]@num
”命令(p
是print
命令的缩写)。其中index
是数组索引(从0开始计数),num
是连续多少个元素
6.4 打印数组的索引下标
#include<stdio.h>
#include<iostream>
int num[10] = {
1 << 0,
1 << 1,
1 << 2,
1 << 3,
1 << 4,
1 << 5,
1 << 6,
1 << 7,
1 << 8,
1 << 9
};
int main (void)
{
int i;
for (i = 0; i < 10; i++)
printf ("num[%d] = %d\n", i, num[i]);
return 0;
}
pwndbg> p num
$1 = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512}
pwndbg> set print array-indexes on
pwndbg> p num
$2 = {[0] = 1, [1] = 2, [2] = 4, [3] = 8, [4] = 16, [5] = 32, [6] = 64, [7] = 128, [8] = 256, [9] = 512}
pwndbg>
在gdb中默认不打印下标,我们可以通过命令set print array-indexes on
,来让其打印下标。
6.5 打印函数局部变量的值
#include<stdio.h>
#include<iostream>
void fun_a(void)
{
int a = 0;
printf("%d\n", a);
}
void fun_b(void)
{
int b = 1;
fun_a();
printf("%d\n", b);
}
void fun_c(void)
{
int c = 2;
fun_b();
printf("%d\n", c);
}
void fun_d(void)
{
int d = 3;
fun_c();
printf("%d\n", d);
}
int main(void)
{
int var = -1;
fun_d();
return 0;
}
pwndbg> bt
#0 fun_a () at test16.cpp:5
#1 0x00005555555551cd in fun_b () at test16.cpp:13
#2 0x00005555555551fe in fun_c () at test16.cpp:20
#3 0x000055555555522f in fun_d () at test16.cpp:27
#4 0x0000555555555260 in main () at test16.cpp:34
#5 0x00007ffff7c09083 in __libc_start_main (main=0x555555555248 <main()>, argc=1, argv=0x7fffffffea48, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffea38) at ../csu/libc-start.c:308
#6 0x00005555555550ce in _start ()
显示各个函数的局部变量值:
pwndbg> bt full
#0 fun_a () at test16.cpp:5
a = 21845
#1 0x00005555555551cd in fun_b () at test16.cpp:13
b = 1
#2 0x00005555555551fe in fun_c () at test16.cpp:20
c = 2
#3 0x000055555555522f in fun_d () at test16.cpp:27
d = 3
#4 0x0000555555555260 in main () at test16.cpp:34
var = -1
#5 0x00007ffff7c09083 in __libc_start_main (main=0x555555555248 <main()>, argc=1, argv=0x7fffffffea48, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffea38) at ../csu/libc-start.c:308
self = <optimized out>
result = <optimized out>
unwind_buf = {
cancel_jmp_buf = {{
jmp_buf = {93824992236240, 7416317012288219881, 93824992235680, 140737488349760, 0, 0, -7416317013009618199, -7416335093455770903},
mask_was_saved = 0
}},
priv = {
pad = {0x0, 0x0, 0x1, 0x7fffffffea48},
data = {
prev = 0x0,
cleanup = 0x0,
canceltype = 1
}
}
}
not_first_call = <optimized out>
#6 0x00005555555550ce in _start ()
No symbol table info available.
从内向外显示n个栈桢,及其局部变量:
pwndbg> bt full 2
#0 fun_a () at test16.cpp:5
a = 21845
#1 0x00005555555551cd in fun_b () at test16.cpp:13
b = 1
(More stack frames follow...)
从外向内显示n个栈桢,及其局部变量:
pwndbg> bt full -4
#3 0x000055555555522f in fun_d () at test16.cpp:27
d = 3
#4 0x0000555555555260 in main () at test16.cpp:34
var = -1
#5 0x00007ffff7c09083 in __libc_start_main (main=0x555555555248 <main()>, argc=1, argv=0x7fffffffea48, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffea38) at ../csu/libc-start.c:308
self = <optimized out>
result = <optimized out>
unwind_buf = {
cancel_jmp_buf = {{
jmp_buf = {93824992236240, 7416317012288219881, 93824992235680, 140737488349760, 0, 0, -7416317013009618199, -7416335093455770903},
mask_was_saved = 0
}},
priv = {
pad = {0x0, 0x0, 0x1, 0x7fffffffea48},
data = {
prev = 0x0,
cleanup = 0x0,
canceltype = 1
}
}
}
not_first_call = <optimized out>
#6 0x00005555555550ce in _start ()
No symbol table info available.
打印当前函数局部变量的值:
pwndbg> info locals
a = 21845
6.6 打印进程内存信息
查看进程的内存映射信息:
pwndbg> i proc mappings
process 1844032
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x555555554000 0x555555555000 0x1000 0x0 /home/ubuntu/Dev/testGDB/test16
0x555555555000 0x555555556000 0x1000 0x1000 /home/ubuntu/Dev/testGDB/test16
0x555555556000 0x555555557000 0x1000 0x2000 /home/ubuntu/Dev/testGDB/test16
0x555555557000 0x555555558000 0x1000 0x2000 /home/ubuntu/Dev/testGDB/test16
0x555555558000 0x555555559000 0x1000 0x3000 /home/ubuntu/Dev/testGDB/test16
0x555555559000 0x55555557a000 0x21000 0x0 [heap]
0x7ffff7a77000 0x7ffff7a7b000 0x4000 0x0
0x7ffff7a7b000 0x7ffff7a7e000 0x3000 0x0 /usr/lib/x86_64-linux-gnu/libgcc_s.so.1
0x7ffff7a7e000 0x7ffff7a90000 0x12000 0x3000 /usr/lib/x86_64-linux-gnu/libgcc_s.so.1
0x7ffff7a90000 0x7ffff7a94000 0x4000 0x15000 /usr/lib/x86_64-linux-gnu/libgcc_s.so.1
0x7ffff7a94000 0x7ffff7a95000 0x1000 0x18000 /usr/lib/x86_64-linux-gnu/libgcc_s.so.1
0x7ffff7a95000 0x7ffff7a96000 0x1000 0x19000 /usr/lib/x86_64-linux-gnu/libgcc_s.so.1
0x7ffff7a96000 0x7ffff7aa3000 0xd000 0x0 /usr/lib/x86_64-linux-gnu/libm-2.31.so
0x7ffff7aa3000 0x7ffff7b4a000 0xa7000 0xd000 /usr/lib/x86_64-linux-gnu/libm-2.31.so
0x7ffff7b4a000 0x7ffff7be3000 0x99000 0xb4000 /usr/lib/x86_64-linux-gnu/libm-2.31.so
0x7ffff7be3000 0x7ffff7be4000 0x1000 0x14c000 /usr/lib/x86_64-linux-gnu/libm-2.31.so
0x7ffff7be4000 0x7ffff7be5000 0x1000 0x14d000 /usr/lib/x86_64-linux-gnu/libm-2.31.so
0x7ffff7be5000 0x7ffff7c07000 0x22000 0x0 /usr/lib/x86_64-linux-gnu/libc-2.31.so
0x7ffff7c07000 0x7ffff7d7f000 0x178000 0x22000 /usr/lib/x86_64-linux-gnu/libc-2.31.so
0x7ffff7d7f000 0x7ffff7dcd000 0x4e000 0x19a000 /usr/lib/x86_64-linux-gnu/libc-2.31.so
0x7ffff7dcd000 0x7ffff7dd1000 0x4000 0x1e7000 /usr/lib/x86_64-linux-gnu/libc-2.31.so
0x7ffff7dd1000 0x7ffff7dd3000 0x2000 0x1eb000 /usr/lib/x86_64-linux-gnu/libc-2.31.so
0x7ffff7dd3000 0x7ffff7dd7000 0x4000 0x0
0x7ffff7dd7000 0x7ffff7e6d000 0x96000 0x0 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28
0x7ffff7e6d000 0x7ffff7f5e000 0xf1000 0x96000 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28
0x7ffff7f5e000 0x7ffff7fa7000 0x49000 0x187000 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28
0x7ffff7fa7000 0x7ffff7fa8000 0x1000 0x1d0000 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28
0x7ffff7fa8000 0x7ffff7fb3000 0xb000 0x1d0000 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28
0x7ffff7fb3000 0x7ffff7fb6000 0x3000 0x1db000 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28
0x7ffff7fb6000 0x7ffff7fbb000 0x5000 0x0
0x7ffff7fcb000 0x7ffff7fce000 0x3000 0x0 [vvar]
0x7ffff7fce000 0x7ffff7fcf000 0x1000 0x0 [vdso]
0x7ffff7fcf000 0x7ffff7fd0000 0x1000 0x0 /usr/lib/x86_64-linux-gnu/ld-2.31.so
0x7ffff7fd0000 0x7ffff7ff3000 0x23000 0x1000 /usr/lib/x86_64-linux-gnu/ld-2.31.so
0x7ffff7ff3000 0x7ffff7ffb000 0x8000 0x24000 /usr/lib/x86_64-linux-gnu/ld-2.31.so
0x7ffff7ffc000 0x7ffff7ffd000 0x1000 0x2c000 /usr/lib/x86_64-linux-gnu/ld-2.31.so
0x7ffff7ffd000 0x7ffff7ffe000 0x1000 0x2d000 /usr/lib/x86_64-linux-gnu/ld-2.31.so
0x7ffff7ffe000 0x7ffff7fff000 0x1000 0x0
0x7ffffffde000 0x7ffffffff000 0x21000 0x0 [stack]
0xffffffffff600000 0xffffffffff601000 0x1000 0x0 [vsyscall]
pwndbg>
更详细地输出进程的内存信息,包括引用的动态链接库:
pwndbg> i files
Symbols from "/home/ubuntu/Dev/testGDB/test16".
Native process:
Using the running image of child process 1844032.
While running this, GDB does not access memory from...
Local exec file:
`/home/ubuntu/Dev/testGDB/test16', file type elf64-x86-64.
Entry point: 0x5555555550a0
0x0000555555554318 - 0x0000555555554334 is .interp
0x0000555555554338 - 0x0000555555554358 is .note.gnu.property
0x0000555555554358 - 0x000055555555437c is .note.gnu.build-id
0x000055555555437c - 0x000055555555439c is .note.ABI-tag
0x00005555555543a0 - 0x00005555555543c4 is .gnu.hash
0x00005555555543c8 - 0x00005555555544b8 is .dynsym
0x00005555555544b8 - 0x0000555555554594 is .dynstr
0x0000555555554594 - 0x00005555555545a8 is .gnu.version
0x00005555555545a8 - 0x00005555555545e8 is .gnu.version_r
0x00005555555545e8 - 0x00005555555546d8 is .rela.dyn
0x00005555555546d8 - 0x0000555555554720 is .rela.plt
0x0000555555555000 - 0x000055555555501b is .init
0x0000555555555020 - 0x0000555555555060 is .plt
0x0000555555555060 - 0x0000555555555070 is .plt.got
0x0000555555555070 - 0x00005555555550a0 is .plt.sec
0x00005555555550a0 - 0x0000555555555345 is .text
0x0000555555555348 - 0x0000555555555355 is .fini
0x0000555555556000 - 0x0000555555556009 is .rodata
0x000055555555600c - 0x0000555555556080 is .eh_frame_hdr
0x0000555555556080 - 0x0000555555556248 is .eh_frame
0x0000555555557d88 - 0x0000555555557d98 is .init_array
0x0000555555557d98 - 0x0000555555557da0 is .fini_array
0x0000555555557da0 - 0x0000555555557fa0 is .dynamic
0x0000555555557fa0 - 0x0000555555558000 is .got
0x0000555555558000 - 0x0000555555558010 is .data
0x0000555555558010 - 0x0000555555558018 is .bss
0x00007ffff7fcf2a8 - 0x00007ffff7fcf2c8 is .note.gnu.property in /lib64/ld-linux-x86-64.so.2
0x00007ffff7fcf2c8 - 0x00007ffff7fcf2ec is .note.gnu.build-id in /lib64/ld-linux-x86-64.so.2
0x00007ffff7fcf2f0 - 0x00007ffff7fcf3c4 is .hash in /lib64/ld-linux-x86-64.so.2
0x00007ffff7fcf3c8 - 0x00007ffff7fcf4c0 is .gnu.hash in /lib64/ld-linux-x86-64.so.2
0x00007ffff7fcf4c0 - 0x00007ffff7fcf7f0 is .dynsym in /lib64/ld-linux-x86-64.so.2
0x00007ffff7fcf7f0 - 0x00007ffff7fcfa14 is .dynstr in /lib64/ld-linux-x86-64.so.2
0x00007ffff7fcfa14 - 0x00007ffff7fcfa58 is .gnu.version in /lib64/ld-linux-x86-64.so.2
0x00007ffff7fcfa58 - 0x00007ffff7fcfafc is .gnu.version_d in /lib64/ld-linux-x86-64.so.2
0x00007ffff7fcfb00 - 0x00007ffff7fcff20 is .rela.dyn in /lib64/ld-linux-x86-64.so.2
0x00007ffff7fcff20 - 0x00007ffff7fcffc8 is .rela.plt in /lib64/ld-linux-x86-64.so.2
0x00007ffff7fd0000 - 0x00007ffff7fd0080 is .plt in /lib64/ld-linux-x86-64.so.2
0x00007ffff7fd0080 - 0x00007ffff7fd0090 is .plt.got in /lib64/ld-linux-x86-64.so.2
0x00007ffff7fd0090 - 0x00007ffff7fd0100 is .plt.sec in /lib64/ld-linux-x86-64.so.2
0x00007ffff7fd0100 - 0x00007ffff7ff2684 is .text in /lib64/ld-linux-x86-64.so.2
0x00007ffff7ff3000 - 0x00007ffff7ff7dbb is .rodata in /lib64/ld-linux-x86-64.so.2
0x00007ffff7ff7dbb - 0x00007ffff7ff7dbc is .stapsdt.base in /lib64/ld-linux-x86-64.so.2
0x00007ffff7ff7dbc - 0x00007ffff7ff84e0 is .eh_frame_hdr in /lib64/ld-linux-x86-64.so.2
0x00007ffff7ff84e0 - 0x00007ffff7ffaccc is .eh_frame in /lib64/ld-linux-x86-64.so.2
0x00007ffff7ffc520 - 0x00007ffff7ffce64 is .data.rel.ro in /lib64/ld-linux-x86-64.so.2
0x00007ffff7ffce68 - 0x00007ffff7ffcfd8 is .dynamic in /lib64/ld-linux-x86-64.so.2
0x00007ffff7ffcfd8 - 0x00007ffff7ffcfe8 is .got in /lib64/ld-linux-x86-64.so.2
0x00007ffff7ffd000 - 0x00007ffff7ffd050 is .got.plt in /lib64/ld-linux-x86-64.so.2
0x00007ffff7ffd060 - 0x00007ffff7ffdff8 is .data in /lib64/ld-linux-x86-64.so.2
0x00007ffff7ffe000 - 0x00007ffff7ffe190 is .bss in /lib64/ld-linux-x86-64.so.2
0x00007ffff7fce120 - 0x00007ffff7fce164 is .hash in system-supplied DSO at 0x7ffff7fce000
0x00007ffff7fce168 - 0x00007ffff7fce1b8 is .gnu.hash in system-supplied DSO at 0x7ffff7fce000
0x00007ffff7fce1b8 - 0x00007ffff7fce2d8 is .dynsym in system-supplied DSO at 0x7ffff7fce000
0x00007ffff7fce2d8 - 0x00007ffff7fce34a is .dynstr in system-supplied DSO at 0x7ffff7fce000
0x00007ffff7fce34a - 0x00007ffff7fce362 is .gnu.version in system-supplied DSO at 0x7ffff7fce000
0x00007ffff7fce368 - 0x00007ffff7fce3a0 is .gnu.version_d in system-supplied DSO at 0x7ffff7fce000
0x00007ffff7fce3a0 - 0x00007ffff7fce4c0 is .dynamic in system-supplied DSO at 0x7ffff7fce000
0x00007ffff7fce4c0 - 0x00007ffff7fce514 is .note in system-supplied DSO at 0x7ffff7fce000
0x00007ffff7fce514 - 0x00007ffff7fce558 is .eh_frame_hdr in system-supplied DSO at 0x7ffff7fce000
0x00007ffff7fce558 - 0x00007ffff7fce674 is .eh_frame in system-supplied DSO at 0x7ffff7fce000
0x00007ffff7fce680 - 0x00007ffff7fce9c5 is .text in system-supplied DSO at 0x7ffff7fce000
0x00007ffff7fce9c5 - 0x00007ffff7fcea20 is .altinstructions in system-supplied DSO at 0x7ffff7fce000
0x00007ffff7fcea20 - 0x00007ffff7fcea3c is .altinstr_replacement in system-supplied DSO at 0x7ffff7fce000
0x00007ffff7dd72e0 - 0x00007ffff7dd7300 is .note.gnu.property in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7dd7300 - 0x00007ffff7dd7324 is .note.gnu.build-id in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7dd7328 - 0x00007ffff7ddfedc is .gnu.hash in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7ddfee0 - 0x00007ffff7e034c0 is .dynsym in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7e034c0 - 0x00007ffff7e4b0c5 is .dynstr in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7e4b0c6 - 0x00007ffff7e4dfee is .gnu.version in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7e4dff0 - 0x00007ffff7e4e61c is .gnu.version_d in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7e4e620 - 0x00007ffff7e4e760 is .gnu.version_r in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7e4e760 - 0x00007ffff7e66b38 is .rela.dyn in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7e66b38 - 0x00007ffff7e6cac0 is .rela.plt in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7e6d000 - 0x00007ffff7e6d01b is .init in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7e6d020 - 0x00007ffff7e70fe0 is .plt in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7e70fe0 - 0x00007ffff7e71170 is .plt.got in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7e71170 - 0x00007ffff7e75120 is .plt.sec in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7e75120 - 0x00007ffff7f5d332 is .text in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7f5d334 - 0x00007ffff7f5d341 is .fini in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7f5e000 - 0x00007ffff7f672b3 is .rodata in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7f672b3 - 0x00007ffff7f672b4 is .stapsdt.base in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7f672b4 - 0x00007ffff7f705f0 is .eh_frame_hdr in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7f705f0 - 0x00007ffff7f9e8c0 is .eh_frame in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7f9e8c0 - 0x00007ffff7fa6e6b is .gcc_except_table in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7fa8978 - 0x00007ffff7fa8998 is .tbss in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7fa8978 - 0x00007ffff7fa89d8 is .init_array in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7fa89d8 - 0x00007ffff7fa89e0 is .fini_array in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7fa89e0 - 0x00007ffff7fb1c68 is .data.rel.ro in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7fb1c68 - 0x00007ffff7fb1e88 is .dynamic in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7fb1e88 - 0x00007ffff7fb2ff0 is .got in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7fb3000 - 0x00007ffff7fb4ff0 is .got.plt in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7fb5000 - 0x00007ffff7fb5190 is .data in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7fb51c0 - 0x00007ffff7fb8800 is .bss in /lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff7be5350 - 0x00007ffff7be5370 is .note.gnu.property in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7be5370 - 0x00007ffff7be5394 is .note.gnu.build-id in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7be5394 - 0x00007ffff7be53b4 is .note.ABI-tag in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7be53b8 - 0x00007ffff7be906c is .gnu.hash in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7be9070 - 0x00007ffff7bf6ea0 is .dynsym in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7bf6ea0 - 0x00007ffff7bfcf61 is .dynstr in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7bfcf62 - 0x00007ffff7bfe1e6 is .gnu.version in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7bfe1e8 - 0x00007ffff7bfe658 is .gnu.version_d in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7bfe658 - 0x00007ffff7bfe688 is .gnu.version_r in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7bfe688 - 0x00007ffff7c06080 is .rela.dyn in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7c06080 - 0x00007ffff7c064e8 is .rela.plt in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7c07000 - 0x00007ffff7c07300 is .plt in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7c07300 - 0x00007ffff7c07340 is .plt.got in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7c07340 - 0x00007ffff7c07630 is .plt.sec in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7c07630 - 0x00007ffff7d7c27d is .text in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7d7c280 - 0x00007ffff7d7e624 is __libc_freeres_fn in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7d7f000 - 0x00007ffff7da3698 is .rodata in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7da3698 - 0x00007ffff7da3699 is .stapsdt.base in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7da36a0 - 0x00007ffff7da36bc is .interp in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7da36bc - 0x00007ffff7da9590 is .eh_frame_hdr in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7da9590 - 0x00007ffff7dc89a8 is .eh_frame in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7dc89a8 - 0x00007ffff7dc8dcd is .gcc_except_table in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7dc8dd0 - 0x00007ffff7dcc2c4 is .hash in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7dcd788 - 0x00007ffff7dcd798 is .tdata in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7dcd798 - 0x00007ffff7dcd818 is .tbss in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7dcd798 - 0x00007ffff7dcd7a8 is .init_array in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7dcd7a8 - 0x00007ffff7dcd898 is __libc_subfreeres in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7dcd898 - 0x00007ffff7dcd8a0 is __libc_atexit in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7dcd8a0 - 0x00007ffff7dce608 is __libc_IO_vtables in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7dce620 - 0x00007ffff7dd0b80 is .data.rel.ro in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7dd0b80 - 0x00007ffff7dd0d60 is .dynamic in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7dd0d60 - 0x00007ffff7dd0ff8 is .got in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7dd1000 - 0x00007ffff7dd1190 is .got.plt in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7dd11a0 - 0x00007ffff7dd27a0 is .data in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7dd27a0 - 0x00007ffff7dd6660 is .bss in /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff7a962a8 - 0x00007ffff7a962c8 is .note.gnu.property in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7a962c8 - 0x00007ffff7a962ec is .note.gnu.build-id in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7a962ec - 0x00007ffff7a9630c is .note.ABI-tag in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7a96310 - 0x00007ffff7a987dc is .gnu.hash in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7a987e0 - 0x00007ffff7a9f0e0 is .dynsym in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7a9f0e0 - 0x00007ffff7aa1446 is .dynstr in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7aa1446 - 0x00007ffff7aa1d06 is .gnu.version in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7aa1d08 - 0x00007ffff7aa1ecc is .gnu.version_d in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7aa1ed0 - 0x00007ffff7aa1f30 is .gnu.version_r in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7aa1f30 - 0x00007ffff7aa2068 is .rela.dyn in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7aa2068 - 0x00007ffff7aa2308 is .rela.plt in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7aa3000 - 0x00007ffff7aa301b is .init in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7aa3020 - 0x00007ffff7aa31f0 is .plt in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7aa31f0 - 0x00007ffff7aa3200 is .plt.got in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7aa3200 - 0x00007ffff7aa33c0 is .plt.sec in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7aa33c0 - 0x00007ffff7b49fa8 is .text in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7b49fa8 - 0x00007ffff7b49fb5 is .fini in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7b4a000 - 0x00007ffff7bd58d4 is .rodata in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7bd58d4 - 0x00007ffff7bd58d5 is .stapsdt.base in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7bd58d8 - 0x00007ffff7bd753c is .eh_frame_hdr in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7bd7540 - 0x00007ffff7be09a4 is .eh_frame in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7be09a8 - 0x00007ffff7be2b14 is .hash in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7be3d80 - 0x00007ffff7be3d88 is .init_array in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7be3d88 - 0x00007ffff7be3d90 is .fini_array in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7be3d90 - 0x00007ffff7be3fb0 is .dynamic in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7be3fb0 - 0x00007ffff7be4000 is .got in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7be4000 - 0x00007ffff7be40f8 is .got.plt in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7be40f8 - 0x00007ffff7be4104 is .data in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7be4104 - 0x00007ffff7be4110 is .bss in /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7a7b2a8 - 0x00007ffff7a7b2c8 is .note.gnu.property in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a7b2c8 - 0x00007ffff7a7b2ec is .note.gnu.build-id in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a7b2f0 - 0x00007ffff7a7b7e8 is .gnu.hash in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a7b7e8 - 0x00007ffff7a7c808 is .dynsym in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a7c808 - 0x00007ffff7a7d0b0 is .dynstr in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a7d0b0 - 0x00007ffff7a7d208 is .gnu.version in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a7d208 - 0x00007ffff7a7d3cc is .gnu.version_d in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a7d3d0 - 0x00007ffff7a7d400 is .gnu.version_r in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a7d400 - 0x00007ffff7a7d4f0 is .rela.dyn in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a7d4f0 - 0x00007ffff7a7d928 is .rela.plt in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a7e000 - 0x00007ffff7a7e01b is .init in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a7e020 - 0x00007ffff7a7e300 is .plt in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a7e300 - 0x00007ffff7a7e310 is .plt.got in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a7e310 - 0x00007ffff7a7e5e0 is .plt.sec in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a7e5e0 - 0x00007ffff7a8f055 is .text in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a8f058 - 0x00007ffff7a8f065 is .fini in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a90000 - 0x00007ffff7a90cbc is .rodata in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a90cbc - 0x00007ffff7a91348 is .eh_frame_hdr in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a91348 - 0x00007ffff7a93364 is .eh_frame in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a94dc8 - 0x00007ffff7a94dd8 is .init_array in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a94dd8 - 0x00007ffff7a94de0 is .fini_array in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a94de0 - 0x00007ffff7a94fd0 is .dynamic in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a94fd0 - 0x00007ffff7a95000 is .got in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a95000 - 0x00007ffff7a95180 is .got.plt in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a95180 - 0x00007ffff7a95190 is .data in /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ffff7a951a0 - 0x00007ffff7a95448 is .bss in /lib/x86_64-linux-gnu/libgcc_s.so.1
pwndbg>
6.7 打印变量的类型和所在文件
#include<stdio.h>
struct child {
char name[10];
enum { boy, girl } gender;
};
struct child he = { "Tom", boy };
int main (void)
{
static struct child she = { "Jerry", girl };
printf ("Hello %s %s.\n", he.gender == boy ? "boy" : "girl", he.name);
printf ("Hello %s %s.\n", she.gender == boy ? "boy" : "girl", she.name);
return 0;
}
查看变量的类型:
pwndbg> whatis he
type = struct child
查看详细的类型信息:
pwndbg> ptype he
type = struct child {
char name[10];
enum {boy, girl} gender;
}
查看定义该变量的文件:
pwndbg> i variables ^he$
All variables matching regular expression "^he$":
File test17.c:
8: struct child he;
pwndbg>
特别注意:需要用到正则表达式,不然会匹配很多he
6.8 打印内存的值
#include <stdio.h>
int main(void)
{
int i = 0;
char a[100];
for (i = 0; i < sizeof(a); i++)
{
a[i] = i;
}
return 0;
}
gdb中使用“x
”命令来打印内存的值,格式为“x/nfu addr
”。含义为以f
格式打印从addr
开始的n
个长度单元为u
的内存值。参数具体含义如下:
a)n:输出单元的个数。
b)f:是输出格式。比如x
是以16进制形式输出,o
是以8进制形式输出,等等。
c)u:标明一个单元的长度。b
是一个byte
,h
是两个byte
(halfword),w
是四个byte
(word),g
是八个byte
(giant word)
以16进制格式打印数组前a
16个byte的值:
pwndbg> x/16xb a
0x7fffffffe8e0: 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07
0x7fffffffe8e8: 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f
以无符号10进制格式打印数组a
前16个byte的值:
pwndbg> x/16ub a
0x7fffffffe8e0: 0 1 2 3 4 5 6 7
0x7fffffffe8e8: 8 9 10 11 12 13 14 15
以2进制格式打印数组前16个a
byte的值::
pwndbg> x/16tb a
0x7fffffffe8e0: 00000000 00000001 00000010 00000011 00000100 00000101 00000110 00000111
0x7fffffffe8e8: 00001000 00001001 00001010 00001011 00001100 00001101 00001110 00001111
以16进制格式打印数组a
前16个word(4个byte)的值::
pwndbg> x/16xw a
0x7fffffffe8e0: 0x03020100 0x07060504 0x0b0a0908 0x0f0e0d0c
0x7fffffffe8f0: 0x13121110 0x17161514 0x1b1a1918 0x1f1e1d1c
0x7fffffffe900: 0x23222120 0x27262524 0x2b2a2928 0x2f2e2d2c
0x7fffffffe910: 0x33323130 0x37363534 0x3b3a3938 0x3f3e3d3c
打印指定内存处的10条指令:
x/10i 0x55555555536c
使用x命令查看内存的内容:
- 形式:
x/FMT ADDRESS
,其中FMT中三部分组成:count format size(format与size的参数位置可以互换) - format:
- o:octal, 即八进制
- x:hex, 十六进制
- d:decimal, 十进制
- u:unsigned decimal
- t:binary, 二进制
- f:float, 符号数
- a:address, 地址的形式
- c:char类型
- s:string
- z:hes, zero padded on the left
- i:指令类型
- size:
- b:byte, 一个字节大小
- h:2个字节
- w:4个字节
- g:giant, 8个字节
6.9 每行打印一个结构体成员
#include <stdio.h>
#include <pthread.h>
typedef struct
{
int a;
int b;
int c;
int d;
pthread_mutex_t mutex;
}ex_st;
int main(void) {
ex_st st = {1, 2, 3, 4, PTHREAD_MUTEX_INITIALIZER};
printf("%d,%d,%d,%d\n", st.a, st.b, st.c, st.d);
return 0;
}
默认情况下,gdb以一种“紧凑”的方式打印结构体。可以执set print pretty on
命令,这样每行只会显示结构体的一名成员,而且还会根据成员的定义层次进行缩进:
pwndbg> set print pretty on
pwndbg> p st
$1 = {
a = 1,
b = 2,
c = 3,
d = 4,
mutex = {
__data = {
__lock = 0,
__count = 0,
__owner = 0,
__nusers = 0,
__kind = 0,
__spins = 0,
__elision = 0,
__list = {
__prev = 0x0,
__next = 0x0
}
},
__size = '\000' <repeats 39 times>,
__align = 0
}
}
6.10 按照派生类型打印对象
#include <iostream>
using namespace std;
class Shape {
public:
virtual void draw () {}
};
class Circle : public Shape {
int radius;
public:
Circle () { radius = 1; }
void draw () { cout << "drawing a circle...\n"; }
};
class Square : public Shape {
int height;
public:
Square () { height = 2; }
void draw () { cout << "drawing a square...\n"; }
};
void drawShape (class Shape &p)
{
p.draw ();
}
int main (void)
{
Circle a;
Square b;
drawShape (a);
drawShape (b);
return 0;
}
在gdb中,当打印一个对象时,缺省是按照声明的类型进行打印:
23 void drawShape (class Shape &p)
24 {
► 25 p.draw ();
26 }
pwndbg> p p
$1 = (Shape &) @0x7fffffffe920: {
_vptr.Shape = 0x555555557d38 <vtable for Circle+16>
}
pwndbg> whatis p
type = Shape &
pwndbg> ptype p
type = class Shape {
public:
virtual void draw(void);
} &
pwndbg>
缺省按照派生类型进行打印:
23 void drawShape (class Shape &p)
24 {
► 25 p.draw ();
26 }
pwndbg> set print object on
pwndbg> p p
$2 = (Circle &) @0x7fffffffe920: {
<Shape> = {
_vptr.Shape = 0x555555557d38 <vtable for Circle+16>
},
members of Circle:
radius = 1
}
pwndbg> whatis p
type = /* real type = Circle & */
Shape &
pwndbg> ptype p
type = /* real type = Circle & */
class Shape {
public:
virtual void draw(void);
} &
pwndbg>
6.11 指定程序的输入输出设备
#include <stdio.h>
int main(void)
{
int i;
for (i = 0; i < 100; i++)
{
printf("i = %d\n", i);
}
return 0;
}
在gdb中,缺省情况下程序的输入输出是和gdb使用同一个终端。你也可以为程序指定一个单独的输入输出终端。
首先,打开一个新终端,使用如下命令获得设备文件名:
$ tty
/dev/pts/2
然后,通过命令行选项指定程序的输入输出设备:
$ gdb -tty /dev/pts/2 ./a.out
(gdb) r
或者,在gdb中,使用命令进行设置:
(gdb) tty /dev/pts/2
这样就实现了在一个终端输入,在另一个终端输出。
7. 多进程/线程
7.1 调试已经运行的进程
假设:
- 运行的程序:hello
- 进程号:65772
查看运行的程序的进程号:ps -aux | grep hello
切换到root用户:su
此时运行的程序会中断,等待你的调试;如果想要程序继续执行,那就退出gdb调试:gdb hello -p 65772
7.2 调试多进程
调试父进程:set follow-fork-mode parent
(默认就是调试父进程)
调试子进程:set follow-fork-mode child
设置调试模式:
set detach-on-fork on
(默认是on). 表示调试当前进程的时候,其它的进程继续运行set detach-on-fork off
。表示调试当前进程的时候,其它的进程被gdb挂起
查看调试的进程:info inferiors
切换当前调试的进程:inferior 进程id
7.3 调试多线程
查看线程:info threads
切换线程:thread 线程id
只运行当前线程:set scheduler-locking on
运行全部的线程:set scheduler-locking off
指定某线程执行某gdb命令:thread apply 线程id cmd
全部的线程执行某gdb命令:thread apply all cmd
8. 调试core
什么是core文件?
- 在Linux下程序不寻常退出时,内核会在当前工作目录下生成一个core文件(是一个内存映像,同时加上调试信息)。使用gdb来查看core文件,可以指示出导致程序出错的代码所在文件和行数。
命令:
ulimit -a
:检查生成core文件的选项是否打开ulimit -c unlimited
:程序会生成core文件ulimit -c 0
:程序不会生成core文件gdb + 可执行程序 + core文件
:显示出错的代码sudo bash -c "echo core > /proc/sys/kernel/core_pattern "
:指定core文件生成在当前目录下bt
:显示调用栈
9. 改变程序的执行
9.1 改变字符串的值
#include <stdio.h>
int main(void)
{
char p1[] = "Sam";
char *p2 = "Bob";
printf("p1 is %s, p2 is %s\n", p1, p2);
return 0;
}
使用gdb调试程序时,可以用“set
”命令改变字符串的值:
pwndbg> set p1="Jil"
pwndbg> set p2="Bill"
pwndbg> p p1
$3 = "Jil"
pwndbg> p p2
$4 = 0x7ffff7fbaf80 "Bill"
pwndbg>
9.2 设置变量的值
在gdb中,可以用“set var variable=expr
”命令设置变量的值:
set var i = 8
用“set {type}address=expr
”的方式,含义是给存储地址在address
,变量类型为type
的变量赋值:
set {int}0x8047a54 = 8
set var $eax = 8
10. 信号
10.1 查看信号处理信息
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
void handler(int sig);
void handler(int sig)
{
signal(sig, handler);
printf("Receive signal: %d\n", sig);
}
int main(void) {
signal(SIGINT, handler);
signal(SIGALRM, handler);
while (1)
{
sleep(1);
}
return 0;
}
用gdb调试程序时,可以用“i signals
”命令(或者“i handle
”命令,i
是info
命令缩写)查看gdb如何处理进程收到的信号:
pwndbg> i signals
Signal Stop Print Pass to program Description
SIGHUP Yes Yes Yes Hangup
SIGINT Yes Yes No Interrupt
SIGQUIT Yes Yes Yes Quit
SIGILL Yes Yes Yes Illegal instruction
SIGTRAP Yes Yes No Trace/breakpoint trap
SIGABRT Yes Yes Yes Aborted
SIGEMT Yes Yes Yes Emulation trap
SIGFPE Yes Yes Yes Arithmetic exception
SIGKILL Yes Yes Yes Killed
SIGBUS Yes Yes No Bus error
SIGSEGV Yes Yes No Segmentation fault
SIGSYS Yes Yes Yes Bad system call
SIGPIPE No Yes No Broken pipe
SIGALRM No Yes No Alarm clock
SIGTERM Yes Yes Yes Terminated
SIGURG No No Yes Urgent I/O condition
SIGSTOP Yes Yes Yes Stopped (signal)
SIGTSTP Yes Yes Yes Stopped (user)
SIGCONT Yes Yes Yes Continued
SIGCHLD No No Yes Child status changed
SIGTTIN Yes Yes Yes Stopped (tty input)
SIGTTOU Yes Yes Yes Stopped (tty output)
SIGIO No No Yes I/O possible
SIGXCPU Yes Yes Yes CPU time limit exceeded
SIGXFSZ Yes Yes Yes File size limit exceeded
SIGVTALRM No No Yes Virtual timer expired
SIGPROF No No Yes Profiling timer expired
SIGWINCH No No Yes Window size changed
SIGLOST Yes Yes Yes Resource lost
SIGUSR1 Yes Yes Yes User defined signal 1
SIGUSR2 Yes Yes Yes User defined signal 2
SIGPWR Yes Yes Yes Power fail/restart
SIGPOLL No No Yes Pollable event occurred
SIGWIND Yes Yes Yes SIGWIND
SIGPHONE Yes Yes Yes SIGPHONE
SIGWAITING No No Yes Process's LWPs are blocked
SIGLWP No No Yes Signal LWP
SIGDANGER Yes Yes Yes Swap space dangerously low
SIGGRANT Yes Yes Yes Monitor mode granted
SIGRETRACT Yes Yes Yes Need to relinquish monitor mode
SIGMSG Yes Yes Yes Monitor mode data available
SIGSOUND Yes Yes Yes Sound completed
SIGSAK Yes Yes Yes Secure attention
SIGPRIO No No Yes SIGPRIO
SIG33 Yes Yes Yes Real-time event 33
SIG34 Yes Yes Yes Real-time event 34
SIG35 Yes Yes Yes Real-time event 35
SIG36 Yes Yes Yes Real-time event 36
SIG37 Yes Yes Yes Real-time event 37
SIG38 Yes Yes Yes Real-time event 38
SIG39 Yes Yes Yes Real-time event 39
SIG40 Yes Yes Yes Real-time event 40
SIG41 Yes Yes Yes Real-time event 41
SIG42 Yes Yes Yes Real-time event 42
SIG43 Yes Yes Yes Real-time event 43
SIG44 Yes Yes Yes Real-time event 44
SIG45 Yes Yes Yes Real-time event 45
SIG46 Yes Yes Yes Real-time event 46
SIG47 Yes Yes Yes Real-time event 47
SIG48 Yes Yes Yes Real-time event 48
SIG49 Yes Yes Yes Real-time event 49
SIG50 Yes Yes Yes Real-time event 50
SIG51 Yes Yes Yes Real-time event 51
SIG52 Yes Yes Yes Real-time event 52
SIG53 Yes Yes Yes Real-time event 53
SIG54 Yes Yes Yes Real-time event 54
SIG55 Yes Yes Yes Real-time event 55
SIG56 Yes Yes Yes Real-time event 56
SIG57 Yes Yes Yes Real-time event 57
SIG58 Yes Yes Yes Real-time event 58
SIG59 Yes Yes Yes Real-time event 59
SIG60 Yes Yes Yes Real-time event 60
SIG61 Yes Yes Yes Real-time event 61
SIG62 Yes Yes Yes Real-time event 62
SIG63 Yes Yes Yes Real-time event 63
SIGCANCEL No No Yes LWP internal signal
SIG32 Yes Yes Yes Real-time event 32
SIG64 Yes Yes Yes Real-time event 64
SIG65 Yes Yes Yes Real-time event 65
SIG66 Yes Yes Yes Real-time event 66
SIG67 Yes Yes Yes Real-time event 67
SIG68 Yes Yes Yes Real-time event 68
SIG69 Yes Yes Yes Real-time event 69
SIG70 Yes Yes Yes Real-time event 70
SIG71 Yes Yes Yes Real-time event 71
SIG72 Yes Yes Yes Real-time event 72
SIG73 Yes Yes Yes Real-time event 73
SIG74 Yes Yes Yes Real-time event 74
SIG75 Yes Yes Yes Real-time event 75
SIG76 Yes Yes Yes Real-time event 76
SIG77 Yes Yes Yes Real-time event 77
SIG78 Yes Yes Yes Real-time event 78
SIG79 Yes Yes Yes Real-time event 79
SIG80 Yes Yes Yes Real-time event 80
SIG81 Yes Yes Yes Real-time event 81
SIG82 Yes Yes Yes Real-time event 82
SIG83 Yes Yes Yes Real-time event 83
SIG84 Yes Yes Yes Real-time event 84
SIG85 Yes Yes Yes Real-time event 85
SIG86 Yes Yes Yes Real-time event 86
SIG87 Yes Yes Yes Real-time event 87
SIG88 Yes Yes Yes Real-time event 88
SIG89 Yes Yes Yes Real-time event 89
SIG90 Yes Yes Yes Real-time event 90
SIG91 Yes Yes Yes Real-time event 91
SIG92 Yes Yes Yes Real-time event 92
SIG93 Yes Yes Yes Real-time event 93
SIG94 Yes Yes Yes Real-time event 94
SIG95 Yes Yes Yes Real-time event 95
SIG96 Yes Yes Yes Real-time event 96
SIG97 Yes Yes Yes Real-time event 97
SIG98 Yes Yes Yes Real-time event 98
SIG99 Yes Yes Yes Real-time event 99
SIG100 Yes Yes Yes Real-time event 100
SIG101 Yes Yes Yes Real-time event 101
SIG102 Yes Yes Yes Real-time event 102
SIG103 Yes Yes Yes Real-time event 103
SIG104 Yes Yes Yes Real-time event 104
SIG105 Yes Yes Yes Real-time event 105
SIG106 Yes Yes Yes Real-time event 106
SIG107 Yes Yes Yes Real-time event 107
SIG108 Yes Yes Yes Real-time event 108
SIG109 Yes Yes Yes Real-time event 109
SIG110 Yes Yes Yes Real-time event 110
SIG111 Yes Yes Yes Real-time event 111
SIG112 Yes Yes Yes Real-time event 112
SIG113 Yes Yes Yes Real-time event 113
SIG114 Yes Yes Yes Real-time event 114
SIG115 Yes Yes Yes Real-time event 115
SIG116 Yes Yes Yes Real-time event 116
SIG117 Yes Yes Yes Real-time event 117
SIG118 Yes Yes Yes Real-time event 118
SIG119 Yes Yes Yes Real-time event 119
SIG120 Yes Yes Yes Real-time event 120
SIG121 Yes Yes Yes Real-time event 121
SIG122 Yes Yes Yes Real-time event 122
SIG123 Yes Yes Yes Real-time event 123
SIG124 Yes Yes Yes Real-time event 124
SIG125 Yes Yes Yes Real-time event 125
SIG126 Yes Yes Yes Real-time event 126
SIG127 Yes Yes Yes Real-time event 127
SIGINFO Yes Yes Yes Information request
EXC_BAD_ACCESS Yes Yes Yes Could not access memory
EXC_BAD_INSTRUCTION Yes Yes Yes Illegal instruction/operand
EXC_ARITHMETIC Yes Yes Yes Arithmetic exception
EXC_EMULATION Yes Yes Yes Emulation instruction
EXC_SOFTWARE Yes Yes Yes Software generated exception
EXC_BREAKPOINT Yes Yes Yes Breakpoint
SIGLIBRT No No Yes librt internal signal
Use the "handle" command to change these tables.
pwndbg>
第一项(Signal
):标示每个信号。
第二项(Stop
):表示被调试的程序有对应的信号发生时,gdb是否会暂停程序。
第三项(Print
):表示被调试的程序有对应的信号发生时,gdb是否会打印相关信息。
第四项(Pass to program
):gdb是否会把这个信号发给被调试的程序。
第五项(Description
):信号的描述信息。
从上面的输出可以看到,当SIGINT
信号发生时,gdb会暂停被调试的程序,并打印相关信息,但不会把这个信号发给被调试的程序。而当SIGALRM
信号发生时,gdb不会暂停被调试的程序,也不打印相关信息,但会把这个信号发给被调试的程序。
启动gdb调试上面的程序,同时另起一个终端,先后发送SIGINT
和SIGALRM
信号给被调试的进程,输出如下:
终端1:
ubuntu@niu0217:~/Dev/testGDB$ ./test25
Receive signal: 2
Receive signal: 14
终端2:
ubuntu@niu0217:~/Dev/testGDB$ ps -aux | grep test25
ubuntu 1932500 0.0 0.0 2356 572 pts/0 S+ 20:02 0:00 ./test25
ubuntu 1932530 0.0 0.0 11276 656 pts/1 S+ 20:02 0:00 grep test25
ubuntu@niu0217:~/Dev/testGDB$ /bin/kill -SIGINT 1932500
ubuntu@niu0217:~/Dev/testGDB$ /bin/kill -SIGALRM 1932500
ubuntu@niu0217:~/Dev/testGDB$
11. 共享库
11.1 显示共享链接库信息
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void handler(int sig);
void handler(int sig)
{
signal(sig, handler);
printf("Receive signal: %d\n", sig);
}
int main(void) {
signal(SIGHUP, handler);
while (1)
{
sleep(1);
}
return 0;
}
使用"info sharedlibrary regex
"命令可以显示程序加载的共享链接库信息,其中regex
可以是正则表达式,意为显示名字符合regex
的共享链接库。如果没有regex
,则列出所有的库:
pwndbg> info sharedlibrary
From To Syms Read Shared Object Library
0x00007ffff7fd0100 0x00007ffff7ff2684 Yes /lib64/ld-linux-x86-64.so.2
0x00007ffff7de9630 0x00007ffff7f5e27d Yes /lib/x86_64-linux-gnu/libc.so.6
12. 脚本
12.1 配置.gdbinit文件
当gdb启动时,会读取HOME目录和当前目录下的的配置文件,执行里面的命令。这个文件通常为“.gdbinit
”。
# 保存历史命令
set history filename ~/.gdb_history
set history save on
# 退出时不显示提示信息
set confirm off
# 按照派生类型打印对象
set print object on
# 打印数组的索引下标
set print array-indexes on
# 每行打印一个结构体成员
set print pretty on
12.2 按何种方式解析脚本文件
gdb支持的脚本文件分为两种:
- 一种是只包含gdb自身命令的脚本,例如
.gdbinit
文件,当gdb在启动时,就会执行.gdbinit
文件中的命令 - gdb还支持其它一些语言写的脚本文件(比如python)。gdb用
set script-extension
命令来决定按何种格式来解析脚本文件。它可以取3个值:off
:所有的脚本文件都解析成gdb的命令脚本;soft
:根据脚本文件扩展名决定如何解析脚本。如果gdb支持解析这种脚本语言(比如python),就按这种语言解析,否则就按命令脚本解析;strict
:根据脚本文件扩展名决定如何解析脚本。如果gdb支持解析这种脚本语言(比如python),就按这种语言解析,否则不解析
13. 其他
13.1 使用命令的缩写形式
在gdb中,你不用必须输入完整的命令,只需命令的(前)几个字母即可。规则是,只要这个缩写不会和其它命令有歧义(注,是否有歧义,这个规则从文档上看不出,看起来需要查看gdb的源代码,或者在实际使用中进行总结)。也可以使用tab键进行命令补全。
其中许多常用命令只使用第一个字母就可以,比如:
b -> break
c -> continue
d -> delete
f -> frame
i -> info
j -> jump
l -> list
n -> next
p -> print
r -> run
s -> step
u -> until
也有使用两个或几个字母的,比如:
aw -> awatch
bt -> backtrace
dir -> directory
disas -> disassemble
fin -> finish
ig -> ignore
ni -> nexti
rw -> rwatch
si -> stepi
tb -> tbreak
wa -> watch
win -> winheight
另外,如果直接按回车键,会重复执行上一次的命令。
13.2 在gdb中执行shell命令和make
(gdb) shell ls
(gdb) make CFLAGS="-g -O0"
13.3 设置被调试程序的参数
(gdb) set args a b c
(gdb) show args
Argument list to give program being debugged when it is started is "a b c".
(gdb) r a b
Starting program: /home/xmj/tmp/a.out a b
(gdb) show args
Argument list to give program being debugged when it is started is "a b".
(gdb) r
Starting program: /home/xmj/tmp/a.out a b
13.4 记录执行gdb的过程
用gdb调试程序时,可以使用“set logging on
”命令把执行gdb的过程记录下来,方便以后自己参考或是别人帮忙分析。默认的日志文件是“gdb.txt
”,也可以用“set logging file file
”改成别的名字
(gdb) set logging file log.txt
(gdb) set logging on
13.5 设置被调试程序的环境变量
在GDB中,你可以使用set environment
命令来设置环境变量。以下是一个例子:
假设你有一个程序,它依赖于一个环境变量MY_VAR
。你可以在GDB中设置这个环境变量,如下所示:
gdb your_program
然后在GDB命令行中:
(gdb) set environment MY_VAR=value
这里,value
是你想要设置的环境变量MY_VAR
的值。
例如,如果你想设置MY_VAR
为hello
,你可以这样做:
(gdb) set environment MY_VAR=hello
之后,当你运行你的程序时,它将看到这个环境变量已经设置好了。
如果你想删除一个环境变量,可以使用unset environment
命令:
(gdb) unset environment MY_VAR
注意,这些环境变量的设置只在GDB会话期间有效,当GDB退出时,这些环境变量的更改不会影响到系统的环境变量。如果你想要永久地设置环境变量,你应该在你的shell配置文件(如.bashrc
或.bash_profile
)中设置它们。