《深入分析GCC 》——2.2 GNU gdb调试工具

2.2 GNU gdb调试工具

调试工具是代码分析中至关重要的工具之一。在使用vim+ctags查看代码时,经常会遇到难以理解的部分,此时,可以借助调试工具,对代码的运行过程进行跟踪,通过跟踪运行过程以及关键数据的变化,可以从程序执行的过程中理解源代码的功能。
调试工具有很多种,最常用的是GNU gdb工具。下面通过一个例子,介绍如何使用gdb,这些调试命令几乎就是笔者调试程序的所有命令,简单且实用。关于完整的gdb的使用,请参与GNU gdb文档,或者使用man gdb进行在线查询。
本例主要使用gdb来跟踪GCC的运行过程,因此,需要事先编译GCC源代码(编译时需要使用-g选项),生成可执行的编译程序cc1,下面利用gdb对cc1程序的运行进行跟踪。
首先,可以在程序入口处设置断点(Break Point):

[GCC@localhost paag-gcc]$ gdb host-i686-pc-linux-gnu/gcc/cc1
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-75.el6)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/GCC/paag-gcc/host-i686-pc-linux-gnu/gcc/cc1...done.
(gdb) b main            ? 设置执行断点
Breakpoint 1 at 0x80c253d: file ../.././gcc/main.c, line 35.
(gdb) info break        ? 查看断点设置情况
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x080c253d in main at ../.././gcc/main.c:35
(gdb)
执行程序,gdb执行到断点处会自动停止,返回交互界面。
(gdb) run           ? 运行程序
Starting program: /home/GCC/paag-gcc/host-i686-pc-linux-gnu/gcc/cc1
Breakpoint 1, main (argc=1, argv=0xbffff434) at ../.././gcc/main.c:35
35      return toplev_main (argc, (const char **) argv);
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.149.el6.i686 gmp-4.3.1-7.el6_2.2.i686 mpfr-2.4.1-6.el6.i686

单步跟踪程序的执行,step命令和next命令均可以进行单步跟踪,二者的主要区别在于step在单步执行函数代码时,会进入被调用的函数,而next则会将函数调用看作“单步”,一次执行完一个函数的调用。对于其他代码,step和next命令的功能基本相同。
此时可以看到,使用run命令执行程序后,程序执行到前面定义的断点处暂停执行。
如果此时需要查看toplev_main函数的执行细节,应该使用step命令进入该函数。
(gdb) step ? 单步跟踪
toplev_main (argc=1, argv=0xbffff434) at ../.././gcc/toplev.c:2212
对于程序执行过程中,需要查看某些变量的值,可以使用print命令。

(gdb) print argc        ? 打印变量值
$1 = 1
(gdb) print argv[0] ? 打印变量值
$2 = 0xbffff5b5 "/home/GCC/paag-gcc/host-i686-pc-linux-gnu/gcc/cc1"

查看变量的值可以使用print命令,如果在每一条指令后都需要查看某些变量的值,使用print显得有些烦琐,可以使用display命令,设置显示的变量。

(gdb) disp argc     ? 设置变量查看
1: argc = 1
(gdb) next          ? 单步执行
2215      general_init (argv[0]);
1: argc = 1
(gdb) next
2219      decode_options (argc, argv);
1: argc = 1
(gdb) next
2221      init_local_tick ();
1: argc = 1

可以看出,每执行一步,变量argc的值都会输出显示。
当需要连续执行程序时,可以使用continue命令,程序则恢复运行,直到下一个断点处再次暂停运行。
通常,在执行到某个断点处时,当需要了解当前函数的调用情况时,可以使用bt命令(backtrace)。
(gdb) bt ? 显示函数调用的堆栈

0 toplev_main (argc=1, argv=0xbffff434) at ../.././gcc/toplev.c:2212

1 main (argc=1, argv=0xbffff434) at ../.././gcc/main.c:35

可以看出当前执行的函数为toplev_main函数,其调用者为函数main,并且这两个函数所在的文件及位置信息也在bt的输出中给出。bt命令的输出可以很详细地展示当前函数的调用关系,对于理解程序的执行流程非常有帮助。
另外,gdb在输入命令时,如果输入命令的开始部分可以完全确定一个命令时,则可以简写该命令,例如,一般用户经常将命令run简写为r,step命令简写为s,next命令简写为n,continue命令简写为c等,如果用户没有输入命令,直接按回车键,则gdb默认会执行上一次输入的命令。例如在单步跟踪时,如果输入了命令next,后续单步跟踪则可以只需要按[Enter]键就可以了。这些规律,读者可以在使用过程中不断总结,提高调试效率。
另外,还有其他众多的调试工具,这些工具大都对gdb程序进行了封装,例如cgdb,可以提供一些方便地实现源代码查看等其他很有特色的功能,其官网地址为http://cgdb.sourceforge.net/。可以通过以下代码进行cgdb程序的安装。

[root@localhost ~]# wget -c http://prdownloads.sourceforge.net/cgdb/cgdb-0.6.6.tar.gz?download
[root@localhost cgdb-0.6.6]# tar xzvf cgdb-0.6.6.tar.gz
[root@localhost cgdb-0.6.6]# cd cgdb
[root@localhost cgdb-0.6.6]# yum install readline*
[root@localhost cgdb-0.6.6]# ./configure
[root@localhost cgdb-0.6.6]# make; make install
例如,可以使用cgdb对cc1进行调试。
[GCC@localhost gcc-4.4.0]$ cgdb ~/paag-gcc/host-i686-pc-linux-gnu/gcc/cc1

界面如图2-3所示,可以看到cgdb中能够很方便地查看源代码。关于cgdb的使用请查阅相关文档,不再赘述。

时间: 2024-12-31 02:27:01

《深入分析GCC 》——2.2 GNU gdb调试工具的相关文章

《深入分析GCC 》导读

前 言 GCC(GNU Compiler Collection,GNU编译器套件)是一套由GNU开发的程序设计语言编译工具,是GNU工程中最重要的组成部分.经过近30年的发展,GCC不仅支持众多的前端编程语言,还支持各种主流的处理器平台和操作系统平台,成为公认的跨平台编译器的事实标准,也成为编译器设计的成功典范. 作为一名GCC编译器的使用者和源码阅读的爱好者,我一直想写一本关于GCC的技术书. 2002年,我开始在Linux系统上进行一些软件开发,GCC就是我使用的编译工具.我一直对从源代码到

使用 Strace 和 GDB 调试工具的乐趣

编写 UNIX 系统程序充满乐趣,并且具有教育意义.使用 UNIX strace 工具和 GDB(GNU 项目调试工具),您可以真正地深入研究系统的功能,并了解组成这些功能的各种各样的程序.同时使用这两种工具,能够在查看 UNIX 计算机底层信息 的时候,给您带来更好的体验. UNIX 家族总是为用户提供了丰富的工具.UNIX 是一个工具财宝箱,有了这些工具,您不仅可以完成具有创造性的工作,还可以在深入研究该操作系统的同时得到教育和娱乐.strace(用来跟踪任何程序的系统调用)和 GDB 调试

《深入分析GCC 》——1.2 GCC的特点

1.2 GCC的特点 GCC作为目前较为成功的编译系统之一,具有非常突出的优点,主要包括: (1)GCC编译系统支持众多的前端编程语言,GCC 4.4.0中${GCC_SOURCE}/gcc/目录下包含了前端编程语言处理的目录及其代码(其中,${GCC_SOURCE}表示GCC源代码的主目录,下同),主要包括C.C++.Ada.Fortran.Java.Objective-C.Objective-C++等语言的前端处理,可以使用如下命令查看这些目录: [GCC@localhost gcc-4.4

gcc/g++编译器和gdb调试器

gcc and g++分别是gnu的c & c++编译器 gcc/g++在执行编译工作的时候,总共需要4步 1.预处理,生成.i的文件[预处理器cpp]2.将预处理后的文件不转换成汇编语言,生成文件.s[编译器egcs]3.有汇编变为目标代码(机器代码)生成.o的文件[汇编器as]4.连接目标代码,生成可执行程序[链接器ld] [参数详解]-x language filename 设定文件所使用的语言,使后缀名无效,对以后的多个有效.也就是根据约定C语言的后缀名称是.c的,而C++的后缀名是.C

《深入分析GCC 》——第1章 GCC概述1.1 GCC的产生与发展

第1章 GCC概述 本章主要对GCC的发展过程及GCC的特点进行简介,并给出了本书的主要内容简介. 1.1 GCC的产生与发展 GCC(GNU Compiler Collection)是GNU工程(GNU Project)中的核心工具软件,其官方网址为https://gcc.gnu.org/.GCC支持多种前端的编程语言,包括C.C++.Java.Ada和Fortran等,其编译生成的目标代码可以在几乎所有的处理器平台上运行,是目前使用最广泛的编译系统之一.GCC遵循GNU GPL(GNU Pu

《深入分析GCC 》——3.3 GCC源代码编译

3.3 GCC源代码编译 在获得了GCC的源代码后,为了生成目标机器上的编译器程序,需要对源代码进行编译,一般步骤包括: (1)使用conf?igure脚本完成编译配置,生成Makef?ile文件. (2)使用make工具编译源代码. (3)使用make工具安装生成的编译程序等. 使用的典型脚本为: ./configure make make install 3.3.1 配置 这个过程一般很简单,可以直接在${GCC_SOURCE}目录下使用命令./conf?igure.该脚本会对GCC源代码编

《深入分析GCC 》——第3章 GCC总体结构3.1 GCC的目录结构

第3章 GCC总体结构GCC是一个复杂的软件系统,例如gcc-4.4.0.tar.gz软件包中包含了成千上万个文件.本章主要对GCC的代码结构和目录结构进行介绍,阐明GCC的主要模块及其相互关系,并给出GCC源代码编译的主要步骤和关键问题.3.1 GCC的目录结构GCC的源代码可以从GCC的官网(https://gcc.gnu.org)上获得.该源代码包主要包括bz2和gz两种压缩形式的tar包,以gcc-4.4.0为例,分别为gcc-4.4.0.tar.bz2及gcc-4.4.0.tar.gz

《深入分析GCC 》——3.2 GCC的逻辑结构

3.2 GCC的逻辑结构 GCC的源代码文件数量庞大,目录结构复杂,总体结构理解有一定的难度,但从代码功能和逻辑结构上来讲,这些代码大致可以分为如图3-1所示的几个部分. 图3-1分为上下两个部分,上半部分使用GCC表示GCC 4.4.0的源代码内容,下半部分使用gcc/cc1表示使用GCC源代码编译生成的编译器程序.图3-1的上半部分根据源代码的功能将GCC源代码分为4大部分:(1)高级语言相关代码(High-Level-Language Specif?ic Code).在GCC的源代码中,对

gcc程序编译和gdb程序调试的基本选项

GCC程序编译 基本格式:gcc [options] [filename] -o 输出可执行文件,如果不给出这个选项,则默认输出a.out可执行文件:如:gcc hello.c -o hello -c 只编译,不连接为可执行文件,生成为以.o为后缀名的目标文件:如:gcc -c hello.c -S 只激活预处理和编译,就是指把文件编 译成为汇编代码.如:gcc -S hello.c    -O 优化编译.连接:-O2对-O再进行优化编译.连接:    -g 编译时,对函数库产生符号信息:(注: