分类: LINUX
2010-07-25 22:29:00
本博客(http://blog.csdn.net/livelylittlefish) 贴出作者(三二一@小鱼)相关研究、学习内容所做的笔记,欢迎广大朋友指正!
GDB内存断点(Memory break)的使用举例
本文是一篇使用GDB设置内存断点的例子。
1. 源程序
文件名:testMemBreak.c
#include #include
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
2 #include
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' (gdb) p &buf $2 = (char (*)[256]) 0x22cb70 (gdb) display &buf 1: &buf = (char (*)[256]) 0x22cb70 (gdb) p/x *0x22cb70@64 $3 = {0x0 (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内存块中的所有数据被初始化为0。
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 (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:
! " # $ % & ' ( ) * + , - . / 0 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查看内存的作用了,只要被查看的单元会被修改(读/写),均会断在此处,以方便我们调试程序。