我的日常工具——gdb篇
我的日常工具——gdb篇
03 Apr 2014
1.gdb的原理
熟悉linux的同学面试官会问你用过gdb么?那好用过,知道gdb是怎么工作的么?然后直接傻眼。。。 gdb是怎么接管一个进程?并且能获取这个进程的变量、堆栈、寄存器、内存映像等信息的呢?还可以打断点执行?这些都是gdb一些基本的功能。 很简单,ptrace,好来看看manual上这个系统调用的定义。
- #include <sys/ptrace.h>
- long ptrace(enum __ptrace_request request, pid_t pid,void *addr,
- void *data);
简单描述: ptrace系统调用提供一种方法使某一父进程(叫做"tracer")可以观察并控制另外一个进程(叫做"tracee")的执行,而且还可以检查并改变执行tracee进程时的内存映像和寄存器。这个系统调用主要用来实现断点调试和函数调用跟踪( It is primarily used to implement breakpoint debugging and system call tracing)。
2.gdb将高级语言转成汇编
对于c、c++这样的语言,如果不注意内存释放经常会出现“野指针”、“空指针”等,程序dump掉的时候要找清楚那地方crash了,汇编指令显的非常重要。 比如:
程序1:
- #include <stdio.h>
- struct foo{
- int i;
- char a[];
- };
- struct fool{
- struct foo *henry;
- };
- int main()
- {
- struct fool test={};
- if(test.henry->a)
- printf("%x\n",test.henry->a);
- return ;
- }
程序2:
- #include <stdio.h>
- struct foo{
- int i;
- char *a;
- };
- struct fool{
- struct foo *henry;
- };
- int main()
- {
- struct fool test={};
- if(test.henry->a)
- printf("%x\n",test.henry->a);
- return ;
- }
第一个程序不会core dump,而第二个程序core dump掉了。原因在第12行程序1访问的a是数组的地址,而程序2访问的时指针a的内容,a为NULL
指针,访问其内容当然时非法的。你可能要问了,你为什么知道程序1访问的是地址而程序2访问的是内容呢? 那就需要汇编指令帮忙了。
题外话:程序2dump会产生core文件,如果没有出现core文件,用ulimit -c unlimited命令产生。
- [henry@localhost core]$ gdb -c core.
- GNU gdb (GDB) Fedora 7.6.50.20130731-.fc20
- Copyright (C) Free Software Foundation, Inc.
- License GPLv3+: GNU GPL version 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 "x86_64-redhat-linux-gnu".
- Type "show configuration" for configuration details.
- For bug reporting instructions, please see:
- <http://www.gnu.org/software/gdb/bugs/>.
- Find the GDB manual and other documentation resources online at:
- <http://www.gnu.org/software/gdb/documentation/>.
- For help, type "help".
- Type "apropos word" to search for commands related to "word".
- [New LWP ]
- Missing separate debuginfo for the main executable file
- Try: yum --enablerepo='*debug*' install /usr/lib/debug/.build-id//a4410588cf88e43ecdfa6825cd15160aa6ddc7
- Core was generated by `./struct_dump1'.
- Program terminated with signal SIGSEGV, Segmentation fault.
- # 0x0000000000400544 in ?? ()
- (gdb) file struct_dump1
- Reading symbols from /home/henry/code/core/struct_dump1...done.
- (gdb) bt
- # 0x0000000000400544 in main () at struct_dump1.c:
- (gdb) disassemble main
- Dump of assembler code for function main:
- 0x0000000000400530 <+>: push %rbp
- 0x0000000000400531 <+>: mov %rsp,%rbp
- 0x0000000000400534 <+>: sub $0x10,%rsp
- 0x0000000000400538 <+>: movq $0x0,-0x10(%rbp)
- 0x0000000000400540 <+>: mov -0x10(%rbp),%rax
- => 0x0000000000400544 <+>: mov 0x8(%rax),%rax
- 0x0000000000400548 <+>: test %rax,%rax
- 0x000000000040054b <+>: je 0x400567 <main+>
- 0x000000000040054d <+>: mov -0x10(%rbp),%rax
- 0x0000000000400551 <+>: mov 0x8(%rax),%rax
- 0x0000000000400555 <+>: mov %rax,%rsi
- 0x0000000000400558 <+>: mov $0x400600,%edi
- 0x000000000040055d <+>: mov $0x0,%eax
- 0x0000000000400562 <+>: callq 0x400410 <printf@plt>
- 0x0000000000400567 <+>: mov $0x0,%eax
- 0x000000000040056c <+>: leaveq
- 0x000000000040056d <+>: retq
- End of assembler dump.
上面看到程序执行时用bt提示程序在12行dump掉了,然后转换成汇编代码可以看到12行执行的时mov指令。
对于char a[0]来说,汇编代码用了lea指令,lea 0×8(%rax), %rax
对于char *a来说,汇编代码用了mov指令,mov 0×8(%rax), %rax
lea指令是把地址放进去,而mov是把内容放进去,而
NULL指针的内容是不能访问的。这就是前面提到的*a 和a[0]的不同。
1
ni
和si
是单步执行汇编命令,和next
与step
一样,n表示在当前函数一步步执行,s代表跟踪函数,可以从当前函数跳到另一个函数。 display
可以显示一些寄存器内容,如display /x $pc
显示程序计数器。 info reg
显示所有寄存器内容。
tips——关于NULL指针:
如果程序里有NULL指针,NULL指针会指向系统为程序分配的段地址的开始,系统为段开头64k做苛刻的规定。程序中(低访问权限)访问要求高访问权限的这64K内存被视作是不容许的,会引发Access Volitation 错误。64K内存是一块保留内存(即不能被程序动态内存分配器分配,不能被访问,也不能被使用),就是简单的保留,不作任何使用。2
下面的代码是对空指针的测试:
- #define NULL (void*)0
- int main()
- {
- int *p1 = NULL;
- int *p2 = NULL;
- int *p3 = NULL;
- return ;
- }
- 下面是用gdb测试:
- [henry@localhost core]$ gcc -g null_point_test.c -o null_point_test
- [henry@localhost core]$ gdb null_point_test
- GNU gdb (GDB) Fedora 7.6.50.20130731-.fc20
- Copyright (C) Free Software Foundation, Inc.
- License GPLv3+: GNU GPL version 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 "x86_64-redhat-linux-gnu".
- Type "show configuration" for configuration details.
- For bug reporting instructions, please see:
- <http://www.gnu.org/software/gdb/bugs/>.
- Find the GDB manual and other documentation resources online at:
- <http://www.gnu.org/software/gdb/documentation/>.
- For help, type "help".
- Type "apropos word" to search for commands related to "word".
- ..
- Reading symbols from /home/henry/code/core/null_point_test...done.
- (gdb) list
- #define NULL (void*)0
- int main()
- {
- int *p1 = NULL;
- int *p2 = NULL;
- int *p3 = NULL;
- return ;
- }
- (gdb) b
- Breakpoint at 0x40050c: file null_point_test.c, line .
- (gdb) r
- Starting program: /home/henry/code/core/null_point_test
- Breakpoint , main () at null_point_test.c:
- return ;
- Missing separate debuginfos, use: debuginfo-install glibc-2.18-.fc20.x86_64
- (gdb) p &p1
- $ = (int **) 0x7fffffffdf08
- (gdb) p &p2
- $ = (int **) 0x7fffffffdf00
- (gdb) p &p3
- $ = (int **) 0x7fffffffdef8
- (gdb) p &p1
- $ = (int *) 0x0
- (gdb) p &p2
- $ = (int *) 0x0
- (gdb) p &p3
- $ = (int *) 0x0
- (gdb) bt
- # main () at null_point_test.c:
- (gdb) p main
- $ = {int ()} 0x4004f0 <main>
- (gdb)
可以看出gdb测试结果p1 p2 p3的内容即null指针的地址都是
- (int *) 0x0
正如上面多说空指针指向段首,并且都指向一个内存单元,null指针只有一个。
3.gdb调试core文件
用gdb -c core文件
命令调试core文件,调试过程种可能会总是一堆问号的问题,用symbol-file core文件对应的bin文件
命令添加字符集即可。
4.gdb条件断点
已经有了断点break_num将其转化成条件断点:condition break_num(断点编号) cond(条件)
,当满足条件cond时,GDB才会在断点break_num处暂停程序的执行。
break break_num if cond(条件)
定义一个断点并使之成为条件断点。
tbreak break_num
临时断点,断点执行一次后此段点无效。
commands breakpoint_number
可以设置执行断点breakpoint_number时执行一段程序,有点批量执行的意思,以end结束。
引用:
我的日常工具——gdb篇的更多相关文章
- Linux工具参考篇(网摘)
Linux工具参考篇 原文出处:[Linux Tools Quick Tutorial] 1. gdb 调试利器 2. ldd 查看程序依赖库 3. lsof 一切皆文件 4. ps 进程查看器 5. ...
- 一些日常工具集合(C++代码片段)
一些日常工具集合(C++代码片段) ——工欲善其事,必先利其器 尽管不会松松松,但是至少维持一个比较小的常数还是比较好的 在此之前依然要保证算法的正确性以及代码的可写性 本文依然会持久更新,因为一次写 ...
- 打造程序员的高效生产力工具-mac篇
打造程序员的高效生产力工具-mac篇 1 概述 古语有云:“工欲善其事,必先利其器” [1] ,作为一个程序员,他最重要的生产资源是脑力知识,最重要的生产工具是什么?电脑. 在进行重要的脑力成果输 ...
- [转]Android开源项目第二篇——工具库篇
本文为那些不错的Android开源项目第二篇--开发工具库篇,主要介绍常用的开发库,包括依赖注入框架.图片缓存.网络相关.数据库ORM建模.Android公共库.Android 高版本向低版本兼容.多 ...
- Android开源项目第二篇——工具库篇
本文为那些不错的Android开源项目第二篇——开发工具库篇,**主要介绍常用的开发库,包括依赖注入框架.图片缓存.网络相关.数据库ORM建模.Android公共库.Android 高版本向低版本兼容 ...
- 第一篇:打造专属开发工具Eclipse篇
第一篇:打造专属开发工具Eclipse篇 eclipse 优化 1.动画很酷,但如果可以的话,我总是在所有的工具中禁用动画.所以classic或者window classic主题是我最常用的主题 , ...
- 开发-日常工具:TFS(Team Foundation Server)
ylbtech-开发-日常工具:TFS(Team Foundation Server) TFS(Team Foundation Server)是一个高可扩展.高可用.高性能.面向互联网服务的分布式文件 ...
- <JVM下篇:性能监控与调优篇>03-JVM监控及诊断工具-GUI篇
笔记来源:尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机) 同步更新:https://gitee.com/vectorx/NOTE_JVM https://codechina.cs ...
- javaSE中级篇2 — 工具类篇 — 更新完毕
1.工具类(也叫常用类)-- 指的是别人已经写好了的,我们只需要拿来用就行了 官网网址:Overview (Java Platform SE 8 ) (oracle.com) ---- 但是这个是英文 ...
随机推荐
- left join查询结果大于原始数据
left join onon后面一定是一个主键或者是一个值为唯一的字段吗 on后面关联的条件如果是1对1的数量就不变,如果是1对多的数量就会增加 追问: 问题就在这,我1对多了 追答: 通常的做法是 ...
- 2、Spring的LocalSessionFactoryBean创建过程源码分析
spring的LocalSessionFactoryBean生成过程与hibernate的SessionFactory生成过程是高度吻合的. 为了后面源码分析,首先讲解一个接口,一个类的功能:①.接口 ...
- Data Flow ->> Slow Changing Dimension
这里简单讲下SCD 在讲之前贴上两个有用的链接地址.作者的两篇文件讲解了SCD是什么以及应用 http://www.cnblogs.com/biwork/p/3363749.html http://w ...
- [转]C:int型指针
开源中国:http://my.oschina.net/lotte1699/blog/142538 网页快照:http://www.piaocafe.com/295977937/139381567037 ...
- poj1988-种类并查集
题意:有N个立方体(1<=N <=30,000),相应地初始时每个立方体放在一个栈中,有两种操作:1.M X Y:把包含第X个立方体的栈中的所有立方体当做一个整体拿出来压入包含第Y个立方体 ...
- php去除数组中重复数据
<?php /** * 去除数组中重复数据 * by www.jbxue.com **/ $input = array("a" => "green" ...
- centos chrome
在centos6.X和redhat enterprise 中安装chrome,我找了很久都不行,今天终于找到了可以用下脚本那安装: #! /bin/bash # Google Chrome Insta ...
- Android HTTPS(1)概念和简单示例
Security with HTTPS and SSL The Secure Sockets Layer (SSL)—now technically known as Transport Layer ...
- ViewPager的监听事件失效
主要是因为在我项目使用了PageIndicator,所以这个时候监听事件要写在PageIndicator上. mIndicator.setOnPageChangeListener(new OnPage ...
- many to one could not resolve property
今天在做一个功能的时候 遇到了.一个Could not resolve property 的问题. 配置文件如下: <many-to-one name="user" cla ...