gdb篇
转自:http://www.cnblogs.com/ypchenry/p/3668572.html
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[0];
};
struct fool{
struct foo *henry;
};
int main()
{
struct fool test={0};
if(test.henry->a)
printf("%x\n",test.henry->a);
return 0;
}
程序2:
#include <stdio.h>
struct foo{
int i;
char *a;
};
struct fool{
struct foo *henry;
};
int main()
{
struct fool test={0};
if(test.henry->a)
printf("%x\n",test.henry->a);
return 0;
}
第一个程序不会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.4340
GNU gdb (GDB) Fedora 7.6.50.20130731-19.fc20
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 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 4340]
Missing separate debuginfo for the main executable file
Try: yum --enablerepo='*debug*' install /usr/lib/debug/.build-id/73/a4410588cf88e43ecdfa6825cd15160aa6ddc7
Core was generated by `./struct_dump1'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x0000000000400544 in ?? ()
(gdb) file struct_dump1
Reading symbols from /home/henry/code/core/struct_dump1...done.
(gdb) bt
#0 0x0000000000400544 in main () at struct_dump1.c:12
(gdb) disassemble main
Dump of assembler code for function main:
0x0000000000400530 <+0>: push %rbp
0x0000000000400531 <+1>: mov %rsp,%rbp
0x0000000000400534 <+4>: sub $0x10,%rsp
0x0000000000400538 <+8>: movq $0x0,-0x10(%rbp)
0x0000000000400540 <+16>: mov -0x10(%rbp),%rax
=> 0x0000000000400544 <+20>: mov 0x8(%rax),%rax
0x0000000000400548 <+24>: test %rax,%rax
0x000000000040054b <+27>: je 0x400567 <main+55>
0x000000000040054d <+29>: mov -0x10(%rbp),%rax
0x0000000000400551 <+33>: mov 0x8(%rax),%rax
0x0000000000400555 <+37>: mov %rax,%rsi
0x0000000000400558 <+40>: mov $0x400600,%edi
0x000000000040055d <+45>: mov $0x0,%eax
0x0000000000400562 <+50>: callq 0x400410 <printf@plt>
0x0000000000400567 <+55>: mov $0x0,%eax
0x000000000040056c <+60>: leaveq
0x000000000040056d <+61>: 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 0;
} 下面是用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-19.fc20
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 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
1 #define NULL (void*)0
2 int main()
3 {
4 int *p1 = NULL;
5 int *p2 = NULL;
6 int *p3 = NULL;
7 return 0;
8 }
(gdb) b 7
Breakpoint 1 at 0x40050c: file null_point_test.c, line 7.
(gdb) r
Starting program: /home/henry/code/core/null_point_test Breakpoint 1, main () at null_point_test.c:7
7 return 0;
Missing separate debuginfos, use: debuginfo-install glibc-2.18-12.fc20.x86_64
(gdb) p &p1
$1 = (int **) 0x7fffffffdf08
(gdb) p &p2
$2 = (int **) 0x7fffffffdf00
(gdb) p &p3
$3 = (int **) 0x7fffffffdef8
(gdb) p &p1
$4 = (int *) 0x0
(gdb) p &p2
$5 = (int *) 0x0
(gdb) p &p3
$6 = (int *) 0x0
(gdb) bt
#0 main () at null_point_test.c:7
(gdb) p main
$4 = {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篇的更多相关文章
- 我的日常工具——gdb篇
我的日常工具——gdb篇 03 Apr 2014 1.gdb的原理 熟悉linux的同学面试官会问你用过gdb么?那好用过,知道gdb是怎么工作的么?然后直接傻眼... gdb是怎么接管一个进程?并且 ...
- TGL站长关于常见问题的回复
问题地址: http://www.thegrouplet.com/thread-112923-1-1.html 问题: 网站配有太多的模板是否影响网站加载速度 月光答复: wp不需要删除其他的模板,不 ...
- 《gdb调试之基础篇》
<gdb调试之基础篇> http://blog.csdn.net/miss_acha/article/details/42346543
- gdb调试coredump(使用篇)
gdb调试coredump(使用篇) 看到一个非常好的介绍coredump的文章,做个记录, 参考链接: https://blog.csdn.net/sunxiaopengsun/article/de ...
- GDB调试增强篇
GDB中应该知道的几个调试方法 七.八年前写过一篇<用GDB调试程序>, 于是,从那以后,很多朋友在MSN上以及给我发邮件询问我关于GDB的问题,一直到今天,还有人在问GDB的相关问题.这 ...
- GDB 入门篇
调试流程:(使用gcc编译时加上 -g -Wall选项)gdb attach pidinfo bb filename:linenum / b filename:functionnamecp varia ...
- GDB调试技巧:总结篇
目录 一 写在开头 1.1 本文内容 二 学习资料 三 常用命令 四 调试技巧 注:原创不易,转载请务必注明原作者和出处,感谢支持! 一 写在开头 1.1 本文内容 总结GDB调试的一些常用命令和调试 ...
- C++雾中风景番外篇3:GDB与Valgrind ,调试代码内存的工具
写 C++的同学想必有太多和内存打交道的血泪经验了,常常被 C++的内存问题搅的焦头烂额.(写 core 的经验了)有很多同学一见到 core 就两眼一抹黑,不知所措了.笔者 入"坑&quo ...
- 破解SQLServer for Linux预览版的3.5GB内存限制 (RHEL篇)
微软发布了SQLServer for Linux,但是安装竟然需要3.5GB内存,这让大部分云主机用户都没办法尝试这个新东西 这篇我将讲解如何破解这个内存限制 要看关键的可以直接跳到第6步,只需要替换 ...
随机推荐
- 安装solaris_11.2与windows双系统(VM10模拟实现)(一)
感慨:这周刚接触solaris,装solaris很蛋疼,一个字:慢! 在上面安装软件包依然很慢,无线网也很不稳定. 在上面搭建环境更蛋疼,一个字:惨! 什么环境之类的废话就不多说了,一般的电脑都可以. ...
- windows设置临时环境变量path
所有在命令行下对环境变量的修改只对当前窗口有效,不是永久性的修改. 1.查看当前所有可以的环境变量:输入set查看 2.查看某个环境变量:输入 set 变量名 例如 set path 3.修改环境变量 ...
- C++_const
//const在C不可以初始化数组 //const在C++可以用来初始化数组 #include <iostream> using namespace std; void main() { ...
- 前端web应用组件化(一) 徐飞
https://github.com/xufei/blog/issues/6 Web应用的组件化(一) 基本思路 1. 为什么要做组件化? 无论前端也好,后端也好,都是整个软件体系的一部分.软件产品也 ...
- 20140613_JavaWeb学习之开发环境配置篇
本文所使用软件百度云盘网址:http://pan.baidu.com/s/1kTDRFwz 1安装JDK 操作系统:windows7-64bit 版本号:jdk-7u51-windows-x64 安装 ...
- 通过案例掌握Spring 管理事务的步骤及配置
案例描述 通过完成生成订单业务,掌握事务处理. 需要d_order表和d_item表 订单生成时的业务逻辑:向d_order插入1条数据的同时,向t_item中插入若干条数据 这就是一个独立的 ...
- Powerdesigner逆向工程从sql server数据库生成pdm
第一步:打开"控制面板"中的"管理工具" 第二步:点击"管理工具"然后双击"数据源(odbc)" 第三步:打开之后,点击 ...
- MySQL学习笔记(2)
打开数据库 USE db_name; SELECT DATABASE();查看当前所选中的数据库 创建数据表 CREATA TABLE [IF NOT EXISTS] table_name ( col ...
- WCF---服务发布的步骤
服务发布的步骤: 1.打开你的VS2012网站项目,右键点击项目>菜单中 重新生成一下网站项目:再次点击右键>发布: 2.弹出网站发布设置面板,点击<新建..>,创建新的发布配 ...
- 菜鸟初试水--JQuery基础
此文仅作入门级文章,望大神们高抬贵手! JQuery: 它是一套跨浏览器的JavaScript库,简化HTML与JavaScript之间的操作. JQuery的用途: ①访问和操作DOM元素: 使用j ...