GDB十分钟教程

it2022-05-10  119

GDB十分钟教程

作者: liigo原文链接: http://blog.csdn.net/liigo/archive/2006/01/17/582231.aspx日期: 2006年1月16日

本文写给主要工作在Windows操作系统下而又须要开发一些跨平台软件的程序猿朋友,以及程序爱好者。

GDB是一个由GNU开源组织公布的、UNIX/LINUX操作系统下的、基于命令行的、功能强大的程序调试工具。

GDB中的命令固然非常多,但我们仅仅需掌握当中十个左右的命令,就大致能够完毕日常的主要的程序调试工作。

 命令 解释 演示样例file <文件名称>载入被调试的可运行程序文件。由于一般都在被调试程序所在文件夹下运行GDB,因而文本名不须要带路径。(gdb) file gdb-samplerRun的简写,执行被调试的程序。假设此前没有下过断点,则执行完整个程序;假设有断点,则程序暂停在第一个可用断点处。(gdb) rcContinue的简写,继续运行被调试程序,直至下一个断点或程序结束。(gdb) cb <行号>b <函数名称>b *<函数名称>b *<代码地址>

d [编号]

b: Breakpoint的简写,设置断点。两能够使用“行号”“函数名称”“运行地址”等方式指定断点位置。当中在函数名称前面加“*”符号表示将断点设置在“由编译器生成的prolog代码处”。假设不了解汇编,能够不予理会此使用方法。

d: Delete breakpoint的简写,删除指定编号的某个断点,或删除全部断点。断点编号从1開始递增。

(gdb) b 8(gdb) b main(gdb) b *main(gdb) b *0x804835c

(gdb) d

s, ns: 运行一行源程序代码,假设此行代码中有函数调用,则进入该函数;n: 运行一行源程序代码,此行代码中的函数调用也一并运行。

s 相当于其他调试器中的“Step Into (单步跟踪进入)”;n 相当于其他调试器中的“Step Over (单步跟踪)”。

这两个命令必须在有源码调试信息的情况下才干够使用(GCC编译时使用“-g”參数)。

(gdb) s(gdb) nsi, nisi命令相似于s命令,ni命令相似于n命令。所不同的是,这两个命令(si/ni)所针对的是汇编指令,而s/n针对的是源码。(gdb) si(gdb) nip <变量名称>Print的简写,显示指定变量(暂时变量或全局变量)的值。(gdb) p i(gdb) p nGlobalVardisplay ...

undisplay <编号>

display,设置程序中断后欲显示的数据及其格式。比如,假设希望每次程序中断后能够看到即将被运行的下一条汇编指令,能够使用命令“display /i $pc”当中 $pc 代表当前汇编指令,/i 表示以十六进行显示。当须要关心汇编代码时,此命令相当实用。

undispaly,取消先前的display设置,编号从1開始递增。

(gdb) display /i $pc

(gdb) undisplay 1

iInfo的简写,用于显示各类信息,详情请查阅“help i”。(gdb) i rqQuit的简写,退出GDB调试环境。(gdb) qhelp [命令名称]GDB帮助命令,提供对GDB名种命令的解释说明。假设指定了“命令名称”參数,则显示该命令的具体说明;假设没有指定參数,则分类显示全部GDB命令,供用户进一步浏览和查询。(gdb) help display

 

废话不多说,以下開始实践。

先给出一个演示样例用的小程序,C语言代码,简单的不能再简单了:

123456789101112131415161718192021222324252627282930313233

//此程序仅作为“GDB十分钟教程”的演示样例代码, by liigo//Email: liigo@sina.com//blog: http://blog.csdn.net/liigo//WebSite: www.liigo.com #include <stdio.h>int nGlobalVar = 0;int tempFunction(int a, int b){    printf("tempFunction is called, a = %d, b = %d /n", a, b);    return (a + b);}int main(){    int n;    n = 1;    n++;    n--;    nGlobalVar += 100;    nGlobalVar -= 12;    printf("n = %d, nGlobalVar = %d /n", n, nGlobalVar);    n = tempFunction(1, 2);    printf("n = %d", n);    return 0;}

请将此代码复制出来并保存到文件 gdb-sample.c 中,然后切换到此文件所在文件夹,用GCC编译之:

gcc gdb-sample.c -o gdb-sample -g

在上面的命令行中,使用 -o 參数指定了编译生成的可运行文件名称为 gdb-sample,使用參数 -g 表示将源码信息编译到可运行文件里。假设不使用參数 -g,会给后面的GDB调试造成不便。当然,假设我们没有程序的源码,自然也无从使用 -g 參数,调试/跟踪时也仅仅能是汇编代码级别的调试/跟踪。

以下“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 arewelcome 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-sample 即前面 GCC 编译输出的可运行文件):

(gdb) file gdb-sampleReading symbols from gdb-sample...done.

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

以下使用“r”命令运行(Run)被调试文件,由于尚未设置不论什么断点,将直接运行到程序结束:

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

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

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

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

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

(gdb) rStarting program: /home/liigo/temp/gdb-sampleBreakpoint 1, main () at gdb-sample.c:1919 n = 1;

程序中断在gdb-sample.c第19行处,即main函数是第一个可运行语句处。

上面最后一行信息为:下一条将要运行的源码为“n = 1;”,它是源码文件gdb-sample.c中的第19行。

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

(gdb) s20 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 26Breakpoint 2 at 0x804837b: file gdb-sample.c, line 26.(gdb) b tempFunctionBreakpoint 3 at 0x804832e: file gdb-sample.c, line 12.

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

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

上面反馈的信息一切都在我们预料之中,哈哈~~~

再一次运行“c”命令(Continue),由于后面再也没有其他断点,程序将一直运行到结束:

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

 

有时候须要看到编译器生成的汇编代码,以进行汇编级的调试或跟踪,又该怎样操作呢?

这就要用到display命令“display /i $pc”了(此命令前面已有详解):

(gdb) display /i $pc(gdb) 

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

(gdb) rStarting program: /home/liigo/temp/test_jmp/test_jmp/gdb-sampleBreakpoint 1, main () at gdb-sample.c:1919 n = 1;1: x/i $pc 0x804835c <main+16>: movl $0x1,0xfffffffc(
转载请注明原文地址: https://win8.8miu.com/read-1492645.html

最新回复(0)