GDB(三) 栈框架和栈

10 篇文章 0 订阅

       内存布局里的一个区域被称为栈,它是栈框架的集合。每个栈框架表示一个函数调用。随着函数被调用,栈框架的数量会增加,栈也是增长。相反,当函数从它们的调用者那里返回,栈框架的数量减少,栈也会缩减。

一个程序由一个或多个通过调用对方来交互的函数组成。每当一个函数被调用时,内存的一块区域为这个新的函数调用分配好,被称为栈框架。这块区域拥有一些重要信息,比如;

1、新的被调用函数的所有自动变量的存储空间。

2、被调用函数返回值要返回到的调用者的行号。

3、被调用函数的参数。

每个函数都有它自己的栈。总的来看,所有栈框架组成了调用栈(call stack)。

调试之前,应该准备好可以调试的可执行程序。简单来说,我们需要在程序里加入信息。

一个符号(symbol)是一个变量或一个函数。符号表(Symbol Tables)就是在一个可执行程序里的变量和函数的一张表。通常,符号表只包含符号的内存地址,因为计算计不使用(或不关心)我们给变量和函数的命名。

但是为了让GDB对我们有用,它需要能够引用变量名和函数名,而不是它们的地址。人类使用main()或i这样的名字。计算机使用0x804b64d或0xbffff7784这样的地址。为了这个目的,我们可以用“调试信息”编译代码,来告诉GDB两件事:

1、如何把符号的地址和源码的名字关联起来;

2、如何把一个机器代码的地址和一行源码关联起来。

拥有这些额外调试信息的符号表被称为一个参数化的或增强的符号表。因为GCC和GDB在如此多的不同平台上运行,调试信息有许多不同的格式:

stabs:多数BSD系统上的DBX使用的格式。

coff:在System V Release 4之前的多数System V系统上的SDB使用的格式。

xcoff:IBM RS/6000系统上的DBX使用的格式。

dwarf:多种SVR4上的SDB使用的格式。

dwarf2:IRIX6上的DBX使用的格式。

vms:VMS系统上的DEBUG使用的格式。

除了调用格式外,GDB了解允许它使用GNU扩展的这些格式的增强变体。使用不是GDB的其它东西来调试一个带有GNU增强调试格式的可执行程序,会导致调试器崩溃。

不要被所有这些格式吓到,GDB会自动为你挑选最好的格式。极少情况下你才需要一个不同的格式,可能千分之一的概率。

使用gcc的-g选项可以为一个可执行程序产生一个增强的符号表。

正如之前讨论的,有许多调试格式。-g的确切含义是为你的系统以本地格式产生调试信息。

作为-g的替代,你还可以使用gcc的-ggdb选项。它以最昂贵的格式来产生调试信息,包括前面讨论的GNU增强变体。这很可能是你在多数情况下想要使用的选项。

你也可以给-g、-ggdb和所有其它调试格式选项一个数值参数。1表示最少量的信息而3表示最多量。没有一个数值参数时,调试等级默认为2。通过使用-g3你甚至可以访问预处理的宏,这非常棒。我们最好总是使用-ggdb3来产生增强符号表。

被编译进可执行程序的调试信息不会被读入内存,除非GDB载入这个可执行程序。这表示含有调试信息的可执行程序不会比不带调试信息的可执行程序运行得更慢(一个普遍误解)。尽管可调试的可执行程序占据更多的磁盘空间,可执行程序不会有更大的“内存使用量”,除非从GDB载入。相似的,除非你有GDB来运行调试可执行程序,否则它的载入时间也是近乎相同。

最后一点,我们可以在带有一个参数化的符号表的可执行程序上执行编译器优化。换句话说:gcc -g -O9 try1.c。事实上,GDB是少有的通常能很好调试被优化的可执行程序的符号调试器。然而,你通常应该在调试一个可执行程序前关闭优化,因为会有使GDB困惑的情况。变量可能因为优化而不存在,函数可能被内联,更多的可能或可能不困惑gdb的事情都会发生。为了安全起见,在调试一个程序时关闭优化。

给出下面的C代码try1.c:

  1. #include <stdio.h>
  2. static void display(int i, int *ptr);

  3. int main(void) {
  4.    int x = 5;
  5.     int *xptr = &x;
  6.     printf("In main():\n");
  7.    printf(" x is %d and is stored at %p.\n", x, &x);
  8.    printf(" xptr points to %p which holds %d.\n", xptr, *xptr);
  9.    display(x, xptr);
  10.    return 0;
  11. }

  12. void display(int z, int *zptr) {
  13.     printf("In display():\n");
  14.    printf(" z is %d and is stored at %p.\n", z, &z);
  15.    printf(" zptr points to %p which holds %d.\n", zptr, *zptr);
  16. }

用命令gcc -ggdb3 -O0 -o try1 try1.c来编译。
先查看try1的size:

$ ls -l try1
-rwxrwxr-x 1 tommy tommy 24752 2012-03-28 10:55 try1

size -A try1
try1  :
section               size        addr
.interp                 19   134512980
.note.ABI-tag           32   134513000
.note.gnu.build-id      36   134513032
.gnu.hash               32   134513068
.dynsym                 96   134513100
.dynstr                 81   134513196
.gnu.version            12   134513278
.gnu.version_r          32   134513292
.rel.dyn                 8   134513324
.rel.plt                32   134513332
.init                   46   134513364
.plt                    80   134513424
.text                  556   134513504
.fini                   26   134514060
.rodata                182   134514088
.eh_frame_hdr           60   134514272
.eh_frame              228   134514332
.ctors                   8   134520596
.dtors                   8   134520604
.jcr                     4   134520612
.dynamic               200   134520616
.got                     4   134520816
.got.plt                28   134520820
.data                    8   134520848
.bss                     8   134520856
.comment                42           0
.debug_aranges          32           0
.debug_info            228           0
.debug_abbrev          157           0
.debug_line            429           0
.debug_str             138           0
.debug_loc             112           0
.debug_macinfo       15956           0
Total                18920

使用命令strip --only-keep-debug try1来移除除debug符号之外的符号。再看下它的size:

$ ls -l try1
-rwxrwxr-x 1 tommy tommy 21060 2012-03-28 11:25 try1

$ size -A try1
try1  :
section               size        addr
.interp                 19   134512980
.note.ABI-tag           32   134513000
.note.gnu.build-id      36   134513032
.gnu.hash               32   134513068
.dynsym                 96   134513100
.dynstr                 81   134513196
.gnu.version            12   134513278
.gnu.version_r          32   134513292
.rel.dyn                 8   134513324
.rel.plt                32   134513332
.init                   46   134513364
.plt                    80   134513424
.text                  556   134513504
.fini                   26   134514060
.rodata                182   134514088
.eh_frame_hdr           60   134514272
.eh_frame              228   134514332
.ctors                   8   134520596
.dtors                   8   134520604
.jcr                     4   134520612
.dynamic               200   134520616
.got                     4   134520816
.got.plt                28   134520820
.data                    8   134520848
.bss                     8   134520856
.comment                42           0
.debug_aranges          32           0
.debug_info            228           0
.debug_abbrev          157           0
.debug_line            429           0
.debug_str             138           0
.debug_loc             112           0
.debug_macinfo       15956           0
Total                18920

如果用命令strip --strip-debug try1来移除调试符号,它的size为:

$ ls -l try1
-rwxrwxr-x 1 tommy tommy 7154 2012-03-28 11:25 try1

看下此时的段信息:

$ size -A try1
try1  :
section              size        addr
.interp                19   134512980
.note.ABI-tag          32   134513000
.note.gnu.build-id     36   134513032
.gnu.hash              32   134513068
.dynsym                96   134513100
.dynstr                81   134513196
.gnu.version           12   134513278
.gnu.version_r         32   134513292
.rel.dyn                8   134513324
.rel.plt               32   134513332
.init                  46   134513364
.plt                   80   134513424
.text                 556   134513504
.fini                  26   134514060
.rodata               182   134514088
.eh_frame_hdr          60   134514272
.eh_frame             228   134514332
.ctors                  8   134520596
.dtors                  8   134520604
.jcr                    4   134520612
.dynamic              200   134520616
.got                    4   134520816
.got.plt               28   134520820
.data                   8   134520848
.bss                    8   134520856
.comment               42           0
Total                1868

如果用命令strip --strip-all try1来移除所有符号,它的size为:

$ ll try1
-rwxrwxr-x 1 tommy tommy 5520 2012-03-28 11:38 try1*
它的段信息:

try1  :
section              size        addr
.interp                19   134512980
.note.ABI-tag          32   134513000
.note.gnu.build-id     36   134513032
.gnu.hash              32   134513068
.dynsym                96   134513100
.dynstr                81   134513196
.gnu.version           12   134513278
.gnu.version_r         32   134513292
.rel.dyn                8   134513324
.rel.plt               32   134513332
.init                  46   134513364
.plt                   80   134513424
.text                 556   134513504
.fini                  26   134514060
.rodata               182   134514088
.eh_frame_hdr          60   134514272
.eh_frame             228   134514332
.ctors                  8   134520596
.dtors                  8   134520604
.jcr                    4   134520612
.dynamic              200   134520616
.got                    4   134520816
.got.plt               28   134520820
.data                   8   134520848
.bss                    8   134520856
.comment               42           0
Total                1868

在移除了上面的部分后,程序仍可以正常运行。但是执行strip --remove-section=.text try1的话,程序无法运行,报出错误“段错误”。看看它此时的信息:

$ ll try1
-rwxrwxr-x 1 tommy tommy 5472 2012-03-28 11:42 try1*

$ size -A try1
try1  :
section              size        addr
.interp                19   134512980
.note.ABI-tag          32   134513000
.note.gnu.build-id     36   134513032
.gnu.hash              32   134513068
.dynsym                96   134513100
.dynstr                81   134513196
.gnu.version           12   134513278
.gnu.version_r         32   134513292
.rel.dyn                8   134513324
.rel.plt               32   134513332
.init                  46   134513364
.plt                   80   134513424
.fini                  26   134514060
.rodata               182   134514088
.eh_frame_hdr          60   134514272
.eh_frame             228   134514332
.ctors                  8   134520596
.dtors                  8   134520604
.jcr                    4   134520612
.dynamic              200   134520616
.got                    4   134520816
.got.plt               28   134520820
.data                   8   134520848
.bss                    8   134520856
.comment               42           0
Total                1312

可以看到移除.text段会连同debug信息一同移除。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值