Debuggers 1012:Introductory GDB

编程语言心法参考:http://www.yinwang.org/blog-cn/2017/07/06/master-pl
英语阅读速成:http://www.yinwang.org/blog-cn/2018/11/23/grammar
记住:晦涩难懂的示例代码直接丢GPT
希望你也搞一个证书,纪念纪念自己的旅途。

image

OpenSecurityTraining2 Learning Paths: Vulnerability Hunting & Exploitation
python:https://www.learnpython.org/
路径图:https://ost2.fyi/OST2_LP_Vulns_Exploits.pdf

Debuggers 1012:Introductory GDB(与 python ) --> Architecture 1001:x86-64 Assembly --> Reverse Engineering 3201:Symbolic Analysis

Download & Install

设置 Ubuntu 系统

VMWare Workstation Player 16: x86-64 Ubuntu 20.04 VM
https://www.youtube.com/watch?v=wGL-IFr-8Is
https://ubuntu.com/download/desktop

VirtualBox 6.1: x86-64 Ubuntu 20.04 VM
https://apps.p.ost2.fyi/learning/course/course-v1:OpenSecurityTraining2+Lab_Setup_x86-64_Ubuntu+2021_v1/home

安装 gcc 和 gdb

sudo apt-get install -y gcc gdb
gcc –v
gdb –version

Create Test Executable 创建测试可执行文件

Compiling Test Programs fibber.c and echo.c 编译测试程序 fibber.c 和 echo.c

将以下代码复制并粘贴到名为 fibber.c 文件中

// fibber.c: A simple recursive Fibbonacci sequence calculation program
#include <stdio.h>

unsigned int fibbonacci(unsigned int n){
    if(n <= 1){
        return n;
    }
    else{
        return (fibbonacci(n-1) + fibbonacci(n-2));
    }
}

int main(){
    unsigned int n = 10;

    printf("First %d elements of the Fibbonacci sequence: ", n);

    for(unsigned int i = 0; i < n; i++){
        printf("%d ", fibbonacci(i));
    }
    printf("\n");
    return 0;
}

编译它

gcc -ggdb fibber.c -o fibber_bin # -ggdb 将GDB debugging symbols添加到二进制文件中

通过运行“./fibber_bin”(不带引号)确认其已执行。

复制并粘贴以下代码到名为 echo.c 的文件中

// echo.c: A simple program to take input on the command line and echo it back out
#include <stdio.h>
void main(int argc, char ** argv){
    if(argv[1] != NULL && argv[1] != ""){
        printf("You entered %s for argv[1]\n", argv[1]);
    } else {
        printf("You didn't enter an argv[1]\n");
    }
}

Compile it with:

gcc -ggdb echo.c -o echo_bin

通过运行“./echo_bin yo”(不带引号)确认其执行。

Loading Binaries 加载二进制文件

Loading a Binary from Disk 从磁盘加载二进制文件

从文件系统加载二进制文件:选项 1

user@ubuntu:~$ gdb --quiet ./fibber_bin 
Reading symbols from ./fibber_bin...
(No debugging symbols found in ./fibber_bin)
(gdb) 

--quiet is equivalent to -q

从文件系统加载二进制文件:选项 2

user@ubuntu:~$ gdb -q
(gdb) file ./fibber_bin 
Reading symbols from ./fibber_bin...
(No debugging symbols found in ./fibber_bin)
(gdb)

退出 GDB

user@ubuntu:~$ gdb -q
(gdb) quit
user@ubuntu:~$

Starting, Stopping, Restarting Binaries 启动、停止、重新启动二进制文件

Commands: run, start, continue 命令:运行、启动、继续

运行(或重新运行)程序
run(简称:r)命令将运行程序
https://www.sourceware.org/gdb/current/onlinedocs/gdb
https://web.archive.org/web/20221209001604/http://www.sourceware.org/gdb/current/onlinedocs/gdb/Starting.html#Starting

运行需要 CLI 参数的程序
如果您的程序需要 CLI 参数,则可以在运行命令后传递它们,就像您直接调用程序一样。
比如:./echo_bin yo

user@ubuntu:~$ gdb ./echo_bin -q
Reading symbols from ./echo_bin...
(gdb) r
Starting program: /home/user/echo_bin 
You didn't enter an argv[1]
[Inferior 1 (process 60868) exited with code 034]
(gdb) r hi
Starting program: /home/user/echo_bin hi
You entered hi for argv[1]
[Inferior 1 (process 60872) exited with code 033]
(gdb) r yo
Starting program: /home/user/echo_bin yo
You entered yo for argv[1]
[Inferior 1 (process 60873) exited with code 033]

启动程序并在其入口点中断
start 命令类似于 run,只不过它在程序的入口点设置断点。(后面的二进制课程将教你如何自己找到入口点。)

user@ubuntu:~$ gdb ./fibber_bin -q
Reading symbols from ./fibber_bin...
(gdb) start 
Temporary breakpoint 1 at 0x1189
Starting program: /home/user/fibber_bin 

Temporary breakpoint 1, 0x0000555555555189 in main ()
(gdb)

与运行类似,您可以在启动命令后指定其他 CLI 参数:

user@ubuntu:~$ gdb ./echo_bin -q
Reading symbols from ./echo_bin...
(No debugging symbols found in ./echo_bin)
(gdb) start hi
Temporary breakpoint 1 at 0x1169
Starting program: /home/user/echo_bin hi

Temporary breakpoint 1, 0x0000555555555169 in main ()
(gdb)

继续执行在断点处停止的程序
如果你使用 start 启动了程序,那么可以使用 continue(缩写:c)从程序设置的临时断点继续执行。

user@ubuntu:~$ gdb ./echo_bin -q
Reading symbols from ./echo_bin...
(gdb) start hi
Temporary breakpoint 1 at 0x1169
Starting program: /home/user/echo_bin hi

Temporary breakpoint 1, 0x0000555555555169 in main ()
(gdb) c
Continuing.
You entered hi for argv[1]
[Inferior 1 (process 60985) exited with code 033]
(gdb)

https://web.archive.org/web/20221211033727/https://sourceware.org/gdb/current/onlinedocs/gdb/Continuing-and-Stepping.html#Continuing-and-Stepping

Working with Breakpoints in Source & Assembly Debugging 在源代码和汇编调试中使用断点

Code Breakpoints: Setting, Listing, and Deleting 代码断点:设置、列出和删除

设置代码断点:
可以使用 break 命令(缩写:b)设置断点。

(gdb) break main
Breakpoint 1 at 0x11a9
(gdb) b fibbonacci
Breakpoint 2 at 0x1169

列出代码断点:
可以使用 info breakpoints 或更短的形式 info break 和 info b 列出断点

(gdb) info breakpoints
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000000011a9 <main>
2       breakpoint     keep y   0x0000000000001169 <fibbonacci>
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000000011a9 <main>
2       breakpoint     keep y   0x0000000000001169 <fibbonacci>

取消设置代码断点:
clear <address> 命令可以删除地址处的断点,该地址由符号名称或 * 后跟绝对内存地址指定。

(gdb) clear *0x00000000000011a9
(gdb) info b
Deleted breakpoint 1 Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x0000000000001169 <fibbonacci>
(gdb) clear fibbonacci
(gdb) info b
Deleted breakpoint 2 No breakpoints or watchpoints.

delete <breakpoint number from info breakpoints>(缩写:d)将删除“info b”输出中指定的编号所给出的特定断点。

(gdb) b main
Breakpoint 3 at 0x11a9
(gdb) info b
Num     Type           Disp Enb Address            What
3       breakpoint     keep y   0x00000000000011a9 <main>
(gdb) delete 3
(gdb) info b
No breakpoints or watchpoints.

https://web.archive.org/web/20221205090253/http://www.sourceware.org/gdb/current/onlinedocs/gdb/Delete-Breaks.html#Delete-Breaks

Breakpoints as offets vs. addresses in memory 断点作为偏移量 VS 内存中的地址
请注意,当断点最初打印出来时,它们是较小的数字。但是当程序启动并再次打印出来时,它们是较大的数字。这是因为在程序运行之前,“地址”实际上只是可执行文件代码执行开始处的偏移量。调试器还不知道程序将在内存中的哪个位置加载,直到它实际执行。这也是因为操作系统可能会随机化可执行文件在内存中的加载位置(一种称为地址空间布局随机化 (ASLR) 的机制,旨在帮助缓解一些安全漏洞。)因此,在可执行文件启动后,调试器现在可以显示可执行文件在内存中加载并启动后的真实地址。(注意:如果您执行相同的步骤,您的地址通常会与下面显示的不同。)

sec875@ubuntu:~$ gdb ./fibber_bin -q
Reading symbols from ./fibber_bin...
(gdb) b main
Breakpoint 1 at 0x11a9: file fibber.c, line 13.
(gdb) break fibbonacci
Breakpoint 2 at 0x1169: file fibber.c, line 4.
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000000011a9 in main at fibber.c:13
2       breakpoint     keep y   0x0000000000001169 in fibbonacci at fibber.c:4
(gdb) r
Starting program: /home/sec875/fibber_bin 

Breakpoint 1, main () at fibber.c:13
13	int main(){
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00005555555551a9 in main at fibber.c:13
	breakpoint already hit 1 time
2       breakpoint     keep y   0x0000555555555169 in fibbonacci at fibber.c:4
(gdb) delete 2
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00005555555551a9 in main at fibber.c:13
	breakpoint already hit 1 time
(gdb) clear *0x00005555555551a9

(gdb) info b
Deleted breakpoint 1 No breakpoints or watchpoints.
(gdb) b main
Breakpoint 3 at 0x5555555551a9: file fibber.c, line 13.
(gdb) delete 3
(gdb) info b
No breakpoints or watchpoints.
(gdb) quit
A debugging session is active.

	Inferior 1 [process 6761] will be killed.

Quit anyway? (y or n) y
sec875@ubuntu:~$ 

检查符号表:https://sourceware.org/gdb/current/onlinedocs/gdb.html/Symbols.html#Symbols

查询程序中定义的符号(变量、函数和类型的名称)。此信息是程序文本中固有的,不会随着程序的执行而改变。GDB 会在程序的符号表、启动 GDB 时指定的文件中(请参阅选择文件)或文件管理命令之一(请参阅指定文件的命令)中找到它。

sec875@ubuntu:~$ gdb ./fibber_bin1 -q
Reading symbols from ./fibber_bin1...
(No debugging symbols found in ./fibber_bin1)
(gdb) p 'main'
$1 = {<text variable, no debug info>} 0x11a9 <main>
(gdb) p 'fibbonacci'
$2 = {<text variable, no debug info>} 0x1169 <fibbonacci>
(gdb) info address main
Symbol "main" is at 0x11a9 in a file compiled without debugging.
(gdb) info address fibbonacci
Symbol "fibbonacci" is at 0x1169 in a file compiled without debugging.
(gdb) b main
Breakpoint 1 at 0x11a9
(gdb) b fibbonacci
Breakpoint 2 at 0x1169
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000000011a9 <main>
2       breakpoint     keep y   0x0000000000001169 <fibbonacci>
(gdb) info symbol 0x11a9
main in section .text
(gdb) info symbol 0x1169
fibbonacci in section .text
(gdb) 

无符号(fibber_bin1)与有符号(fibber_bin)

gcc -ggdb fibber.c -o fibber_bin # -ggdb 将GDB debugging symbols添加到二进制文件中
sec875@ubuntu:~$ gdb ./fibber_bin1 -q
Reading symbols from ./fibber_bin1...
(No debugging symbols found in ./fibber_bin1)
(gdb) p './fibber.c'::main
No symbol table is loaded.  Use the "file" command.
(gdb) p 'fibber.c'::main
No symbol table is loaded.  Use the "file" command.
(gdb) file fibber.bin1
fibber.bin1: No such file or directory.
(gdb) file fibber.c
"/home/sec875/fibber.c": not in executable format: file format not recognized
(gdb) file fibber_bin1 
Reading symbols from fibber_bin1...
(No debugging symbols found in fibber_bin1)
(gdb) q
sec875@ubuntu:~$ gdb ./fibber_bin -q
Reading symbols from ./fibber_bin...
(gdb) p 'fibber.c'::main
$1 = {int ()} 0x11a9 <main>
(gdb) p 'fibber.c'::return
No symbol "return" in specified context.
(gdb) p 'fibber.c'::fibbonacci
$2 = {unsigned int (unsigned int)} 0x1169 <fibbonacci>
(gdb) b main
Breakpoint 1 at 0x11a9: file fibber.c, line 13.
(gdb) c
The program is not being run.
(gdb) r
Starting program: /home/sec875/fibber_bin 

Breakpoint 1, main () at fibber.c:13
13	int main(){
(gdb) p 'fibber.c'::main
$3 = {int ()} 0x5555555551a9 <main>
(gdb) 

All Breakpoints: Disabling and Enabling 所有断点:禁用和启用

禁用断点:
从“info b”获取断点编号后,可以使用以下命令禁用断点
disable <breakpoint number>

随后运行“info b”将在输出的“Enb”(启用)列中将断点显示为“n”。例如:

(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00005555555551a9 <main>
    breakpoint already hit 1 time
(gdb) disable 1
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep n   0x00005555555551a9 <main>
    breakpoint already hit 1 time

https://web.archive.org/web/20221203080449/http://www.sourceware.org/gdb/current/onlinedocs/gdb/Disabling.html

启用断点:
从“info b”获取断点编号后,可以使用以下命令启用断点
enable <breakpoint number>
随后运行“info b”将在输出的“Enb”(启用)列中将断点显示为“y”。例如:

(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep n   0x00005555555551a9 <main>
    breakpoint already hit 1 time
(gdb) enable 1
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00005555555551a9 <main>
    breakpoint already hit 1 time

演练

sec875@ubuntu:~$ gdb ./fibber_bin -q
Reading symbols from ./fibber_bin...
(gdb) b main
Breakpoint 1 at 0x11a9: file fibber.c, line 13.
(gdb) b fibbonacci
Breakpoint 2 at 0x1169: file fibber.c, line 4.
(gdb) r
Starting program: /home/sec875/fibber_bin 

Breakpoint 1, main () at fibber.c:13
13	int main(){
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00005555555551a9 in main at fibber.c:13
	breakpoint already hit 1 time
2       breakpoint     keep y   0x0000555555555169 in fibbonacci at fibber.c:4
(gdb) c
Continuing.

Breakpoint 2, fibbonacci (n=21845) at fibber.c:4
4	unsigned int fibbonacci(unsigned int n){
(gdb) c
Continuing.

Breakpoint 2, fibbonacci (n=0) at fibber.c:4
4	unsigned int fibbonacci(unsigned int n){
(gdb) c
Continuing.

Breakpoint 2, fibbonacci (n=1) at fibber.c:4
4	unsigned int fibbonacci(unsigned int n){
(gdb) disable 2
(gdb) c
Continuing.
First 10 elements of the Fibbonacci sequence: 0 1 1 2 3 5 8 13 21 34 
[Inferior 1 (process 1923) exited normally]
(gdb) r
Starting program: /home/sec875/fibber_bin 

Breakpoint 1, main () at fibber.c:13
13	int main(){
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00005555555551a9 in main at fibber.c:13
	breakpoint already hit 1 time
2       breakpoint     keep n   0x0000555555555169 in fibbonacci at fibber.c:4
(gdb) enable 2
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00005555555551a9 in main at fibber.c:13
	breakpoint already hit 1 time
2       breakpoint     keep y   0x0000555555555169 in fibbonacci at fibber.c:4
(gdb) c
Continuing.

Breakpoint 2, fibbonacci (n=21845) at fibber.c:4
4	unsigned int fibbonacci(unsigned int n){
(gdb) c
Continuing.

Breakpoint 2, fibbonacci (n=0) at fibber.c:4
4	unsigned int fibbonacci(unsigned int n){
(gdb) q
A debugging session is active.

	Inferior 1 [process 2302] will be killed.

Quit anyway? (y or n) y
sec875@ubuntu:~$ 

Examining Source Code 检查源代码

列出源代码行
此选项仅与您拥有要调试的程序的源代码并且它是在启用符号的情况下构建的(gcc 的 -g 或 -ggdb 标志)有关。在对不透明二进制文件进行逆向工程时,它不会很有用,但在一些 OST2 课程(例如 Architecture 4021:Introductory UEFI)中很有用,您可以在其中自己编译源代码。

list 命令将显示当前停止位置周围的源代码。
list <function name> 命令将显示给定函数之前和之后的源代码。
list <source file name>:<line number> list <源文件名>:<行号> 命令将显示给定文件中给定行之前和之后的源代码。
https://web.archive.org/web/20220606212422/https://sourceware.org/gdb/current/onlinedocs/gdb/List.html#List

演练:

sec875@ubuntu:~$ gdb ./fibber_bin1 -q
Reading symbols from ./fibber_bin1...
(No debugging symbols found in ./fibber_bin1)
(gdb) list
No symbol table is loaded.  Use the "file" command.
(gdb) quit
sec875@ubuntu:~$ gdb ./fibber_bin -q
Reading symbols from ./fibber_bin...
(gdb) list
1	// fibber.c: A simple recursive Fibbonacci sequence calculation program
2	#include <stdio.h>
3	
4	unsigned int fibbonacci(unsigned int n){
5	    if(n <= 1){
6	        return n;
7	    }
8	    else{
9	        return (fibbonacci(n-1) + fibbonacci(n-2));
10	    }
(gdb) b main
Breakpoint 1 at 0x11a9: file fibber.c, line 13.
(gdb) r
Starting program: /home/sec875/fibber_bin 

Breakpoint 1, main () at fibber.c:13
13	int main(){
(gdb) list
8	    else{
9	        return (fibbonacci(n-1) + fibbonacci(n-2));
10	    }
11	}
12	
13	int main(){
14	    unsigned int n = 10;
15	
16	    printf("First %d elements of the Fibbonacci sequence: ", n);
17	
(gdb) list fibber.c:0
1	// fibber.c: A simple recursive Fibbonacci sequence calculation program
2	#include <stdio.h>
3	
4	unsigned int fibbonacci(unsigned int n){
5	    if(n <= 1){
6	        return n;
7	    }
8	    else{
9	        return (fibbonacci(n-1) + fibbonacci(n-2));
10	    }
(gdb) quit
A debugging session is active.

	Inferior 1 [process 2801] will be killed.

Quit anyway? (y or n) y
sec875@ubuntu:~$ 

忘记屏幕录制应用程序和模糊的视频。 体验轻量级、基于文本的终端录制方法。 https://asciinema.org/

Examining Assembly 检查汇编

One-time Disassembly Display 一次性反汇编展示
disassemble 反汇编命令(简称:disas)本身将显示您所停留的当前位置周围的汇编。
disassemble <address or symbol name> disassemble <地址或符号名称> 命令将反汇编由地址或符号名称指定的内存。
您可以选择在反汇编后给出 /r 参数来显示构成指令的 raw 原始字节。
您可以选择在反汇编后给出 /m 参数来 mix 混合源代码和汇编代码。
要同时给出两个参数,必须将它们组合为“/rm”。
https://web.archive.org/web/20221127202729/https://sourceware.org/gdb/current/onlinedocs/gdb/Machine-Code.html

或者,x(examine检查 内存)命令的一种形式(我们稍后会详细了解)可以在给定地址处显示一定数量的指令(在下面的示例中为 10 条)。该形式为:
x/10i <address>

Continuously-updating Disassembly Display 持续更新反汇编展示
display 命令的一种形式(我们稍后会详细了解)可以确保每次程序停止时,都会从寄存器中给出的地址开始打印出一些指令(在下面的例子中为 10 条),该地址表示 CPU 要执行的下一条汇编指令。该形式为:
display/10i <instruction pointer / program counter>

在 x86 系统上,该寄存器被称为“ instruction pointer 指令指针”,对于 64 位代码来说,具体来说是“RIP”,因此命令将是 display/10i $rip
在 x86 系统上,该寄存器被称为“指令指针”,对于 32 位代码来说具体是“EIP”,因此命令为 display/10i $eip
在 ARM 或 RISC-V 系统上,寄存器被称为“ program counter 程序计数器”,即 display/10i $pc

演练

sec875@ubuntu:~$ gdb ./fibber_bin1 -q
Reading symbols from ./fibber_bin1...
(No debugging symbols found in ./fibber_bin1)
(gdb) b main
Breakpoint 1 at 0x11a9
(gdb) b fibbonacci
Breakpoint 2 at 0x1169
(gdb) r
Starting program: /home/sec875/fibber_bin1 

Breakpoint 1, 0x00005555555551a9 in main ()
(gdb) disas
Dump of assembler code for function main:
=> 0x00005555555551a9 <+0>:	endbr64 
   0x00005555555551ad <+4>:	push   %rbp
   0x00005555555551ae <+5>:	mov    %rsp,%rbp
   0x00005555555551b1 <+8>:	sub    $0x10,%rsp
   0x00005555555551b5 <+12>:	movl   $0xa,-0x4(%rbp)
   0x00005555555551bc <+19>:	mov    -0x4(%rbp),%eax
   0x00005555555551bf <+22>:	mov    %eax,%esi
   0x00005555555551c1 <+24>:	lea    0xe40(%rip),%rdi        # 0x555555556008
   0x00005555555551c8 <+31>:	mov    $0x0,%eax
   0x00005555555551cd <+36>:	callq  0x555555555070 <printf@plt>
   0x00005555555551d2 <+41>:	movl   $0x0,-0x8(%rbp)
   0x00005555555551d9 <+48>:	jmp    0x5555555551fc <main+83>
   0x00005555555551db <+50>:	mov    -0x8(%rbp),%eax
   0x00005555555551de <+53>:	mov    %eax,%edi
   0x00005555555551e0 <+55>:	callq  0x555555555169 <fibbonacci>
   0x00005555555551e5 <+60>:	mov    %eax,%esi
   0x00005555555551e7 <+62>:	lea    0xe49(%rip),%rdi        # 0x555555556037
   0x00005555555551ee <+69>:	mov    $0x0,%eax
   0x00005555555551f3 <+74>:	callq  0x555555555070 <printf@plt>
   0x00005555555551f8 <+79>:	addl   $0x1,-0x8(%rbp)
   0x00005555555551fc <+83>:	mov    -0x8(%rbp),%eax
   0x00005555555551ff <+86>:	cmp    -0x4(%rbp),%eax
   0x0000555555555202 <+89>:	jb     0x5555555551db <main+50>
   0x0000555555555204 <+91>:	mov    $0xa,%edi
   0x0000555555555209 <+96>:	callq  0x555555555060 <putchar@plt>
   0x000055555555520e <+101>:	mov    $0x0,%eax
   0x0000555555555213 <+106>:	leaveq 
   0x0000555555555214 <+107>:	retq   
End of assembler dump.
(gdb) x/10i fibbonacci
   0x555555555169 <fibbonacci>:	endbr64 
   0x55555555516d <fibbonacci+4>:	push   %rbp
   0x55555555516e <fibbonacci+5>:	mov    %rsp,%rbp
   0x555555555171 <fibbonacci+8>:	push   %rbx
   0x555555555172 <fibbonacci+9>:	sub    $0x18,%rsp
   0x555555555176 <fibbonacci+13>:	mov    %edi,-0x14(%rbp)
   0x555555555179 <fibbonacci+16>:	cmpl   $0x1,-0x14(%rbp)
   0x55555555517d <fibbonacci+20>:	ja     0x555555555184 <fibbonacci+27>
   0x55555555517f <fibbonacci+22>:	mov    -0x14(%rbp),%eax
   0x555555555182 <fibbonacci+25>:	jmp    0x5555555551a2 <fibbonacci+57>
(gdb) display/10i $rip
1: x/10i $rip
=> 0x5555555551a9 <main>:	endbr64 
   0x5555555551ad <main+4>:	push   %rbp
   0x5555555551ae <main+5>:	mov    %rsp,%rbp
   0x5555555551b1 <main+8>:	sub    $0x10,%rsp
   0x5555555551b5 <main+12>:	movl   $0xa,-0x4(%rbp)
   0x5555555551bc <main+19>:	mov    -0x4(%rbp),%eax
   0x5555555551bf <main+22>:	mov    %eax,%esi
   0x5555555551c1 <main+24>:	lea    0xe40(%rip),%rdi        # 0x555555556008
   0x5555555551c8 <main+31>:	mov    $0x0,%eax
   0x5555555551cd <main+36>:	callq  0x555555555070 <printf@plt>
(gdb) c
Continuing.

Breakpoint 2, 0x0000555555555169 in fibbonacci ()
1: x/10i $rip
=> 0x555555555169 <fibbonacci>:	endbr64 
   0x55555555516d <fibbonacci+4>:	push   %rbp
   0x55555555516e <fibbonacci+5>:	mov    %rsp,%rbp
   0x555555555171 <fibbonacci+8>:	push   %rbx
   0x555555555172 <fibbonacci+9>:	sub    $0x18,%rsp
   0x555555555176 <fibbonacci+13>:	mov    %edi,-0x14(%rbp)
   0x555555555179 <fibbonacci+16>:	cmpl   $0x1,-0x14(%rbp)
   0x55555555517d <fibbonacci+20>:	ja     0x555555555184 <fibbonacci+27>
   0x55555555517f <fibbonacci+22>:	mov    -0x14(%rbp),%eax
   0x555555555182 <fibbonacci+25>:	jmp    0x5555555551a2 <fibbonacci+57>
(gdb) c
Continuing.

Breakpoint 2, 0x0000555555555169 in fibbonacci ()
1: x/10i $rip
=> 0x555555555169 <fibbonacci>:	endbr64 
   0x55555555516d <fibbonacci+4>:	push   %rbp
   0x55555555516e <fibbonacci+5>:	mov    %rsp,%rbp
   0x555555555171 <fibbonacci+8>:	push   %rbx
   0x555555555172 <fibbonacci+9>:	sub    $0x18,%rsp
   0x555555555176 <fibbonacci+13>:	mov    %edi,-0x14(%rbp)
   0x555555555179 <fibbonacci+16>:	cmpl   $0x1,-0x14(%rbp)
   0x55555555517d <fibbonacci+20>:	ja     0x555555555184 <fibbonacci+27>
   0x55555555517f <fibbonacci+22>:	mov    -0x14(%rbp),%eax
   0x555555555182 <fibbonacci+25>:	jmp    0x5555555551a2 <fibbonacci+57>
(gdb) disas main
Dump of assembler code for function main:
   0x00005555555551a9 <+0>:	endbr64 
   0x00005555555551ad <+4>:	push   %rbp
   0x00005555555551ae <+5>:	mov    %rsp,%rbp
   0x00005555555551b1 <+8>:	sub    $0x10,%rsp
   0x00005555555551b5 <+12>:	movl   $0xa,-0x4(%rbp)
   0x00005555555551bc <+19>:	mov    -0x4(%rbp),%eax
   0x00005555555551bf <+22>:	mov    %eax,%esi
   0x00005555555551c1 <+24>:	lea    0xe40(%rip),%rdi        # 0x555555556008
   0x00005555555551c8 <+31>:	mov    $0x0,%eax
   0x00005555555551cd <+36>:	callq  0x555555555070 <printf@plt>
   0x00005555555551d2 <+41>:	movl   $0x0,-0x8(%rbp)
   0x00005555555551d9 <+48>:	jmp    0x5555555551fc <main+83>
   0x00005555555551db <+50>:	mov    -0x8(%rbp),%eax
   0x00005555555551de <+53>:	mov    %eax,%edi
   0x00005555555551e0 <+55>:	callq  0x555555555169 <fibbonacci>
   0x00005555555551e5 <+60>:	mov    %eax,%esi
   0x00005555555551e7 <+62>:	lea    0xe49(%rip),%rdi        # 0x555555556037
   0x00005555555551ee <+69>:	mov    $0x0,%eax
   0x00005555555551f3 <+74>:	callq  0x555555555070 <printf@plt>
   0x00005555555551f8 <+79>:	addl   $0x1,-0x8(%rbp)
   0x00005555555551fc <+83>:	mov    -0x8(%rbp),%eax
   0x00005555555551ff <+86>:	cmp    -0x4(%rbp),%eax
   0x0000555555555202 <+89>:	jb     0x5555555551db <main+50>
   0x0000555555555204 <+91>:	mov    $0xa,%edi
   0x0000555555555209 <+96>:	callq  0x555555555060 <putchar@plt>
   0x000055555555520e <+101>:	mov    $0x0,%eax
   0x0000555555555213 <+106>:	leaveq 
   0x0000555555555214 <+107>:	retq   
End of assembler dump.
(gdb) b *0x000055555555520e
Breakpoint 3 at 0x55555555520e
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00005555555551a9 <main>
	breakpoint already hit 1 time
2       breakpoint     keep y   0x0000555555555169 <fibbonacci>
	breakpoint already hit 2 times
3       breakpoint     keep y   0x000055555555520e <main+101>
(gdb) d 2
(gdb) c
Continuing.
First 10 elements of the Fibbonacci sequence: 0 1 1 2 3 5 8 13 21 34 

Breakpoint 3, 0x000055555555520e in main ()
1: x/10i $rip
=> 0x55555555520e <main+101>:	mov    $0x0,%eax
   0x555555555213 <main+106>:	leaveq 
   0x555555555214 <main+107>:	retq   
   0x555555555215:	nopw   %cs:0x0(%rax,%rax,1)
   0x55555555521f:	nop
   0x555555555220 <__libc_csu_init>:	endbr64 
   0x555555555224 <__libc_csu_init+4>:	push   %r15
   0x555555555226 <__libc_csu_init+6>:	
    lea    0x2b83(%rip),%r15        # 0x555555557db0
   0x55555555522d <__libc_csu_init+13>:	push   %r14
   0x55555555522f <__libc_csu_init+15>:	mov    %rdx,%r14
(gdb) disas
Dump of assembler code for function main:
   0x00005555555551a9 <+0>:	endbr64 
   0x00005555555551ad <+4>:	push   %rbp
   0x00005555555551ae <+5>:	mov    %rsp,%rbp
   0x00005555555551b1 <+8>:	sub    $0x10,%rsp
   0x00005555555551b5 <+12>:	movl   $0xa,-0x4(%rbp)
   0x00005555555551bc <+19>:	mov    -0x4(%rbp),%eax
   0x00005555555551bf <+22>:	mov    %eax,%esi
   0x00005555555551c1 <+24>:	lea    0xe40(%rip),%rdi        # 0x555555556008
   0x00005555555551c8 <+31>:	mov    $0x0,%eax
   0x00005555555551cd <+36>:	callq  0x555555555070 <printf@plt>
   0x00005555555551d2 <+41>:	movl   $0x0,-0x8(%rbp)
   0x00005555555551d9 <+48>:	jmp    0x5555555551fc <main+83>
   0x00005555555551db <+50>:	mov    -0x8(%rbp),%eax
   0x00005555555551de <+53>:	mov    %eax,%edi
   0x00005555555551e0 <+55>:	callq  0x555555555169 <fibbonacci>
   0x00005555555551e5 <+60>:	mov    %eax,%esi
   0x00005555555551e7 <+62>:	lea    0xe49(%rip),%rdi        # 0x555555556037
   0x00005555555551ee <+69>:	mov    $0x0,%eax
   0x00005555555551f3 <+74>:	callq  0x555555555070 <printf@plt>
   0x00005555555551f8 <+79>:	addl   $0x1,-0x8(%rbp)
   0x00005555555551fc <+83>:	mov    -0x8(%rbp),%eax
   0x00005555555551ff <+86>:	cmp    -0x4(%rbp),%eax
   0x0000555555555202 <+89>:	jb     0x5555555551db <main+50>
   0x0000555555555204 <+91>:	mov    $0xa,%edi
   0x0000555555555209 <+96>:	callq  0x555555555060 <putchar@plt>
=> 0x000055555555520e <+101>:	mov    $0x0,%eax
   0x0000555555555213 <+106>:	leaveq 
   0x0000555555555214 <+107>:	retq   
End of assembler dump.
(gdb) quit
A debugging session is active.

	Inferior 1 [process 2967] will be killed.

Quit anyway? (y or n) y
sec875@ubuntu:~$ 

Examining and Modifying Registers and Memory 检查和修改寄存器和内存

Examine Registers & Memory 检查寄存器和内存

Commands: x (examine), print, display

许多 GDB 命令支持格式说明符,我们将其称为 /FMT(因为在 gdb help 命令中每个命令都这样称呼它)
(gdb) help

格式说明符
/FMT 是 / 字符、后跟数字 n、格式说明符 f 和单位大小说明符 u 的组合。
n、f 和 u 都是可选的,如果未指定,则默认为上次使用的值或默认初始值。
/多少条n;输出格式f和单位大小byte还是word

我们之前看到的命令“display/10i” 的n为10 和 f为‘i’,用于指令,不需要指定u,因为它对于指令来说没有意义。

Print value of expression EXP each time the program stops.
Usage: display[/FMT] EXP
/FMT may be used before EXP as in the "print" command.
/FMT "i" or "s" or including a size-letter is allowed,
as in the "x" command, and then EXP is used to get the address to examine
and examining is done as in the "x" command.

With no argument, display all currently requested auto-display expressions.
Use "undisplay" to cancel display requests previously made.
(gdb) 

格式说明符 f 的最常见值是:
‘x’ 表示十六进制
‘d’ 表示有符号十进制
‘u’ 表示无符号十进制
‘c’ 表示 ASCII 字符
‘s’ 表示完整(假定以空字符结尾)ASCII 字符串。
此处给出了受支持的格式的完整列表。https://web.archive.org/web/20221004134402/http://sourceware.org/gdb/onlinedocs/gdb/Output-Formats.html

u 的单位大小为:
‘b’ 表示字节 bytes
‘h’ 表示半字 half-words(2 个字节)
‘w’ 表示字 words(4 个字节)
‘g’ 表示大字 giant-words(8 个字节)

Intel 注释:GDB 的字(4 个字节)术语与 Intel 的字(2 个字节)术语不一致!这是你必须记住并牢记的事情。

RISC-V 注意事项:GDB 的字(4 字节)术语与 RISC-V 的字术语一致。主要的术语差异在于 64 位(8 字节)值在 GDB 中称为“giant-words 巨字”,在 RISC-V 中称为“double-words 双字”。您只需记住这一点即可。

查看寄存器
“info registers”(简称:info r)命令将默认打印一些 GDB 开发人员认为最常用的寄存器集。

在 Intel 上,这些是general purpose registers 通用寄存器、eflags 寄存器和 segment registers 段寄存器(在 Arch2001 中了解)。

在 RISC-V 上,这些是通用寄存器(x0-x31,由其 ABI 名称显示)和程序计数器 (pc) 寄存器。

您还可以通过在“info r”后列出寄存器来指定您想要查看的特定寄存器集。https://web.archive.org/web/20221128034353/https://sourceware.org/gdb/onlinedocs/gdb/Registers.html

您还可以使用带有 /FMT 说明符的“print”命令(缩写形式:p),仅使用 f 格式说明符,来打印单个寄存器。
https://web.archive.org/web/20220726115258/https://sourceware.org/gdb/current/onlinedocs/gdb/Data.html#index-printing-data

print 命令要求寄存器名称以 $ 为前缀。而“info r”命令则不需要这样的前缀。

在 Intel 上,这可能会与 x86-64 AT&T 语法要求相混淆,即立即数以 $ 为前缀,而寄存器以 % 为前缀。您只需记住这一点即可。

Intel (x86-64) ‘info r’ example:

(gdb) info r rax rbx rsp
rax            0xface              64206
rbx            0x555555555220      93824992236064
rsp            0x7fffffffe038      0x7fffffffe038

Intel (x86-64) ‘print’ example:

(gdb) p/x $rax
$11 = 0xface
(gdb) p/u $rax
$12 = 64206
(gdb) p/d $rax
$13 = 64206
(gdb) p/d $ax
$14 = -1330
(gdb) p/gd $ax
Size letters are meaningless in "print" command.
(gdb) p/10d $ax
Item count other than 1 is meaningless in "print" command.

RISC-V (RV64I) ‘info r’ example:

(gdb) info r fp sp a4 a5
fp             0x7ffffffffaa8   0x7ffffffffaa8
sp             0x7ffffffff920   0x7ffffffff920
a4             0x7ffffffff940   140737488353600
a5             0x41 65

RISC-V (RV64I) ‘print’ example:

(gdb) p/x $a0
$2 = 0x41
(gdb) p/u $a0
$3 = 65
(gdb) p/d $a0
$4 = 65
(gdb) p/gx $fp
Size letters are meaningless in "print" command.
(gdb) p/10x $fp
Item count other than 1 is meaningless in "print" command.

Viewing (Examining) Memory 查看(检查)内存
“x”命令(用于检查内存)支持/FMT 说明符。
https://web.archive.org/web/20221230195737/https://sourceware.org/gdb/current/onlinedocs/gdb/Memory.html#index-examining-memory (其中包括对/FMT 的讨论)

Intel (x86-64) ‘x’ examine memory example:

(gdb) x/8xb $rsp
0x7fffffffe038: 0xb3    0xd0    0xde    0xf7    0xff    0x7f    0x00    0x00
(gdb) x/4xh $rsp
0x7fffffffe038: 0xd0b3  0xf7de  0x7fff  0x0000
(gdb) x/2xw $rsp
0x7fffffffe038: 0xf7ded0b3  0x00007fff
(gdb) x/1xg $rsp
0x7fffffffe038: 0x00007ffff7ded0b3
(gdb) x/s 0x555555556008
0x555555556008: "First %d elements of the Fibbonacci sequence: "
(gdb) x/3i $rip
=> 0x5555555551a9 <main>:   endbr64 
   0x5555555551ad <main+4>: push   %rbp
   0x5555555551ae <main+5>: mov    %rsp,%rbp

RISC-V (RV64I) ‘x’ examine memory example:

(gdb) x/8xb $sp
0x7ffffffff920: 0x50    0xe0    0xff    0xf7    0xff    0x7f    0x00    0x00
(gdb) x/4xh $sp
0x7ffffffff920: 0xe050  0xf7ff  0x7fff  0x0000
(gdb) x/2xw $sp
0x7ffffffff920: 0xf7ffe050  0x00007fff
(gdb) x/1xg $sp
0x7ffffffff920: 0x00007ffff7ffe050
(gdb) x/s 0x555555555790
0x555555555790: "First %d elements of the Fibbonacci sequence: "
(gdb) x/4i $pc
=> 0x555555555712 <main>:   addi    sp,sp,-32
   0x555555555714 <main+2>: sd  ra,24(sp)
   0x555555555716 <main+4>: sd  s0,16(sp)
   0x555555555718 <main+6>: addi    s0,sp,32

演练

sec875@ubuntu:~$ gdb ./fibber_bin -q
Reading symbols from ./fibber_bin...
(gdb) b *main
Breakpoint 1 at 0x11a9: file fibber.c, line 13.
(gdb) r
Starting program: /home/sec875/fibber_bin 

Breakpoint 1, main () at fibber.c:13
13	int main(){
(gdb) info registers 
rax            0x5555555551a9      93824992235945
rbx            0x555555555220      93824992236064
rcx            0x555555555220      93824992236064
rdx            0x7fffffffe128      140737488347432
rsi            0x7fffffffe118      140737488347416
rdi            0x1                 1
rbp            0x0                 0x0
rsp            0x7fffffffe028      0x7fffffffe028
r8             0x0                 0
r9             0x7ffff7fe0d60      140737354009952
r10            0x0                 0
r11            0x7ffff7f738f0      140737353562352
r12            0x555555555080      93824992235648
r13            0x7fffffffe110      140737488347408
r14            0x0                 0
r15            0x0                 0
rip            0x5555555551a9      0x5555555551a9 <main>
eflags         0x246               [ PF ZF IF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0
(gdb) clear 

(gdb) info r
Deleted breakpoint 1 rax            0x5555555551a9      93824992235945
rbx            0x555555555220      93824992236064
rcx            0x555555555220      93824992236064
rdx            0x7fffffffe128      140737488347432
rsi            0x7fffffffe118      140737488347416
rdi            0x1                 1
rbp            0x0                 0x0
rsp            0x7fffffffe028      0x7fffffffe028
r8             0x0                 0
r9             0x7ffff7fe0d60      140737354009952
r10            0x0                 0
r11            0x7ffff7f738f0      140737353562352
r12            0x555555555080      93824992235648
r13            0x7fffffffe110      140737488347408
r14            0x0                 0
r15            0x0                 0
rip            0x5555555551a9      0x5555555551a9 <main>
eflags         0x246               [ PF ZF IF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0
(gdb) info r rip eflags r8
rip            0x5555555551a9      0x5555555551a9 <main>
eflags         0x246               [ PF ZF IF ]
r8             0x0                 0
(gdb) p/xg $rbx $rdi
Size letters are meaningless in "print" command.
(gdb) p/x $rbx $rdi
A syntax error in expression, near `$rdi'.
(gdb) p/x $rbx 
$1 = 0x555555555220
(gdb) p/x $r8
$2 = 0x0
(gdb) x/16xb 0x5555555551a9
0x5555555551a9 <main>:	0xf3	0x0f	0x1e	0xfa	0x55	0x48	0x89	0xe5
0x5555555551b1 <main+8>:	0x48	0x83	0xec	0x10	0xc7	0x45	0xfc	0x0a
(gdb) x/8xh 0x5555555551a9
0x5555555551a9 <main>:	0x0ff3	0xfa1e	0x4855	0xe589	0x8348	0x10ec	0x45c7	0x0afc
(gdb) x/4xw 0x5555555551a9
0x5555555551a9 <main>:	0xfa1e0ff3	0xe5894855	0x10ec8348	0x0afc45c7
(gdb) x/2xg 0x5555555551a9
0x5555555551a9 <main>:	0xe5894855fa1e0ff3	0x0afc45c710ec8348
(gdb) quit
A debugging session is active.

	Inferior 1 [process 3251] will be killed.

Quit anyway? (y or n) y
sec875@ubuntu:~$ 

Modify Registers & Memory 修改寄存器和内存

Commands: set

修改寄存器
“set”命令与等号结合使用时可用于设置寄存器。

Intel(x86-64)‘设置’寄存器值示例:

(gdb) set $rax = 0xdeadbeeff00dface
(gdb) p/x $rax
$15 = 0xdeadbeeff00dface
(gdb) set $ax = 0xcafef00d
(gdb) p/x $rax
$16 = 0xdeadbeeff00df00d

请注意,写入的大小是寄存器的大小(16 位,ax)而不是立即数的大小(32 位)。

RISC-V (RV64I) ‘set’ register value example:

(gdb) p/x $a0
$4 = 0x41
(gdb) set $a0 = 0xdeadbeeff00dface
(gdb) p/x $a0
$5 = 0xdeadbeeff00dface

修改内存
与寄存器类似,可以使用“set”命令修改内存,也可以选择指定 C 样式类型以指定要写入的长度。
小于指定内存写入大小的立即数将进行零扩展,而不是进行符号扩展。
Intel (x86-64) ‘set’ memory example:

(gdb) x/1xg $rsp
0x7fffffffe038: 0x00007ffff7ded0b3
(gdb) set {char}$rsp = 0xFF
(gdb) x/1xg $rsp
0x7fffffffe038: 0x00007ffff7ded0ff
(gdb) set {short}$rsp = 0xFF
(gdb) x/1xg $rsp
0x7fffffffe038: 0x00007ffff7de00ff
(gdb) set {short}$rsp = 0xFFFF
(gdb) x/1xg $rsp
0x7fffffffe038: 0x00007ffff7deffff
(gdb) set {long long}$rsp = 0x1337bee7
(gdb) x/1xg $rsp
0x7fffffffe038: 0x000000001337bee7

请注意,对于“set {short}$rsp = 0xFF”,它没有将 1 字节值符号扩展为 2 字节短值 0xFFFF。它只是将 0xFF 零扩展为 0x00FF,这就是底部 2 个字节变成 0x00FF 的原因。

RISC-V (RV64I) ‘set’ memory example:

(gdb) x/1xg $sp
0x7ffffffff920: 0x00007ffff7ffe050
(gdb) set {char}$sp = 0xFF
(gdb) x/1xg $sp
0x7ffffffff920: 0x00007ffff7ffe0ff
(gdb) set {short}$sp = 0xFF
(gdb) x/1xg $sp
0x7ffffffff920: 0x00007ffff7ff00ff
(gdb) set {short}$sp = 0xFFFF
(gdb) x/1xg $sp
0x7ffffffff920: 0x00007ffff7ffffff
(gdb) set {long long}$sp = 0x1337bee7
(gdb) x/1xg $sp
0x7ffffffff920: 0x000000001337bee7

请注意,对于“set {short}$sp = 0xFF”,它没有将 1 字节值符号扩展为 2 字节短值 0xFFFF。它只是将 0xFF 零扩展为 0x00FF,这就是底部 2 个字节变成 0x00FF 的原因。

演练:

sec875@ubuntu:~$ gdb ./fibber_bin -q
Reading symbols from ./fibber_bin...
(gdb) b *main
Breakpoint 1 at 0x11a9: file fibber.c, line 13.
(gdb) r
Starting program: /home/sec875/fibber_bin 

Breakpoint 1, main () at fibber.c:13
13	int main(){
(gdb) info r rdi
rdi            0x1                 1
(gdb) set $rdi = 0xdeabdeef
(gdb) p/x $rdi
$1 = 0xdeabdeef
(gdb) x/16xb $rsp
0x7fffffffe028:	0x83	0x80	0xde	0xf7	0xff	0x7f	0x00	0x00
0x7fffffffe030:	0x20	0xc6	0xff	0xf7	0xff	0x7f	0x00	0x00
(gdb) x/2xg $rsp
0x7fffffffe028:	0x00007ffff7de8083	0x00007ffff7ffc620
(gdb) set {char}$rsp=0x11223344
(gdb) x/2xg $rsp
0x7fffffffe028:	0x00007ffff7de8044	0x00007ffff7ffc620
(gdb) set {int}$rsp=0x11223344
(gdb) x/2xg $rsp
0x7fffffffe028:	0x00007fff11223344	0x00007ffff7ffc620
(gdb) quit
A debugging session is active.

	Inferior 1 [process 3382] will be killed.

Quit anyway? (y or n) y
sec875@ubuntu:~$ 

Setting Up an Updating Stack View 设置更新栈视图

更新 Stack View
只需使用前面讨论过的显示命令即可完成此操作,使用 /FMT 格式说明符指示要从堆栈指针寄存器中的地址开始显示多少个十六进制字(32 位)或巨字(64 位)。通常,您应该将大小与指针大小相匹配。因此,32 位架构上显示字,64 位上显示巨字。例如

display/10xg $rsp on x86 64-bit.
display/10xw $esp on x86 32-bit.
display/10xg $sp on ARM or RISC-V 64-bit (RV64I).
display/10xw $sp on ARM or RISC-V 32-bit (RV32I/RC32E).

演练

sec875@ubuntu:~$ gdb ./fibber_bin1 -q
Reading symbols from ./fibber_bin1...
(No debugging symbols found in ./fibber_bin1)
(gdb) b main
Breakpoint 1 at 0x11a9
(gdb) b fibbonacci
Breakpoint 2 at 0x1169
(gdb) r
Starting program: /home/sec875/fibber_bin1 

Breakpoint 1, 0x00005555555551a9 in main ()
(gdb) display/10i $rip
1: x/10i $rip
=> 0x5555555551a9 <main>:	endbr64 
   0x5555555551ad <main+4>:	push   %rbp
   0x5555555551ae <main+5>:	mov    %rsp,%rbp
   0x5555555551b1 <main+8>:	sub    $0x10,%rsp
   0x5555555551b5 <main+12>:	movl   $0xa,-0x4(%rbp)
   0x5555555551bc <main+19>:	mov    -0x4(%rbp),%eax
   0x5555555551bf <main+22>:	mov    %eax,%esi
   0x5555555551c1 <main+24>:	lea    0xe40(%rip),%rdi        # 0x555555556008
   0x5555555551c8 <main+31>:	mov    $0x0,%eax
   0x5555555551cd <main+36>:	callq  0x555555555070 <printf@plt>
(gdb) display/10xg $rsp
2: x/10xg $rsp
0x7fffffffe018:	0x00007ffff7de8083	0x00007ffff7ffc620
0x7fffffffe028:	0x00007fffffffe108	0x0000000100000000
0x7fffffffe038:	0x00005555555551a9	0x0000555555555220
0x7fffffffe048:	0xcee116a85070b21d	0x0000555555555080
0x7fffffffe058:	0x00007fffffffe100	0x0000000000000000
(gdb) c
Continuing.

Breakpoint 2, 0x0000555555555169 in fibbonacci ()
1: x/10i $rip
=> 0x555555555169 <fibbonacci>:	endbr64 
   0x55555555516d <fibbonacci+4>:	push   %rbp
   0x55555555516e <fibbonacci+5>:	mov    %rsp,%rbp
   0x555555555171 <fibbonacci+8>:	push   %rbx
   0x555555555172 <fibbonacci+9>:	sub    $0x18,%rsp
   0x555555555176 <fibbonacci+13>:	mov    %edi,-0x14(%rbp)
   0x555555555179 <fibbonacci+16>:	cmpl   $0x1,-0x14(%rbp)
   0x55555555517d <fibbonacci+20>:	ja     0x555555555184 <fibbonacci+27>
   0x55555555517f <fibbonacci+22>:	mov    -0x14(%rbp),%eax
   0x555555555182 <fibbonacci+25>:	jmp    0x5555555551a2 <fibbonacci+57>
2: x/10xg $rsp
0x7fffffffdff8:	0x00005555555551e5	0x00007fffffffe100
0x7fffffffe008:	0x0000000a00000000	0x0000000000000000
0x7fffffffe018:	0x00007ffff7de8083	0x00007ffff7ffc620
0x7fffffffe028:	0x00007fffffffe108	0x0000000100000000
0x7fffffffe038:	0x00005555555551a9	0x0000555555555220
(gdb) c
Continuing.

Breakpoint 2, 0x0000555555555169 in fibbonacci ()
1: x/10i $rip
=> 0x555555555169 <fibbonacci>:	endbr64 
   0x55555555516d <fibbonacci+4>:	push   %rbp
   0x55555555516e <fibbonacci+5>:	mov    %rsp,%rbp
   0x555555555171 <fibbonacci+8>:	push   %rbx
   0x555555555172 <fibbonacci+9>:	sub    $0x18,%rsp
   0x555555555176 <fibbonacci+13>:	mov    %edi,-0x14(%rbp)
   0x555555555179 <fibbonacci+16>:	cmpl   $0x1,-0x14(%rbp)
   0x55555555517d <fibbonacci+20>:	ja     0x555555555184 <fibbonacci+27>
   0x55555555517f <fibbonacci+22>:	mov    -0x14(%rbp),%eax
   0x555555555182 <fibbonacci+25>:	jmp    0x5555555551a2 <fibbonacci+57>
2: x/10xg $rsp
0x7fffffffdf68:	0x0000555555555191	0x0000000000000000
0x7fffffffdf78:	0x0000000400000000	0x0000000000000000
0x7fffffffdf88:	0x0000555555555220	0x00007fffffffdfc0
0x7fffffffdf98:	0x0000555555555191	0x0000000000000000
0x7fffffffdfa8:	0x0000000500000000	0x0000555555554040
(gdb) quit
A debugging session is active.

	Inferior 1 [process 3459] will be killed.

Quit anyway? (y or n) y
sec875@ubuntu:~$ 

Stack Backtrace 栈回溯

堆栈回溯

backtrace(简称:bt)提供调用堆栈回溯。最近调用的函数位于回溯的顶部,而最近最少调用的函数位于底部。或者换句话说,顶部的函数是由其下方的函数调用的。显示的地址是函数完成后将返回的位置。

例如,当第一次在 fibbonacci() 的入口点中断时,bt 可能会产生类似以下输出的内容:

(gdb) bt
#0  fibbonacci (n=0) at ./fibber.c:4
#1  0x0000555555555742 in main () at ./fibber.c:18

因为 fibbonacci() 是一个递归函数,所以如果继续执行,可能会看到如下输出:

(gdb) bt
#0  fibbonacci (n=3) at ./fibber.c:4
#1  0x00005555555556ea in fibbonacci (n=4) at ./fibber.c:8
#2  0x00005555555556ea in fibbonacci (n=5) at ./fibber.c:8
#3  0x0000555555555742 in main () at ./fibber.c:18

https://web.archive.org/web/20221127202729/https://sourceware.org/gdb/current/onlinedocs/gdb/Backtrace.html#Backtrace

Stepping Through Assembly 逐步执行汇编

Step Into vs. Step Over vs. Step Out: 步入 vs. 跨过 vs. 退出:

Step Over vs. Step Into vs. Step Out
与其他调试器一样,“step over”的概念表示 UI 应该跳过调用指令 - 执行其中的所有指令,但直到到达调用指令之后的指令时,调试器 UI 才显示为已停止。另一方面,“Step into”将进入调用指令。“Step out”将一直步进直到到达函数退出(调试器在执行“return”类型指令时会启发式地确定函数已完成。)

注意:与其他 gdb 指令一样,如果您在空行中输入 return,gdb 将重新执行上一个命令。此行为在步进上下文中特别有用,因为您无需在每次想要步进时重新输入步进指令,而是只需继续按回车键即可。

Step Over 跨过
nexti(简称:ni)跳过下一条指令,继续执行下一条指令,尤其是当它是一条可能返回相同位置的控制流指令时(如“调用”类型指令)。
https://web.archive.org/web/20221211033727/https://sourceware.org/gdb/current/onlinedocs/gdb/Continuing-and-Stepping.html#Continuing-and-Stepping

Step Into 步入
stepi(缩写:si)进入下一条指令,从该指令所指向的位置继续执行,特别是如果它是一条控制流指令(例如“调用”或“跳转”类型的指令)。
https://web.archive.org/web/20221211033727/https://sourceware.org/gdb/current/onlinedocs/gdb/Continuing-and-Stepping.html#Continuing-and-Stepping

Step Out 退出
finish(简称:fin)退出当前函数上下文,完成其余代码的执行,直到函数结束。
https://web.archive.org/web/20221211033727/https://sourceware.org/gdb/current/onlinedocs/gdb/Continuing-and-Stepping.html#Continuing-and-Stepping

演练

sec875@ubuntu:~$ gdb ./fibber_bin1 -q
Reading symbols from ./fibber_bin1...
(No debugging symbols found in ./fibber_bin1)
(gdb) b main
Breakpoint 1 at 0x11a9
(gdb) display/10i $rip
1: x/10i $rip
<error: No registers.>
(gdb) r
Starting program: /home/sec875/fibber_bin1 

Breakpoint 1, 0x00005555555551a9 in main ()
1: x/10i $rip
=> 0x5555555551a9 <main>:	endbr64 
   0x5555555551ad <main+4>:	push   %rbp
   0x5555555551ae <main+5>:	mov    %rsp,%rbp
   0x5555555551b1 <main+8>:	sub    $0x10,%rsp
   0x5555555551b5 <main+12>:	movl   $0xa,-0x4(%rbp)
   0x5555555551bc <main+19>:	mov    -0x4(%rbp),%eax
   0x5555555551bf <main+22>:	mov    %eax,%esi
   0x5555555551c1 <main+24>:	lea    0xe40(%rip),%rdi        # 0x555555556008
   0x5555555551c8 <main+31>:	mov    $0x0,%eax
   0x5555555551cd <main+36>:	callq  0x555555555070 <printf@plt>
(gdb) ni
0x00005555555551ad in main ()
1: x/10i $rip
=> 0x5555555551ad <main+4>:	push   %rbp
   0x5555555551ae <main+5>:	mov    %rsp,%rbp
   0x5555555551b1 <main+8>:	sub    $0x10,%rsp
   0x5555555551b5 <main+12>:	movl   $0xa,-0x4(%rbp)
   0x5555555551bc <main+19>:	mov    -0x4(%rbp),%eax
   0x5555555551bf <main+22>:	mov    %eax,%esi
   0x5555555551c1 <main+24>:	lea    0xe40(%rip),%rdi        # 0x555555556008
   0x5555555551c8 <main+31>:	mov    $0x0,%eax
   0x5555555551cd <main+36>:	callq  0x555555555070 <printf@plt>
   0x5555555551d2 <main+41>:	movl   $0x0,-0x8(%rbp)
...
(gdb) 
0x00005555555551fc in main ()
1: x/10i $rip
=> 0x5555555551fc <main+83>:	mov    -0x8(%rbp),%eax
   0x5555555551ff <main+86>:	cmp    -0x4(%rbp),%eax
   0x555555555202 <main+89>:	jb     0x5555555551db <main+50>
   0x555555555204 <main+91>:	mov    $0xa,%edi
   0x555555555209 <main+96>:	callq  0x555555555060 <putchar@plt>
   0x55555555520e <main+101>:	mov    $0x0,%eax
   0x555555555213 <main+106>:	leaveq 
   0x555555555214 <main+107>:	retq   
   0x555555555215:	nopw   %cs:0x0(%rax,%rax,1)
   0x55555555521f:	nop
(gdb) si
0x00005555555551ff in main ()
1: x/10i $rip
=> 0x5555555551ff <main+86>:	cmp    -0x4(%rbp),%eax
   0x555555555202 <main+89>:	jb     0x5555555551db <main+50>
   0x555555555204 <main+91>:	mov    $0xa,%edi
   0x555555555209 <main+96>:	callq  0x555555555060 <putchar@plt>
   0x55555555520e <main+101>:	mov    $0x0,%eax
   0x555555555213 <main+106>:	leaveq 
   0x555555555214 <main+107>:	retq   
   0x555555555215:	nopw   %cs:0x0(%rax,%rax,1)
   0x55555555521f:	nop
   0x555555555220 <__libc_csu_init>:	endbr64 
(gdb) 
0x0000555555555202 in main ()
1: x/10i $rip
=> 0x555555555202 <main+89>:	jb     0x5555555551db <main+50>
   0x555555555204 <main+91>:	mov    $0xa,%edi
   0x555555555209 <main+96>:	callq  0x555555555060 <putchar@plt>
   0x55555555520e <main+101>:	mov    $0x0,%eax
   0x555555555213 <main+106>:	leaveq 
   0x555555555214 <main+107>:	retq   
   0x555555555215:	nopw   %cs:0x0(%rax,%rax,1)
   0x55555555521f:	nop
   0x555555555220 <__libc_csu_init>:	endbr64 
   0x555555555224 <__libc_csu_init+4>:	push   %r15
(gdb) 
0x00005555555551e0 in main ()
1: x/10i $rip
=> 0x5555555551e0 <main+55>:	callq  0x555555555169 <fibbonacci>
   0x5555555551e5 <main+60>:	mov    %eax,%esi
   0x5555555551e7 <main+62>:	lea    0xe49(%rip),%rdi        # 0x555555556037
   0x5555555551ee <main+69>:	mov    $0x0,%eax
   0x5555555551f3 <main+74>:	callq  0x555555555070 <printf@plt>
   0x5555555551f8 <main+79>:	addl   $0x1,-0x8(%rbp)
   0x5555555551fc <main+83>:	mov    -0x8(%rbp),%eax
   0x5555555551ff <main+86>:	cmp    -0x4(%rbp),%eax
   0x555555555202 <main+89>:	jb     0x5555555551db <main+50>
   0x555555555204 <main+91>:	mov    $0xa,%edi
(gdb) si
0x0000555555555169 in fibbonacci ()
1: x/10i $rip
=> 0x555555555169 <fibbonacci>:	endbr64 
   0x55555555516d <fibbonacci+4>:	push   %rbp
   0x55555555516e <fibbonacci+5>:	mov    %rsp,%rbp
   0x555555555171 <fibbonacci+8>:	push   %rbx
   0x555555555172 <fibbonacci+9>:	sub    $0x18,%rsp
   0x555555555176 <fibbonacci+13>:	mov    %edi,-0x14(%rbp)
   0x555555555179 <fibbonacci+16>:	cmpl   $0x1,-0x14(%rbp)
   0x55555555517d <fibbonacci+20>:	ja     0x555555555184 <fibbonacci+27>
   0x55555555517f <fibbonacci+22>:	mov    -0x14(%rbp),%eax
   0x555555555182 <fibbonacci+25>:	jmp    0x5555555551a2 <fibbonacci+57>

(gdb) 
0x000055555555516e in fibbonacci ()
1: x/10i $rip
=> 0x55555555516e <fibbonacci+5>:	mov    %rsp,%rbp
   0x555555555171 <fibbonacci+8>:	push   %rbx
   0x555555555172 <fibbonacci+9>:	sub    $0x18,%rsp
   0x555555555176 <fibbonacci+13>:	mov    %edi,-0x14(%rbp)
   0x555555555179 <fibbonacci+16>:	cmpl   $0x1,-0x14(%rbp)
   0x55555555517d <fibbonacci+20>:	ja     0x555555555184 <fibbonacci+27>
   0x55555555517f <fibbonacci+22>:	mov    -0x14(%rbp),%eax
   0x555555555182 <fibbonacci+25>:	jmp    0x5555555551a2 <fibbonacci+57>
   0x555555555184 <fibbonacci+27>:	mov    -0x14(%rbp),%eax
   0x555555555187 <fibbonacci+30>:	sub    $0x1,%eax
(gdb) 
0x0000555555555172 in fibbonacci ()
1: x/10i $rip
=> 0x555555555172 <fibbonacci+9>:	sub    $0x18,%rsp
   0x555555555176 <fibbonacci+13>:	mov    %edi,-0x14(%rbp)
   0x555555555179 <fibbonacci+16>:	cmpl   $0x1,-0x14(%rbp)
   0x55555555517d <fibbonacci+20>:	ja     0x555555555184 <fibbonacci+27>
   0x55555555517f <fibbonacci+22>:	mov    -0x14(%rbp),%eax
   0x555555555182 <fibbonacci+25>:	jmp    0x5555555551a2 <fibbonacci+57>
   0x555555555184 <fibbonacci+27>:	mov    -0x14(%rbp),%eax
   0x555555555187 <fibbonacci+30>:	sub    $0x1,%eax
   0x55555555518a <fibbonacci+33>:	mov    %eax,%edi
   0x55555555518c <fibbonacci+35>:	callq  0x555555555169 <fibbonacci>
(gdb) fin
Run till exit from #0  0x0000555555555172 in fibbonacci ()
0x00005555555551e5 in main ()
1: x/10i $rip
=> 0x5555555551e5 <main+60>:	mov    %eax,%esi
   0x5555555551e7 <main+62>:	lea    0xe49(%rip),%rdi        # 0x555555556037
   0x5555555551ee <main+69>:	mov    $0x0,%eax
   0x5555555551f3 <main+74>:	callq  0x555555555070 <printf@plt>
   0x5555555551f8 <main+79>:	addl   $0x1,-0x8(%rbp)
   0x5555555551fc <main+83>:	mov    -0x8(%rbp),%eax
   0x5555555551ff <main+86>:	cmp    -0x4(%rbp),%eax
   0x555555555202 <main+89>:	jb     0x5555555551db <main+50>
   0x555555555204 <main+91>:	mov    $0xa,%edi
   0x555555555209 <main+96>:	callq  0x555555555060 <putchar@plt>
(gdb) ni
0x00005555555551e7 in main ()
1: x/10i $rip
=> 0x5555555551e7 <main+62>:	lea    0xe49(%rip),%rdi        # 0x555555556037
   0x5555555551ee <main+69>:	mov    $0x0,%eax
   0x5555555551f3 <main+74>:	callq  0x555555555070 <printf@plt>
   0x5555555551f8 <main+79>:	addl   $0x1,-0x8(%rbp)
   0x5555555551fc <main+83>:	mov    -0x8(%rbp),%eax
   0x5555555551ff <main+86>:	cmp    -0x4(%rbp),%eax
   0x555555555202 <main+89>:	jb     0x5555555551db <main+50>
   0x555555555204 <main+91>:	mov    $0xa,%edi
   0x555555555209 <main+96>:	callq  0x555555555060 <putchar@plt>
   0x55555555520e <main+101>:	mov    $0x0,%eax
(gdb) 
0x00005555555551ee in main ()
1: x/10i $rip
=> 0x5555555551ee <main+69>:	mov    $0x0,%eax
   0x5555555551f3 <main+74>:	callq  0x555555555070 <printf@plt>
   0x5555555551f8 <main+79>:	addl   $0x1,-0x8(%rbp)
   0x5555555551fc <main+83>:	mov    -0x8(%rbp),%eax
   0x5555555551ff <main+86>:	cmp    -0x4(%rbp),%eax
   0x555555555202 <main+89>:	jb     0x5555555551db <main+50>
   0x555555555204 <main+91>:	mov    $0xa,%edi
   0x555555555209 <main+96>:	callq  0x555555555060 <putchar@plt>
   0x55555555520e <main+101>:	mov    $0x0,%eax
   0x555555555213 <main+106>:	leaveq 
(gdb) quit
A debugging session is active.

	Inferior 1 [process 3811] will be killed.

Quit anyway? (y or n) y
sec875@ubuntu:~$ 

Run Until Address 运行至地址

临时代码断点,又称运行至地址

运行至地址(又称临时断点)

如果您只想向前执行一些指令,但不想设置然后删除断点,或者不想计算指令数量,则可以使用“until <address>”(缩写:u)命令。

但请注意,如果由于某种原因始终无法到达地址(例如因为控制流分支到其他方向),则在退出当前函数时,until 命令也会中断。

演练

sec875@ubuntu:~$ gdb ./fibber_bin1 -q
Reading symbols from ./fibber_bin1...
(No debugging symbols found in ./fibber_bin1)
(gdb) b main
Breakpoint 1 at 0x11a9
(gdb) r
Starting program: /home/sec875/fibber_bin1 

Breakpoint 1, 0x00005555555551a9 in main ()
(gdb) disas
Dump of assembler code for function main:
=> 0x00005555555551a9 <+0>:	endbr64 
   0x00005555555551ad <+4>:	push   %rbp
   0x00005555555551ae <+5>:	mov    %rsp,%rbp
   0x00005555555551b1 <+8>:	sub    $0x10,%rsp
   0x00005555555551b5 <+12>:	movl   $0xa,-0x4(%rbp)
   0x00005555555551bc <+19>:	mov    -0x4(%rbp),%eax
   0x00005555555551bf <+22>:	mov    %eax,%esi
   0x00005555555551c1 <+24>:	lea    0xe40(%rip),%rdi        # 0x555555556008
   0x00005555555551c8 <+31>:	mov    $0x0,%eax
   0x00005555555551cd <+36>:	callq  0x555555555070 <printf@plt>
   0x00005555555551d2 <+41>:	movl   $0x0,-0x8(%rbp)
   0x00005555555551d9 <+48>:	jmp    0x5555555551fc <main+83>
   0x00005555555551db <+50>:	mov    -0x8(%rbp),%eax
   0x00005555555551de <+53>:	mov    %eax,%edi
   0x00005555555551e0 <+55>:	callq  0x555555555169 <fibbonacci>
   0x00005555555551e5 <+60>:	mov    %eax,%esi
   0x00005555555551e7 <+62>:	lea    0xe49(%rip),%rdi        # 0x555555556037
   0x00005555555551ee <+69>:	mov    $0x0,%eax
   0x00005555555551f3 <+74>:	callq  0x555555555070 <printf@plt>
   0x00005555555551f8 <+79>:	addl   $0x1,-0x8(%rbp)
   0x00005555555551fc <+83>:	mov    -0x8(%rbp),%eax
   0x00005555555551ff <+86>:	cmp    -0x4(%rbp),%eax
   0x0000555555555202 <+89>:	jb     0x5555555551db <main+50>
   0x0000555555555204 <+91>:	mov    $0xa,%edi
   0x0000555555555209 <+96>:	callq  0x555555555060 <putchar@plt>
   0x000055555555520e <+101>:	mov    $0x0,%eax
   0x0000555555555213 <+106>:	leaveq 
   0x0000555555555214 <+107>:	retq   
End of assembler dump.
(gdb) running until after fibbonacci returns...
Undefined command: "running".  Try "help".
(gdb) u *0x00005555555551e5
0x00005555555551e5 in main ()
(gdb) disas
Dump of assembler code for function main:
   0x00005555555551a9 <+0>:	endbr64 
   0x00005555555551ad <+4>:	push   %rbp
   0x00005555555551ae <+5>:	mov    %rsp,%rbp
   0x00005555555551b1 <+8>:	sub    $0x10,%rsp
   0x00005555555551b5 <+12>:	movl   $0xa,-0x4(%rbp)
   0x00005555555551bc <+19>:	mov    -0x4(%rbp),%eax
   0x00005555555551bf <+22>:	mov    %eax,%esi
   0x00005555555551c1 <+24>:	lea    0xe40(%rip),%rdi        # 0x555555556008
   0x00005555555551c8 <+31>:	mov    $0x0,%eax
   0x00005555555551cd <+36>:	callq  0x555555555070 <printf@plt>
   0x00005555555551d2 <+41>:	movl   $0x0,-0x8(%rbp)
   0x00005555555551d9 <+48>:	jmp    0x5555555551fc <main+83>
   0x00005555555551db <+50>:	mov    -0x8(%rbp),%eax
   0x00005555555551de <+53>:	mov    %eax,%edi
   0x00005555555551e0 <+55>:	callq  0x555555555169 <fibbonacci>
=> 0x00005555555551e5 <+60>:	mov    %eax,%esi
   0x00005555555551e7 <+62>:	lea    0xe49(%rip),%rdi        # 0x555555556037
   0x00005555555551ee <+69>:	mov    $0x0,%eax
   0x00005555555551f3 <+74>:	callq  0x555555555070 <printf@plt>
   0x00005555555551f8 <+79>:	addl   $0x1,-0x8(%rbp)
   0x00005555555551fc <+83>:	mov    -0x8(%rbp),%eax
   0x00005555555551ff <+86>:	cmp    -0x4(%rbp),%eax
   0x0000555555555202 <+89>:	jb     0x5555555551db <main+50>
   0x0000555555555204 <+91>:	mov    $0xa,%edi
   0x0000555555555209 <+96>:	callq  0x555555555060 <putchar@plt>
   0x000055555555520e <+101>:	mov    $0x0,%eax
   0x0000555555555213 <+106>:	leaveq 
   0x0000555555555214 <+107>:	retq   
End of assembler dump.
(gdb) now running until after the next printf
Undefined command: "now".  Try "help".
(gdb) until *0x00005555555551f8
0x00005555555551f8 in main ()
(gdb) disas
Dump of assembler code for function main:
   0x00005555555551a9 <+0>:	endbr64 
   0x00005555555551ad <+4>:	push   %rbp
   0x00005555555551ae <+5>:	mov    %rsp,%rbp
   0x00005555555551b1 <+8>:	sub    $0x10,%rsp
   0x00005555555551b5 <+12>:	movl   $0xa,-0x4(%rbp)
   0x00005555555551bc <+19>:	mov    -0x4(%rbp),%eax
   0x00005555555551bf <+22>:	mov    %eax,%esi
   0x00005555555551c1 <+24>:	lea    0xe40(%rip),%rdi        # 0x555555556008
   0x00005555555551c8 <+31>:	mov    $0x0,%eax
   0x00005555555551cd <+36>:	callq  0x555555555070 <printf@plt>
   0x00005555555551d2 <+41>:	movl   $0x0,-0x8(%rbp)
   0x00005555555551d9 <+48>:	jmp    0x5555555551fc <main+83>
   0x00005555555551db <+50>:	mov    -0x8(%rbp),%eax
   0x00005555555551de <+53>:	mov    %eax,%edi
   0x00005555555551e0 <+55>:	callq  0x555555555169 <fibbonacci>
   0x00005555555551e5 <+60>:	mov    %eax,%esi
   0x00005555555551e7 <+62>:	lea    0xe49(%rip),%rdi        # 0x555555556037
   0x00005555555551ee <+69>:	mov    $0x0,%eax
   0x00005555555551f3 <+74>:	callq  0x555555555070 <printf@plt>
=> 0x00005555555551f8 <+79>:	addl   $0x1,-0x8(%rbp)
   0x00005555555551fc <+83>:	mov    -0x8(%rbp),%eax
   0x00005555555551ff <+86>:	cmp    -0x4(%rbp),%eax
   0x0000555555555202 <+89>:	jb     0x5555555551db <main+50>
   0x0000555555555204 <+91>:	mov    $0xa,%edi
   0x0000555555555209 <+96>:	callq  0x555555555060 <putchar@plt>
   0x000055555555520e <+101>:	mov    $0x0,%eax
   0x0000555555555213 <+106>:	leaveq 
   0x0000555555555214 <+107>:	retq   
End of assembler dump.
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00005555555551a9 <main>
	breakpoint already hit 1 time
(gdb) Quit
(gdb) q
A debugging session is active.

	Inferior 1 [process 3875] will be killed.

Quit anyway? (y or n) y
sec875@ubuntu:~$ 

GDB Misc GDB 杂项

Saving a Persistent GDB Configuration 保存持久 GDB 配置

GDB 命令文件
通常,您会在 gdb 中多次启动和停止相同或不同的可执行文件。您可能希望每次启动 gdb 时都运行相同的命令,以设置一组通用寄存器、内存或指令的视图。或者您可能希望设置一些常用断点。这可以通过创建一个纯文本文件(例如 ~/x.cfg)并输入您希望在启动时在 gdb 中执行的一组 gdb 命令(每行一个)来实现。然后,当您启动 gdb 时,使用 -x 选项指定命令文件(例如 -x ~/x.cfg)。

Intel(x86-64)推荐启动命令
将这些复制并粘贴到您自己的 ~/x.cfg 命令文本文件中:

display/10i $rip
display/x $rbp
display/x $rsp
display/x $rax
display/x $rbx
display/x $rcx
display/x $rdx
display/x $rdi
display/x $rsi
display/x $r8
display/x $r9
display/x $r12
display/x $r13
display/x $r14
display/10gx $rsp
start

RISC-V (RV32I/RV64I) recommended starting commands
将这些复制并粘贴到您自己的 ~/x.cfg 命令文本文件中:

display/x $ra
display/x $a0
display/x $a1
display/x $a4
display/x $a5
display/x $s0
display/10gx $sp
display/10i $pc
start

Changing Assembly Syntax 更改汇编语法

更改反汇编语法(RISC-V)
您可以禁用 ABI 寄存器名称的使用,并恢复为仅使用 x0-x31 寄存器名称,方法是:
set disassembler-options numeric
您可以使用以下命令在汇编输出中禁用伪指令(别名):
set disassembler-options no-aliases

注意:我认为目前存在一个错误,因为“set disassembler-options”应该清除这些选项,但并没有取消设置这些选项(“unset disassembler-options”命令也不起作用)。撤消这些选项的唯一方法是退出并重新启动 gdb。(但如果你找到了另一种方法,LMK!)

Mini-Course Complete! 迷你课程完成

Mini-Course Complete! 迷你课程完成

干得好!现在您可以在依赖这些技能的各种 OST 课程中使用这些技能!(例如 Arch1001:x86-64 汇编,或 Arch1005:RISC-V 汇编)。

这里有一些 GDB command cheatsheets GDB 命令备忘单,供以后参考:1、2。
https://darkdust.net/files/GDB Cheat Sheet.pdf
https://users.ece.utexas.edu/~adnan/gdb-refcard.pdf

Timing Feedback: Mini-Course Complete! 时间反馈:迷你课程完成

posted @ 2024-10-04 05:24  sec875  阅读(12)  评论(0编辑  收藏  举报