首页 > 其他分享 >GDB

GDB

时间:2024-10-15 20:33:58浏览次数:1  
标签:gdb sample pc GDB main 断点

gdb

小南梁

  • 功能强大的程序调试器

补充说明

gdb命令 包含在GNU的gcc开发套件中,是功能强大的程序调试器。GDB中的命令固然很多,但我们只需掌握其中十个左右的命令,就大致可以完成日常的基本的程序调试工作。

语法

gdb(选项)(参数)

选项

-cd:设置工作目录;
-q:安静模式,不打印介绍信息和版本信息;
-d:添加文件查找路径;
-x:从指定文件中执行GDB指令;
-s:设置读取的符号表文件。
gcc gdb-sample.c -o gdb-sample -g

-o :指定输出文件名
-g :将源代码信息编译到可执行文件中

如果不使用 -g 会给后面的GDB 调试带来不便!

下面“gdb”命令启动GDB,将首先显示GDB说明:

/*GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
Copyright 2003 free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu".
(gdb)*/

上面最后一行“(gdb)”为GDB内部命令引导符,等待用户输入GDB命令。

下面使用“file”命令载入被调试程序 gdb-sample
(gdb) file gdb-sample
Reading symbols from gdb-sample...done.

上面最后一行提示已经加载成功。

下面使用“r”命令执行(Run)被调试文件,因为尚未设置任何断点,将直接执行到程序结束

(gdb) r
Starting program: /home/liigo/temp/test_jmp/test_jmp/gdb-sample
n = 1, nGlobalVar = 88
tempFunction is called, a = 1, b = 2
n = 3
Program exited normally.

下面使用“b”命令在 main 函数开头设置一个断点(Breakpoint):


(gdb) b main
Breakpoint 1 at 0x804835c: file gdb-sample.c, line 19.

上面最后一行提示已经成功设置断点,并给出了该断点信息:在源文件 gdb-sample.c 第19行处设置断点;这是本程序的第一个断点(序号为1);断点处的代码地址为 0x804835c(此值可能仅在本次调试过程中有效)。回过头去看源代码,第19行中的代码为“n = 1”,恰好是 main 函数中的第一个可执行语句(前面的“int n;”为变量定义语句,并非可执行语句)。

再次使用“r”命令执行(Run)被调试程序

(gdb) r
Starting program: /home/liigo/temp/gdb-sample

Breakpoint 1, main () at gdb-sample.c:19
19 n = 1;

下面使用“s”命令(Step)执行下一行代码(即第19行“n = 1;”):

(gdb) s
20 n++;

上面的信息表示已经执行完“n = 1;”,并显示下一条要执行的代码为第20行的“n++;”

既然已经执行了“n = 1;”,即给变量 n 赋值为 1,那我们用“p”命令(Print)看一下变量 n 的值是不是 1 :

(gdb) p n
$1 = 1

果然是 1。($1大致是表示这是第一次使用“p”命令——再次执行“p n”将显示“$2 = 1”——此信息应该没有什么用处。)

下面我们分别在第26行、tempFunction 函数开头各设置一个断点(分别使用命令“b 26”“b tempFunction”):

(gdb) b 26
Breakpoint 2 at 0x804837b: file gdb-sample.c, line 26.
(gdb) b tempFunction
Breakpoint 3 at 0x804832e: file gdb-sample.c, line 12

使用“c”命令继续(Continue)执行被调试程序,程序将中断在第二 个断点(26行),此时全局变量 nGlobalVar 的值应该是 88;再一次执行“c”命令,程序将中断于第三个断点(12行,tempFunction 函数开头处),此时tempFunction 函数的两个参数 a、b 的值应分别是 1 和 2:

(gdb) c
Continuing.

Breakpoint 2, main () at gdb-sample.c:26
26 printf("n = %d, nGlobalVar = %d /n", n, nGlobalVar);
(gdb) p nGlobalVar
$2 = 88
(gdb) c
Continuing.
n = 1, nGlobalVar = 88

Breakpoint 3, tempFunction (a=1, b=2) at gdb-sample.c:12
12 printf("tempFunction is called, a = %d, b = %d /n", a, b);
(gdb) p a
$3 = 1
(gdb) p b
$4 = 2

再一次执行“c”命令(Continue),因为后面再也没有其它断点,程序将一直执行到结束:

(gdb) c
Continuing.
tempFunction is called, a = 1, b = 2
n = 3
Program exited normally.

有时候需要看到编译器生成的汇编代码,以进行汇编级的调试或跟踪,又该如何操作呢?这就要用到display命令“display /i $pc”了(此命令前面已有详细解释):

(gdb) display /i $pc
(gdb)

此后程序再中断时,就可以显示出汇编代码了:

(gdb) r
Starting program: /home/liigo/temp/test_jmp/test_jmp/gdb-sample

Breakpoint 1, main () at gdb-sample.c:19
19 n = 1;
1: x/i $pc 0x804835c <main+16>: movl $0x1,0xfffffffc(%ebp)

看到了汇编代码,“n = 1;”对应的汇编代码是“movl $0x1,0xfffffffc(%ebp)”
并且以后程序每次中断都将显示下一条汇编指定(“si”命令用于执行一条汇编代码——区别于“s”执行一行C代码)

(gdb) si
20 n++;
1: x/i $pc 0x8048363 <main+23>: lea 0xfffffffc(%ebp),%eax
(gdb) si
0x08048366 20 n++;
1: x/i $pc 0x8048366 <main+26>: incl (%eax)
(gdb) si
21 n--;
1: x/i $pc 0x8048368 <main+28>: lea 0xfffffffc(%ebp),%eax
(gdb) si
0x0804836b 21 n--;
1: x/i $pc 0x804836b <main+31>: decl (%eax)
(gdb) si
23 nGlobalVar += 100;
1: x/i $pc 0x804836d <main+33>: addl $0x64,0x80494fc

接下来我们试一下命令“b *<函数名称>”。

为了更简明,有必要先删除目前所有断点(使用“d”命令——Delete breakpoint):

(gdb) d
Delete all breakpoints? (y or n) y
(gdb)

当被询问是否删除所有断点时,输入“y”并按回车键即可。

下面使用命令“b *main”在 main 函数的 prolog 代码处设置断点(prolog、epilog,分别表示编译器在每个函数的开头和结尾自行插入的代码)

(gdb) b *main
Breakpoint 4 at 0x804834c: file gdb-sample.c, line 17.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/liigo/temp/test_jmp/test_jmp/gdb-sample

Breakpoint 4, main () at gdb-sample.c:17
17 {
1: x/i $pc 0x804834c <main>: push %ebp
(gdb) si
0x0804834d 17 {
1: x/i $pc 0x804834d <main+1>: mov %esp,%ebp
(gdb) si
0x0804834f in main () at gdb-sample.c:17
17 {
1: x/i $pc 0x804834f <main+3>: sub $0x8,%esp
(gdb) si
0x08048352 17 {
1: x/i $pc 0x8048352 <main+6>: and $0xfffffff0,%esp
(gdb) si
0x08048355 17 {
1: x/i $pc 0x8048355 <main+9>: mov $0x0,%eax
(gdb) si
0x0804835a 17 {
1: x/i $pc 0x804835a <main+14>: sub %eax,%esp
(gdb) si
19 n = 1;
1: x/i $pc 0x804835c <main+16>: movl $0x1,0xfffffffc(%ebp)

当然也可以显示任意一个指定的寄存器值:

(gdb) i r eax
eax 0xbffff6a4 -1073744220

最后一个要介绍的命令是“q”,退出(Quit)GDB调试环境:

(gdb) q
The program is running. exit anyway? (y or n)

补充内容

I love you !

如果删除源代码, 就无法显示行号等辅助信息了

gcc -g gdb.c -o gdb.out # -g 支持gdb调试; -o 输出, 默认为 a.out

gdb gdb.out # 进入 gdb 调试环境
enter # 继续执行上条命令
l # 列出源代码, 默认 10 行, 按 l 继续

start # 开始单步调试, 默认 main() 第一行
p a # 查看 a 变量的值
n # 继续到下一行
s # 进入子函数
bt # 查看函数栈
f 1 # 切换函数栈

q 退出调试

测试用代码

#include <stdio.h>

void change(int a, int b){
    int tmp=a;
    a=b; b=tmp;
}

void change2(int *a, int *b){
    int tmp=*a;
    *a=*b; *b=tmp;
}

int main(){
    int a=5,b=3;
    change(a,b);
    printf("change:\na=%d\nb=%d\n", a,b);
    change2(&a,&b);
    printf("change2:\na=%d\nb=%d\n", a,b);
}

标签:gdb,sample,pc,GDB,main,断点
From: https://www.cnblogs.com/mathMing66/p/18468368

相关文章

  • 循序渐进丨MogDB 数据库查询重写规则lazyagg详解
    问题概述在MogDB和openGauss中,参数rewrite_rule用于控制查询重写,本文介绍查询重写规则lazyagg。在未设置rewrite_rule=lazyagg的情况下,子查询中有GROUPBY会先进行GROUPBY;lazyagg表示延迟聚合运算,目的是消除子查询中的聚合运算,先关联再GROUPBY;当子查询中有GROUPBY,子......
  • GCC 编译器 与 GDB 调试器的基本操作
    一、GCC编译器1.什么是GCCGCC是GNUCompilerCollection(GNU编译器套装)的简称,目前GCC可以支持C,C++,ADA,JAVA,Fortran,PASCAL等多种高级语言。支持主流的CPU平台,完成从源程序向特定CPU硬件平台上自标代码的转换。2.GCC编译流程2.1方法一:四步完成编译1)预处理对......
  • gdb多线程多进程调试命令
    多线程infothreads查看当前所有运行线程的列表thread线程编号 切换到特定线程进行调试setscheduler-lockingon只运行当前线程,停止其他线程进行调试多进程infoinferions显示所有正在调试的进程inferion进程编号 切换到特定进程运行,同时挂起其他进程detach-on-fo......
  • [20241006]跟踪library cache lock library cache pin使用gdb(补充测试3).txt
    [20241006]跟踪librarycachelocklibrarycachepin使用gdb(补充测试3).txt--//补充测试产生光标已经缓存的情况下,生成新子光标的调用librarycachelocklibrarycachepin的情况。1.环境:SCOTT@book01p>@ver2==============================PORT_STRING          ......
  • 今天终于解决lazarus debug模式为GDB时中文变量显示出错的问题
    之前已修复fpdebug中文变量的Bug,但GDB还存在问题(提示:Invalidcharacterxxxxinexpression)修复步骤:打开lazarus/components/lazdebuggergdbmi/gdbmidebugger.pp,按红色代码修改。在TGDBMIExceptionInfo=record后添加functionischinese(s:string):string(1790行):TGD......
  • gdb调试
    1、https://gitee.com/下载课程代码,编译运⾏"bestidiocs2024/ch02/c/testgdb.c",记录编译运⾏结果(2分)运行结果:Thesumof1-50is12752、参考https://www.cnblogs.com/rocedu/p/16714289.html调试代码,⾄少涵盖4种断点(⾏断点,函数断点,临时断点,条件断点)行断点:bmain函数断点:b......
  • gdb
    gdb控制程序行为环境变量(gdb)setenvironmentVAR=value多线程相关命令查看线程列表:在gdb中可以使用以下命令查看当前所有线程的列表:(gdb)infothreads这将列出所有线程及其状态,包括它们的LWPID和线程标识符。切换到特定线程:如果你想切换调试上下文到某......
  • Debuggers 1012:Introductory GDB
    OpenSecurityTraining2LearningPaths:VulnerabilityHunting&Exploitationpython:https://www.learnpython.org/路径图:https://ost2.fyi/OST2_LP_Vulns_Exploits.pdfDebuggers1012:IntroductoryGDB(与python)-->Architecture1001:x86-64Assembly-->R......
  • linux gdb debuging
    GDBGNU下的一个调试软件,在linux下可以用来调试c/c++代码。启动可以通过gdb--help查看用法,如下:ThisistheGNUdebugger.Usage:gdb[options][executable-file[core-fileorprocess-id]]gdb[options]--argsexecutable-file[inferior-arguments...]gdb[optio......
  • mongdb7副本集修改IP
    mongdb7副本集修改IP环境信息主机名IP端口资源mongodb1192.168.56.111C/2G/50Gmongodb2192.168.56.121C/2G/50Gmongodb3192.168.56.131C/2G/50Goperatingsystem:CentOS-7.6-x86_64-DVD-1810.isoMasterIP:192.168.56.11SlaveIP:192.168.56.12ArbiterIP:192.168.56.13......