Linux基础(03)gdb调试
1. 安装GDB增强工具 (gef)
* GDB的版本大于7.7
* wget -q -O- https://github.com/hugsy/gef/raw/master/scripts/gef.sh | sh
* 确保网络连通 并且成功更新ubuntu (更新source.list 使用apt-get update)
2. GDB安装插件(在root权限安装,用户权限使用不了需要在用户权限下安装)
git clone https://github.com/gatieme/GdbPlugins.git ~/GdbPlugins (安装gdb的Python脚本插件)
切换gdb模式 :
echo "source ~/GdbPlugins/peda/peda.py" > ~/.gdbinit (默认打开gdb插件是pada) 倾向于破解和逆向
echo "source ~/GdbPlugins/gef/gef.py" > ~/.gdbinit 倾向于debug 逆向
echo "source ~/GdbPlugins/gdbinit/gdbinit" > ~/.gdbinit 个人定制
3.Linux程序发布流程
* 确定程序是否存在符号表
readelf -s test-1
* 生成符号表
objcopy --only-keep-debug test-1 test-1.symbol
* 生成发布程序
objcopy --strip-debug test-1 test-release
* 使用符号表进行程序debug
gdb -q --symbol=test-1.symbol --exec=test-release
4.gdb语法的使用
set listsize num 设置 l 的显示行数
list/l (code/num) 查看某个函数代码或者查看某行代码. 查看其它文件的代码 l xxx.c:(code/num)
break/b num 打断点 条件断点 b num if var== 也可以断到某个函数上b func
continue/c 跳到下一个断点
disable num 使断点失效 enable num 使断点重新有效
run/r 运行程序
调试已运行的程序
info breakpoints 查看断点 delete/d num 删除断点列表的某个断点
print/p code 调试时打印某个变量的值 也可以选择打印的方式 如: p/d code 打印十进制的结果 p/s 打印字符串的结果
p var=100 修改内存
step/s 执行下一句代码有函数进入函数
next/n 执行下一句代码有函数也跳过
until/u 跳出当前循环
finish 退出当前函数
info locals 查看当前函数中的全部局部变量
bt 查看函数调用栈 如: 进入某个函数时bt一下可以知道哪个函数调用了当前进入的函数 或者 可以查看处在哪个函数中
info frame 打印当前栈里所以的信息
x &code 查看某个变量的内存地址
#观察点
watch var/add 观察内存是否被改变如果改变则自动断点
gdb就近原则 如果有变量重名 想查看任意函数内 的变量 watch func::var
info watchpoints 查看观察点列表
rwatch var/add 观察内存是否被读取如果被读取则断点
#设置捕捉点
catch event/throw
throw 抛出一个C++的异常 catch throw
catch 捕捉一个C++的异常 catch catch
exec 调用系统调用exev时停止 catch exec
exec 在一个进程中启动另外一个程序
fork 调用系统调用fork时停止 catch fork
load/load libname 载入动态链接库时 catch load / catch load libname
unload
#搜索源代码
search var/func 内存搜索 只有调用了函数或存在于内存才能搜索到
reverse-search var/func 全文搜索 不占用内存也能搜索只要在代码段
#查看内存
x/nfu
x 是 examine 的缩写
n表示要显示的内存单元的个数
f表示显示方式, 可取如下值
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
i 指令地址格式
c 按字符格式显示变量。
f 按浮点数格式显示变量。
u表示一个地址单元的长度
b表示单字节,
h表示双字节,
w表示四字节,
g表示八字节
十六进制两位数一个字节
如:x/3uh 0x80494a4 往后的三个无符号的十六进制只显示两个字节的地址
x/3uh 0x80494a4 1 0 16
x/3xh 0x80494a4 0x0001 0x0000 0x0010
查看数组地址 p*arr@len
#插入命令
在触发某些断点是执行插入的命令并不是真的在源代码上插入
conmades bnum
...
...
end
一般都是没有gef等脚本时使用的
##############################################################################
内存分段的概念: https://blog.csdn.net/zhy557/article/details/80832268
code: 代码域 , 程序的执行代码(所有的函数)都存放在这里
RO_data: 只读数据域 , 存放只读常量 ,如const和字符串
RW_data 可读写数据域: 存放初始化为 非0值 的可读写变量
ZI_data: 和RW_data的区别在于存放的都是初始化为 0 的变量
RO: 包括code和RO_data
当程序存储在ROM中时,所占用的大小为Code + RO_data + RW_data 。
当程序执行时, RW_data和 ZI_data在RAM中,RO_data和code视cpu架构(51、arm、x86)不同处于ROM或者RAM中。其中ZI_data对应了BSS段,RW_data对应数据段,code对应代码段, RO_data对应数据段。(RAM:随机存储内存 ; ROM只读内存)
############## 程序进程中的分区
相关概念:堆(heap),栈(stack),BSS段,数据段(data),代码段(code /text),全局静态区,文字常量区,程序代码区。
BSS段:BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。
数据段:数据段(data segment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。
代码段:代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。
堆(heap):堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)。
栈(stack):栈又称堆栈,用户存放程序临时创建的局部变量。在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的后进先出特点,所以栈特别方便用来保存/恢复调用现场。
全局静态区,文字常量区,程序代码区是从内存地址分配的角度来描述的。
全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。
文字常量区—常量字符串就是放在这里的。
程序代码区—存放函数体的二进制代码。
################################################################################
5.gdb多进程多线程调试
int main()
{
pid_t pid = fork();//创建子进程
if(pid == -)
{
perror("fork error");
return -;
}
else if(pid == )//child
{
printf("i am a child:my pid is %d,my father is%d\n",getpid(),getppid());
}
else//father
{
printf("i am a father:my pid is %d\n",getpid());
wait(NULL);//等待子进程
}
return ;
}
##################进程间是完全独立互不影响的但可以通信
fork创建一个完全和父进程一样的子进程,两个进程并行执行,执行先后随机看CPU的调度
父进程的fork返回值是子进程的pid号
子进程的fork返回值是0
wait阻塞函数 等待子进程退出后 父进程才退出
##确定gdb中的进程跟踪模式
show/set follow-fork-mode parent/child 跟踪的父子进程间的切换
detach-on-fork
show detach-on-fork和跟踪的进程有关,只负责on和off , 跟踪父进程则负责父进程的on/off , 跟踪子进程则负责子进程的on/off
parent on 只调试父进程,子进程正常运行
child on 只调试子进程,父进程正常运行
parent off 同时调试两个进程,子进程暂停在fork位置
child off 同时调试两个进程,父进程暂停在fork位置
shell ps -ef | grep num/programName 查看指定pid或程序名的进程 shell ps -A查看所有进程
##进程间的切换 在detach off 的时候使用切换调试的进程
info inferiors 查看调试的进程
inferiors num 切换调试的进程
#进程的管理
add-inferior [-copies n] 复制一个进程 -copies + 进程列表num
[-exec executable] 新开一个进程 + 程序的路径
detach
kill
remove-inferior 删除进程
###########多线程
show/set scheduler-locking off不锁定任何线程 on锁定其他线程只有当前线程执行 step只有被调试线程运行
gdb版本过低不一定能锁定
info thread 查看所有线程
threads num 切换到指定线程
int main()
{
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,thread1,NULL);//创建线程1
pthread_create(&tid2,NULL,thread2,NULL);//创建线程2
pthread_join(tid1,NULL);//等待线程1
pthread_join(tid2,NULL);//等待线程2
return ;
}
切换到指定线程后调试,断点打在线程函数上不妨碍主线程main的执行所以会有三个线程
Linux基础(03)gdb调试的更多相关文章
- linux基础2——gdb调试器
gdb调试器使用的一般步骤(不断更新完善): 1.编译过程中要用-g参数来添加调试符号——gcc test.c -g: 2.gdb启动可执行文件——gdb a.out: 3.出现gdb符号表示启动成功 ...
- 【转】 linux编程之GDB调试
GDB是一套字符界面的程序集,可以用它在linux上调试C和C++程序,它提供了以下的功能: 1 在程序中设置断点,当程序运行到断点处暂停 2 显示变量的值,可以打印或者监视某个变量,将某个变量的值显 ...
- linux学习之四---gdb调试
在Linux应用程序开发中,最经常使用的调试器是gdb. 一.启动和退出gdb gdb调试的对象是可运行文件,而不是程序的源码.假设要使一个可运行文件能够被gdb调试,那么使用编译器gcc编译时须要增 ...
- linux编程之GDB调试
GDB是一套字符界面的程序集,可以用它在linux上调试C和C++程序,它提供了以下的功能: 1 在程序中设置断点,当程序运行到断点处暂停 2 显示变量的值,可以打印或者监视某个变量,将某个变量的值显 ...
- linux应用程序设计--GDB调试
GDB简介:GDB是GNU发布的一款功能强大的程序调试工具,GDB主要完成下面三个方面功能: 一.GDB的使用操作 1.启动被调试程序. 2.让被调试的程序在指定的位置停住. 3.当程序被停住时,可以 ...
- Linux下用gdb 调试、查看代码堆栈
Linux中用gdb 查看代码堆栈的信息 core dump 一般是在segmentation fault(段错误)的情况下产生的文件,需要通过ulimit来设置才会得到的. 调试的话输入: gd ...
- NOI Linux下Emacs && gdb调试方法
1. 首先要配置emacs文件: (global-linum-mode t) (show-paren-mode t) (global-set-key (kbd "C-s") 'sa ...
- Linux系统下GDB调试
GDB 一.gdb常用命令: 命令 描述 backtrace(或bt) 查看各级函数调用及参数 finish 连续运行到当前函数返回为止,然后停下来等待命令 frame(或f) 帧编号 选择栈帧 in ...
- Linux基础03
** Linux基本操作常用命令(三) ** Linux的软件包 Linux的软件把分为“源码包”和“二进制包” 源码包:免费,开源 二进制包:系统默认包,即RPM包(上一节我们通过rpm卸载过ope ...
随机推荐
- 记一次CPU使用100%问题排查
需求 前端同事说测试环境的服务接口查起来很慢,很不稳定,不是个别接口,而是大量接口. 情况分析 由于是在测试环境联调,没有多少用户量.第一步:先去服务器看看资源的使用情况.使用top命令,查看cpu的 ...
- centos7 出现“FirewallD is not running”
原因:没有开启防火墙 #提示没有开启防火墙服务,–permanent #永久生效,没有此参数重启后失效 [root@uJZ ~]# firewall-cmd --permanent --zone=/t ...
- (持续更新) C# 面试技术点、常见SQL技术点 和 解决高并发的相关技术
这篇博客 持续更新. 方便小伙伴们学习与面试前的复习
- Navicat自动断开连接处理方式
问题描述 使用Navicat连接mysql后,如果一段时间不操作,那么会再次操作时会提示无响应,每次都这样确实折磨人,大大降低了工作效率! 问题解决 关闭连接→右键连接→连接属性 将上述心跳时间设置为 ...
- nginx php-fpm 配置问题(2)
问题: Nginx/FPM/PHP all php files say 'File not found.' 解决: 可能情况 1: 在 nginx php-fpm 配置问题(1)文中,我们分析了一种可 ...
- WebSocket专题(阿里)
我们的项目中使用了websocket 用java-websocket 开源项目做的,阿里的人问我用啥实现的websocket一时没有答上来 回来做了总结: 1.前言 最近有同学问我有没有做过在线咨询功 ...
- 后台接收参数报错 Required String parameter 'id' is not present
来自:https://blog.csdn.net/qq_15238647/article/details/81539287 关于ajax请求spring后台出现 Required String par ...
- C# Microsoft.Office.Interop.Owc11 导出excel文件
C# Microsoft.Office.Interop.Owc11 导出excel文件 1.新建项SupremeWindowsForms窗体应用项目(项目平台设置称X86) 注意:因为大多数第三方写的 ...
- Refused to execute script from '...' because its MIME type ('') is not executable, and strict MIME type checking is enabled.
写在前面 部署项目到weblogic上启动首页访问空白, 浏览器控制台报如题错误. web.xml中把响应头添加防止攻击的报文过滤器禁用就行了(仅仅是为了启动), 以下为转载内容, 可以根据需要自行测 ...
- java 把 PEM 格式的公钥证书转换为 X.509 格式的证书
代码: @UtilityClass public final class X509Certs { private static final CertificateFactory CERTIFICATE ...