GDB内存断点(Memory break)的使用举例

晨曦之光 发布于 2012/03/09 14:15
阅读 1K+
收藏 0

收藏!数据建模最全知识体系解读!>>>

本博客(http://blog.csdn.net/livelylittlefish)贴出作者(三二一@小鱼)相关研究、学习内容所做的笔记,欢迎广大朋友指正!

 

GDB内存断点(Memory break)的使用举例

     

    本文是一篇使用GDB设置内存断点的例子。

     

    1. 源程序

     

    文件名:testMemBreak.c

    #include <stdio.h>

    #include <string.h>

     

    int main()

    {

        int i,j;

        char buf[256]={0};

        char* pp = buf;

     

        printf("buf addr= 0x%x/r/n",buf);

        for(i=0;i<16;i++)

        {

            printf("addr = 0x%x ~ 0x%x/r/n",pp+i*16,pp+i*16+15);

            for(j=0;j<16;j++)

                *(pp+i*16+j)=i*16+j;

        }

     

        printf("ASCII table:/n");

        for(i=0;i<16;i++)

        {

            for(j=0;j<16;j++)

                printf("%c  ", *(pp+i*16+j));

            printf("/n");

        }

       

        return 0;

     

    }

     

    即完成ASCII码的初始化并打印出来。

     

    要使用的GDB命令,如下。

    (gdb) help watch

    Set a watchpoint for an expression.

    A watchpoint stops execution of your program whenever the value of

    an expression changes.

    (gdb) help rwatch

    Set a read watchpoint for an expression.

    A watchpoint stops execution of your program whenever the value of

    an expression is read.

    (gdb) help awatch

    Set a watchpoint for an expression.

    A watchpoint stops execution of your program whenever the value of

    an expression is either read or written.

    (gdb)

     

    2. 调试过程

     

    2.1 设置断点并启动程序完成初始化

     

    启动程序对其进行初始化,并使用display自动显示buf的地址。

     

    $ gcc -g -o membreak testMemBreak.c

     

    $ gdb ./membreak.exe

    GNU gdb 6.3.50_2004-12-28-cvs (cygwin-special)

    Copyright 2004 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 "i686-pc-cygwin"...

    (gdb) l

    1       #include <stdio.h>

    2       #include <string.h>

    3

    4       int main()

    5       {

    6           int i,j;

    7           char buf[256]={0};

    8           char* pp = buf;

    9

    10          printf("buf addr= 0x%x/r/n",buf);

    (gdb)

    11          for(i=0;i<16;i++)

    12          {

    13              printf("addr = 0x%x ~ 0x%x/r/n",pp+i*16,pp+i*16+15);

    14              for(j=0;j<16;j++)

    15                  *(pp+i*16+j)=i*16+j;

    16          }

    17

    18          printf("ASCII table:/n");

    19          for(i=0;i<16;i++)

    20          {

    (gdb)

    21              for(j=0;j<16;j++)

    22                  printf("%c  ", *(pp+i*16+j));

    23              printf("/n");

    24          }

    25

    26          return 0;

    27      }

    (gdb) b 10

    Breakpoint 1 at 0x4010ae: file testMemBreak.c, line 10.

    (gdb) r

    Starting program: /cygdrive/e/study/programming/linux/2009-12-28 testMemBreak/membreak.exe

     

    Breakpoint 1, main () at testMemBreak.c:10

    10          printf("buf addr= 0x%x/r/n",buf);

    (gdb) step

    buf addr= 0x22cb70

    11          for(i=0;i<16;i++)

    (gdb) p buf

    $1 = '/0' <repeats 255 times>

    (gdb) p &buf

    $2 = (char (*)[256]) 0x22cb70

    (gdb) display &buf

    1: &buf = (char (*)[256]) 0x22cb70

    (gdb) p/x *0x22cb70@64

    $3 = {0x0 <repeats 64 times>}

    (gdb) x/64w 0x22cb70

    0x22cb70:       0x00000000      0x00000000      0x00000000      0x00000000

    0x22cb80:       0x00000000      0x00000000      0x00000000      0x00000000

    0x22cb90:       0x00000000      0x00000000      0x00000000      0x00000000

    0x22cba0:       0x00000000      0x00000000      0x00000000      0x00000000

    0x22cbb0:       0x00000000      0x00000000      0x00000000      0x00000000

    0x22cbc0:       0x00000000      0x00000000      0x00000000      0x00000000

    0x22cbd0:       0x00000000      0x00000000      0x00000000      0x00000000

    0x22cbe0:       0x00000000      0x00000000      0x00000000      0x00000000

    0x22cbf0:       0x00000000      0x00000000      0x00000000      0x00000000

    0x22cc00:       0x00000000      0x00000000      0x00000000      0x00000000

    0x22cc10:       0x00000000      0x00000000      0x00000000      0x00000000

    0x22cc20:       0x00000000      0x00000000      0x00000000      0x00000000

    0x22cc30:       0x00000000      0x00000000      0x00000000      0x00000000

    0x22cc40:       0x00000000      0x00000000      0x00000000      0x00000000

    0x22cc50:       0x00000000      0x00000000      0x00000000      0x00000000

    0x22cc60:       0x00000000      0x00000000      0x00000000      0x00000000

     

    p/x *0x22cb70@64:以16进制方式显示0x22cb70开始的64个双字组成的数组,实际上就是256个字节的数组,只是默认以双字显示。

    可以看见,buf内存块中的所有数据被初始化为

     

    2.2 buf+80处设置内存断点

     

    设置断点后,运行程序,使之停在对该内存写的动作上。

    (gdb) watch *(int*)0x22cbc0

    Hardware watchpoint 2: *(int *) 2280384

    (gdb) c

    Continuing.

    addr = 0x22cb70 ~ 0x22cb7f

    addr = 0x22cb80 ~ 0x22cb8f

    addr = 0x22cb90 ~ 0x22cb9f

    addr = 0x22cba0 ~ 0x22cbaf

    addr = 0x22cbb0 ~ 0x22cbbf

    addr = 0x22cbc0 ~ 0x22cbcf

    Hardware watchpoint 2: *(int *) 2280384

     

    Old value = 0

    New value = 80

    main () at testMemBreak.c:14

    14              for(j=0;j<16;j++)

    1: &buf = (char (*)[256]) 0x22cb70

    (gdb) p i

    $4 = 5

    (gdb) p j

    $5 = 0

    (gdb) info breakpoints

    Num Type           Disp Enb Address    What

    1   breakpoint     keep y   0x004010ae in main at testMemBreak.c:10

            breakpoint already hit 1 time

    2   hw watchpoint  keep y              *(int *) 2280384

            breakpoint already hit 1 time

    (gdb) delete 1

    (gdb) delete 2

    (gdb) b 18

    Breakpoint 3 at 0x40113b: file testMemBreak.c, line 18.

    (gdb) info breakpoints

    Num Type           Disp Enb Address    What

    3   breakpoint     keep y   0x0040113b in main at testMemBreak.c:18

    (gdb) p/x *0x22cb70@64

    $6 = {0x3020100, 0x7060504, 0xb0a0908, 0xf0e0d0c, 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c, 0x23222120,

      0x27262524, 0x2b2a2928, 0x2f2e2d2c, 0x33323130, 0x37363534, 0x3b3a3938, 0x3f3e3d3c, 0x43424140, 0x47464544,

      0x4b4a4948, 0x4f4e4d4c, 0x50, 0x0 <repeats 43 times>}

    (gdb) x/64w 0x22cb70

    0x22cb70:       0x03020100      0x07060504      0x0b0a0908      0x0f0e0d0c

    0x22cb80:       0x13121110      0x17161514      0x1b1a1918      0x1f1e1d1c

    0x22cb90:       0x23222120      0x27262524      0x2b2a2928      0x2f2e2d2c

    0x22cba0:       0x33323130      0x37363534      0x3b3a3938      0x3f3e3d3c

    0x22cbb0:       0x43424140      0x47464544      0x4b4a4948      0x4f4e4d4c

    0x22cbc0:       0x00000050      0x00000000      0x00000000      0x00000000

    0x22cbd0:       0x00000000      0x00000000      0x00000000      0x00000000

    0x22cbe0:       0x00000000      0x00000000      0x00000000      0x00000000

    0x22cbf0:       0x00000000      0x00000000      0x00000000      0x00000000

    0x22cc00:       0x00000000      0x00000000      0x00000000      0x00000000

    0x22cc10:       0x00000000      0x00000000      0x00000000      0x00000000

    0x22cc20:       0x00000000      0x00000000      0x00000000      0x00000000

    0x22cc30:       0x00000000      0x00000000      0x00000000      0x00000000

    0x22cc40:       0x00000000      0x00000000      0x00000000      0x00000000

    0x22cc50:       0x00000000      0x00000000      0x00000000      0x00000000

    0x22cc60:       0x00000000      0x00000000      0x00000000      0x00000000

     

    查看buf内存块,可以看见,程序按我们希望的在运行,并在buf+80处停住。此时,程序正试图向该单元即0x22cbc0写入80

     

    2.3 使用continue执行程序直至结束

     

    (gdb) c

    Continuing.

    addr = 0x22cbd0 ~ 0x22cbdf

    addr = 0x22cbe0 ~ 0x22cbef

    addr = 0x22cbf0 ~ 0x22cbff

    addr = 0x22cc00 ~ 0x22cc0f

    addr = 0x22cc10 ~ 0x22cc1f

    addr = 0x22cc20 ~ 0x22cc2f

    addr = 0x22cc30 ~ 0x22cc3f

    addr = 0x22cc40 ~ 0x22cc4f

    addr = 0x22cc50 ~ 0x22cc5f

    addr = 0x22cc60 ~ 0x22cc6f

     

    Breakpoint 3, main () at testMemBreak.c:18

    18          printf("ASCII table:/n");

    1: &buf = (char (*)[256]) 0x22cb70

    (gdb) p/x *0x22cb70@64

    $7 = {0x3020100, 0x7060504, 0xb0a0908, 0xf0e0d0c, 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c, 0x23222120,

      0x27262524, 0x2b2a2928, 0x2f2e2d2c, 0x33323130, 0x37363534, 0x3b3a3938, 0x3f3e3d3c, 0x43424140, 0x47464544,

      0x4b4a4948, 0x4f4e4d4c, 0x53525150, 0x57565554, 0x5b5a5958, 0x5f5e5d5c, 0x63626160, 0x67666564, 0x6b6a6968,

      0x6f6e6d6c, 0x73727170, 0x77767574, 0x7b7a7978, 0x7f7e7d7c, 0x83828180, 0x87868584, 0x8b8a8988, 0x8f8e8d8c,

      0x93929190, 0x97969594, 0x9b9a9998, 0x9f9e9d9c, 0xa3a2a1a0, 0xa7a6a5a4, 0xabaaa9a8, 0xafaeadac, 0xb3b2b1b0,

      0xb7b6b5b4, 0xbbbab9b8, 0xbfbebdbc, 0xc3c2c1c0, 0xc7c6c5c4, 0xcbcac9c8, 0xcfcecdcc, 0xd3d2d1d0, 0xd7d6d5d4,

      0xdbdad9d8, 0xdfdedddc, 0xe3e2e1e0, 0xe7e6e5e4, 0xebeae9e8, 0xefeeedec, 0xf3f2f1f0, 0xf7f6f5f4, 0xfbfaf9f8,

      0xfffefdfc}

    (gdb) x/64w 0x22cb70

    0x22cb70:       0x03020100      0x07060504      0x0b0a0908      0x0f0e0d0c

    0x22cb80:       0x13121110      0x17161514      0x1b1a1918      0x1f1e1d1c

    0x22cb90:       0x23222120      0x27262524      0x2b2a2928      0x2f2e2d2c

    0x22cba0:       0x33323130      0x37363534      0x3b3a3938      0x3f3e3d3c

    0x22cbb0:       0x43424140      0x47464544      0x4b4a4948      0x4f4e4d4c

    0x22cbc0:       0x53525150      0x57565554      0x5b5a5958      0x5f5e5d5c

    0x22cbd0:       0x63626160      0x67666564      0x6b6a6968      0x6f6e6d6c

    0x22cbe0:       0x73727170      0x77767574      0x7b7a7978      0x7f7e7d7c

    0x22cbf0:       0x83828180      0x87868584      0x8b8a8988      0x8f8e8d8c

    0x22cc00:       0x93929190      0x97969594      0x9b9a9998      0x9f9e9d9c

    0x22cc10:       0xa3a2a1a0      0xa7a6a5a4      0xabaaa9a8      0xafaeadac

    0x22cc20:       0xb3b2b1b0      0xb7b6b5b4      0xbbbab9b8      0xbfbebdbc

    0x22cc30:       0xc3c2c1c0      0xc7c6c5c4      0xcbcac9c8      0xcfcecdcc

    0x22cc40:       0xd3d2d1d0      0xd7d6d5d4      0xdbdad9d8      0xdfdedddc

    0x22cc50:       0xe3e2e1e0      0xe7e6e5e4      0xebeae9e8      0xefeeedec

    0x22cc60:       0xf3f2f1f0      0xf7f6f5f4      0xfbfaf9f8      0xfffefdfc

    (gdb) c

    Continuing.

    ASCII table:

                 

       

                                

       !  "  #  $  %  &  '  (  )  *  +  ,  -  .  /

      1  2  3  4  5  6  7  8  9  :  ;  <  =  >  ?

    @  A  B  C  D  E  F  G  H  I  J  K  L  M  N  O

    P  Q  R  S  T  U  V  W  X  Y  Z  [  /  ]  ^  _

    `  a  b  c  d  e  f  g  h  i  j  k  l  m  n  o

    p  q  r  s  t  u  v  w  x  y  z  {  |  }  ~  

      ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 

     

    Program exited normally.

    (gdb)

     

    至此,我们已经看到watch查看内存的作用了,只要被查看的单元会被修改(读/写),均会断在此处,以方便我们调试程序。


原文链接:http://blog.csdn.net/livelylittlefish/article/details/5110234
加载中
返回顶部
顶部