Linux GDB调试 学习记录.docx
- 文档编号:27283349
- 上传时间:2023-06-28
- 格式:DOCX
- 页数:14
- 大小:18.50KB
Linux GDB调试 学习记录.docx
《Linux GDB调试 学习记录.docx》由会员分享,可在线阅读,更多相关《Linux GDB调试 学习记录.docx(14页珍藏版)》请在冰豆网上搜索。
LinuxGDB调试学习记录
gdbrecord
[root@localhosttest_gdb]#ll
total4
-rw-r--r--1rootroot121Oct 902:
33helloworld.c
[root@localhosttest_gdb]#gcc-Ehelloworld.c-ohelloworld.i
[root@localhosttest_gdb]#ll
total44
-rw-r--r--1rootroot 121Oct 902:
33helloworld.c
-rw-r--r--1rootroot40016Oct2320:
06helloworld.i
[root@localhosttest_gdb]#gcc-Shelloworld.i
[root@localhosttest_gdb]#ll
total48
-rw-r--r--1rootroot 121Oct 902:
33helloworld.c
-rw-r--r--1rootroot40016Oct2320:
06helloworld.i
-rw-r--r--1rootroot 449Oct2320:
08helloworld.s
[root@localhosttest_gdb]#gcc-Shelloworld.i-ohelloworld.s
[root@localhosttest_gdb]#ll
total48
-rw-r--r--1rootroot 121Oct 902:
33helloworld.c
-rw-r--r--1rootroot40016Oct2320:
06helloworld.i
-rw-r--r--1rootroot 449Oct2320:
09helloworld.s
[root@localhosttest_gdb]#gcc-chelloworld.s
[root@localhosttest_gdb]#ll
total52
-rw-r--r--1rootroot 121Oct 902:
33helloworld.c
-rw-r--r--1rootroot40016Oct2320:
06helloworld.i
-rw-r--r--1rootroot 876Oct2320:
10helloworld.o
-rw-r--r--1rootroot 449Oct2320:
09helloworld.s
[root@localhosttest_gdb]#gcc-chelloworld.s-ohelloworld.o
[root@localhosttest_gdb]#ll
total52
-rw-r--r--1rootroot 121Oct 902:
33helloworld.c
-rw-r--r--1rootroot40016Oct2320:
06helloworld.i
-rw-r--r--1rootroot 876Oct2320:
10helloworld.o
-rw-r--r--1rootroot 449Oct2320:
09helloworld.s
每天学点GDB1
在Linux环境下进行C或是C++编程,调试工具首选GDB。
GDB的功能很多,一下子全弄明白似乎不太可能。
那么就从最简单的使用说起吧。
一谈起简单,Helloworld就成了最佳的选择了。
复制代码
1#include
2#include
3
4intmain(intargc,char**argv){
5 printf("hello,world\n");
6 return0;
7}
复制代码
编译链接
gcc-ohello-ghelloworld.c
-g可以生成调试信息供gdb使用
好了,现在可执行目标文件hello已经生成,接下来的事情就是用gdb将其载入并运行。
gdb./hello
接下来的会看到如下的信息。
gdbhello
GNUgdb(GDB)7.5.1
Copyright(C)2012FreeSoftwareFoundation,Inc.
LicenseGPLv3+:
GNUGPLversion3orlater //gnu.org/licenses/gpl.html> Thisisfreesoftware: youarefreetochangeandredistributeit. ThereisNOWARRANTY,totheextentpermittedbylaw. Type"showcopying" and"showwarranty"fordetails. ThisGDBwasconfiguredas"x86_64-unknown-linux-gnu". Forbugreportinginstructions,pleasesee: //www.gnu.org/software/gdb/bugs/>... Readingsymbolsfrom/tmp/hello...done. (gdb) 显示源代码 (gdb)list1,10 1 #include 2 #include 3 4 intmain(intargc,char**argv){ 5 printf("hello,world\n"); 6 return0; 7 } 设置断点有多种方法,如通过函数名,通过指定源码行数,下面的例子通过指定文件中的行数来设置断点 (gdb)break7 运行程序 (gdb)run Startingprogram: /test/test_gdb/hello hello,world1 Breakpoint1,main()athelloworld.c: 8 8 return0; 当检查完相关的变量后,继续运行程序 (gdb)pi $1=1 (gdb)continue 最终,退出gdb (gdb)quit ok,重新回到bashshell. 每天学点GDB2 在一中提到GDB最最基本的用法,在本节主要讲述一下如何让GDB在断点处打印一下诊断信息,但程序执行本身不会中断。 先稍微改一改源程序 #include #include intmain(intargc,char**argv){ inti=0; printf("hello,world\n"); for(i=0;i<20;i++){ printf("now,theseqis%d\n",i); } return0; } 假设要在执行期间查看i值的变化。 如果是stepbystep的办法,具体步骤如下。 设置断点 gdb)break8 执行程序 gdb)run 在断点处停止执行,执行如下指令显示i的值 gdb)pi 继续程序执行 gdb)continue 上述步骤会一直重复出现,如果想一次性设定后,让程序执行不因断点设置而中断,可采用下述办法。 gdb)commands Typecommandsforbreakpoint(s)1,oneperline. Endwithalinesayingjust"end". >silent >pi >conti >end 输入end表示在断点处的批处理结束,再次回到gdb。 pi表示指印i的值 conti表示继续程序执行 gdb)run 这样每次在断点处会自动打印变量i的值,并继续执行剩下的程序。 hello,world $2=0 now,theseqis0 $3=1 now,theseqis1 $4=2 now,theseqis2 $5=3 now,theseqis3 $6=4 now,theseqis4 $7=5 now,theseqis5 $8=6 now,theseqis6 $9=7 now,theseqis7 $10=8 now,theseqis8 $11=9 now,theseqis9 $12=10 now,theseqis10 $13=11 now,theseqis11 $14=12 now,theseqis12 $15=13 now,theseqis13 $16=14 now,theseqis14 $17=15 now,theseqis15 $18=16 now,theseqis16 $19=17 now,theseqis17 $20=18 now,theseqis18 $21=19 now,theseqis19 Programexitednormally. 每天学点GDB4 本节侧重于如何用各种方法查看变量的值。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include #include voidshow_slogan(char*slogan); intcounter; char*welcome_msg="youarewelcome! "; intmain(intargc,char**argv){ inti=0; counter=0; show_slogan(welcome_msg); return0; } voidshow_slogan(char*slogan){ printf("%s\n",slogan); counter++; printf("you' 编译 gcc-otest-gtest.c 启动gdb gdbtest gdb)br10 gdb)r 程序运行至断点1,即行10 显示局部变量的值 gdb)infoloal i=10 打印i的地址 gdb)p&i $1=(int*)0x7fffffffe7cc 因为作者当前是64位cpu,故显示为64位指针 有了指针,就可以使用大杀器"x" 多费一句话,在gdb中,查看内存中到底放置了哪些东西关键的关键就是要学会使用x并理解其输出内容中的具体含义。 gdb)x0x7fffffffe7cc 显示当前指针中包含的值,与pi的效果相同。 如果上述i的例子不能让你有较深印象的话,那么就用welcome_msg来说明问题中。 gdb)pwelcome_msg $5=0x400664"youarewelcome! " 现在有了welcome_msg的指针,有x来打印内容 gdb)x/s0x400664 0x400664: "youarewelcome! " 想到byte级别,好的使用修饰符c gdb)x/16c0x400664 0x400664: 121'y'111'o'117'u'32''97'a'114'r'101'e'32'' 0x40066c: 119'w'101'e'108'l'99'c' 111'o'109'm'101'e'33'! 想来welcome_msg的例子可以让你切身体会到x的强大之处。 x后可以跟多种修饰符 显示x的帮助信息 gdb)helpx 好了,今天的主要内容就是介绍赫赫有名的x.用好x就可以让内存中的内容无所遁形。 每天学点GDB5 GDB提供了强大的反汇编能力,本节就围绕于该主题而展开。 继续以Hello.c为例。 1 2 3 4 5 6 7 #include #include intmain(intargc,char**argv){ printf("hello,world\n"); return0; } 编译生成可执行文件 gcc-ohello-ghello.c 用gdb载入进行调试 gdbhello 反汇编main函数 disassemblemain 以下为输出内容 Dumpofassemblercodeforfunctionmain: 0x080483fc<+0>: push %ebp 0x080483fd<+1>: mov %esp,%ebp 0x080483ff<+3>: and $0xfffffff0,%esp 0x08048402<+6>: sub $0x10,%esp 0x08048405<+9>: movl $0x80484b0,(%esp) 0x0804840c<+16>: call 0x80482d0 0x08048411<+21>: mov $0x0,%eax 0x08048416<+26>: leave 0x08048417<+27>: ret Endofassemblerdump. 如果留心的话,可能发现在main函数中调用的printf并没有在反汇编中出现。 原因在于printf其实使用的是puts。 如果已经知道了地址,想反过来查看是否对应为某一个函数的话,可以使用infosymbol指令 infosymbol0x80482d0 输出为 puts@pltinsection.plt 说明地址0x80482d0对应于函数puts 与infosymbol相对的指令为infoaddress,可以通过名称获得其地址。 继续为Puts为例 infoaddrputs 输出为 Symbol"puts"isat0x80482d0inafilecompiledwithoutdebugging. 反汇编的另外一种方法就是使用x,当程序执行后(注意一定是程序运行后,停在断点处时),可以使用如下指令 x/3i$pc 每天学点GDB6 今天探讨的话题是“helloworld最先是从main函数开始执行的么”。 复制代码 1#include 2#include 3 4intmain(intargc,char**argv){ 5 printf("hello,world\n"); 6 return0; 7} 复制代码 一个最简单的程序,简单到任何人都能信手写来。 如果静下来仔细想想,这个程序是如何执行的时候,总会有一些小小的疑惑。 那么用之前的GDB知识来看看这个执行过程吧。 gdb)br5 gdb)r gdb)bt 显示调用堆栈 gdb)bt #0 main(argc=1,argv=0x7fffffffe918)athello.c: 5 进一步显示frame的信息 复制代码 gdb)infoframe Stacklevel0,frameat0x7fffffffe840: rip=0x40050finmain(hello.c: 5);savedrip0x7ffff7a4fa15 sourcelanguagec. Arglistat0x7fffffffe830,args: argc=1,argv=0x7fffffffe918 Localsat0x7fffffffe830,Previousframe'sspis0x7fffffffe840 Savedregisters: rbpat0x7fffffffe830,ripat0x7fffffffe838 复制代码 注意两个register的值,分别是保存的rbp和rip.savedrip表示main被调用前的代码。 可以用x来看看具体的函数名称 (gdb)x0x7ffff7a4fa15 0x7ffff7a4fa15<__libc_start_main+245>: 0xb4e8c789 或者利用另一种方法 infosymbol0x7ffff7a4fa15 __libc_start_main+245insection.textof/usr/lib/libc.so.6 至此,可断定main函数被__libc_start_main调用。 如果到这还不尽兴的话,可以用如下指令来看看__libc_start_main中有哪些内容,或者直接去下载glibc源码。 gdb)disassemble __libc_start_main
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Linux GDB调试 学习记录 GDB 调试 学习 记录