Linux环境下的堆栈--调试C程序
完整的调试过程,跟踪堆栈变化,32位下。
注意64位和此不同。
a.c代码:
#include <stdio.h>
int main()
{ AFunc(5,6);return 0;
} int BFunc(int i,int j)
{int m = 1;int n = 2;m = i;n = j; return m;
}int AFunc(int i,int j)
{int m = 3;int n = 4; m = i;n = j;BFunc(m,n);return 8;
}
编译加上调试信息
#gcc -g -o a a.c
要调试C程序,在编译时,必须要把调试信息加到可执行文件中。使用编译器(cc/gcc/g++)的 -g 参数可以做到这一点。如:
> cc -g hello.c -o hello
> g++ -g hello.cpp -o hello
如果没有-g,你将看不见程序的函数名、变量名,所代替的全是运行时的内存地址。
启动gdb
#gdb a
增加断点
#break *main
运行
#run
步入
#s 进入的单步执行
如果已经进入了某函数,而想退出该函数返回到它的调用函数中,可使用命令finish
#finsh
#n 不进入的单步执行
查看数组的值
有时候,你需要查看一段连续的内存空间的值。比如数组的一段,或是动态分配的数据的大小。你可以使用GDB的“@”操作符,“@”的左边是第一个内存的地址的值,“@”的右边则你你想查看内存的长度。例如,你的程序中有这样的语句:
int *array = (int *) malloc (len * sizeof (int));
于是,在GDB调试过程中,你可以以如下命令显示出这个动态数组的取值:
#p *array@len
如果是静态数组的话,可以直接用print数组名,就可以显示数组中所有数据的内容了。
whatis 命令可以显示某个变量的类型
(gdb) whatis p
type = int *
查看汇编
#disas
#bt 查看栈帧
#f 0查看第0帧
#f 1查看第1帧
#f N查看第N帧
之后查看寄存器也会查看对应的寄存器
#i r
之后也会查看对应寄存器内容
#x/40xw $esp
查看堆栈底
#x/40xw $ebp
--《深入理解计算机系统(原书第2版)》
开始
1.main函数中第1个s
ebp的内容为0
2.main函数中第2个s,开始调用A函数
很明显esp和ebp变化了,上一步的ebp地址被pusp到新的ebp的内容。
3.进入A函数
显示ebp入栈;
然后esp指向新的ebp
sub $0x18,%esp即esp减少24个地址;0xbffff618-18=0xbffff600
第1帧:
第0帧:
ebp依次保存了:
“上一个ebp的地址 0xbffff638;
“main函数中调用完A函数后的执行地址 0x080483b1”;
“上级函数传递的参数5保存在ebp的正向地址”;
“上级函数传递的参数6保存在ebp的正向地址”
将进入AFunc函数之前的EBP的值入栈保存,这时候的EBP相当于是AFunc上级函数; 的一个现场信息,所以需要保存起来,以便于AFunc返回后上级函数可以恢复EBP使其指向其调用; AFunc之前的堆栈位置(当然,这还需要靠恢复ESP来协助达到这一目的)
4.A函数中int n=4前
0x8(%ebp)的-8个位置存放3;
0x4(%ebp)的-4个位置存放4。
注意:这里如果调用f 0则后面的i r和x/40xw $ebp都是查看该栈帧
5.A函数m=j前
函数的局部变量放置在EBP的负偏移处(Negative; Offset)也就是向低地址方向。
esp在0xbffff618,3和4分别在0xbffff610和0xbffff614。
6.A函数n=j之前
0x8(ebp)获取ebp正向地址的值稍后mov到eax寄存器;
然后将eax寄存器中的5移到-0x8(ebp)即ebp的负地址8
0xbffff610处的3已经被替换为5
7.进入B函数之前
0xc(%ebp)从ebp高地址获取6并存储在ebp的低地址-4位置,然后放到eax寄存器
0xbffff614处的4已经被替换为6
8.进入B函数
按之前的第7步在进入B函数之前先把参数5和6从ebp的-4和-8地址上取出存在eax寄存器,然后存储到esp的正向地址上
esp和ebp存储新的内存地址位置
参数5和6依次保存在esp的正向地址中
8.B函数n=2之前
第2帧:
第1帧:
第一帧的ebp保存着:
main函数的ebp地址0xbffff638;
以及main函数需要继续执行的地址0x080483b1
第0帧:
这是当前B函数的帧以及对应的寄存器内容,其中1被存储在ebp的-8位置,和之前的A函数中的过程一样,没有新的差异。
9.B函数的m=i之前
10.B函数的n=j之前
11.B函数return之前
12.B函数返回值
leave 将ebp值赋给esp,
pop先前栈内的上级函数栈的基地址给ebp,
恢复原栈基址相当于:
movl %ebp,%esp
popl %ebp
返回值放在eax寄存器中
13.回到A函数
8赋给eax寄存器
14.A返回值,pop出main函数的ebp
15.回到main函数
16.退出main函数
17.进入__libc_start_main ()系统调用
18.结束
关于win32环境下的堆栈参考:Win32 环境下的堆栈
关于gdb查看栈参考: GDB查看栈信息
关于gdb调试可以参考:GDB调试--以汇编语言为例
GDB 进行调试 使用心得
相关文章:
听说过代码洁癖,Bug洁癖怎么解?
来源 | Python编程时光(ID: Cool-Python)当我们写的一个脚本或程序发生各种不可预知的异常时,如果我们没有进行捕获处理的时候,通常都会致使程序崩溃退出,并且会在终端打印出一堆 密密麻麻 的 traceback 堆栈信息来告诉…

POJO、VO、PO、FormBean区别:
首先讲一下四者的概念 POJO:Pure Old Java Object,符合Java Bean属性规范的简单Java对象,通常也称为VO(Value Object,值对象)。 VO:就是POJO; PO: Persistent Object,持久化对…

oracle中的sql%rowcount,sql%found、sql%notfound、sql%rowcount和sql%isopen
Oracle 存储过程 删除表记录时删除不存在的记录也是显示删除成功 create or replace procedure delDept(p_deptno in dept.deptno%type) is begindelete from dept where deptnop_deptno;dbms_output.put_line(部门删除成功...);exception when others thendbms_output.put_lin…

linux平台的链接与加载
原文是上下两篇 链接与加载(上) — 静态链接链接与加载(下) — 动态链接 为观看方便,现在合并起来。 一.静态链接 示例程序 我们先看一个简单的示例程序,代码如下: /*main.c*/int u 333;int sum(int, int);int main(int argc, char* argv…
预训练模型ProphetNet:根据未来文本信息进行自然语言生成
作者 | 刘大一恒、齐炜祯、晏宇、宫叶云、段楠、周明来源 | 微软研究院AI头条(ID:MSRAsia)编者按:微软亚洲研究院提出新的预训练模型 ProphetNet,提出了一种新的自监督学习目标——同时预测多个未来字符,在序列到序列的…

模拟进程管理小结,编码规范的重要性
废话不多说了,省的又有衰人找我麻烦。希望我讨厌的,和讨厌我的少来骚扰我,由衷的感谢它们。 我不回那些骚扰,是因为我见到名字就直接删了,看都懒的看了。也别怪我粗鲁,因为我一向是对什么人说什么话 的&…

JSPServlet路径问题
2019独角兽企业重金招聘Python工程师标准>>> 如果带WebRoot,那么js、css、img都应该放到WebRoot目录下,否则访问会有问题。千万不要放在WEB-INF下,因为WEB-INF下的内容只有服务器转发可以访问到,出于安全考虑。 如果不…

Git学习教程(六)Git日志
第六课 Git 日志 内容提要:浏览项目历史,查询指定提交内容,图形化显示分枝和合并...git log是git中最常用的一个命令,执行之后,会显示该项目的提交历史。如果命令不加任何参数,那么就会显示目前所在分枝上&…

汇编包含C代码
反汇编的时候带上C代码便于观察 比较三元表达式和if else的差异 a1.c #include <stdio.h> int main(void) { int a1;int b2;int c0;a (b>c)?1:0;return 0;} a2.c #include <stdio.h> int main(void) { int a1;int b2;int c0;if(b>c){a1;}else{a0;…
无需3D运动数据训练,最新人体姿势估计方法达到SOTA | CVPR 2020
作者 | Muhammed Kocabas译者 | 刘畅出品 | AI科技大本营(ID:rgznai100)人体的运动对于理解人的行为是非常重要的。尽管目前已经在单图像3D姿势和动作估计方面取得了进展,但由于缺少用于训练的真实的3D运动数据,因此现有的基于视频…

Linux内核跟踪之trace框架分析【转】
转自:http://blog.chinaunix.net/uid-20543183-id-1930846.html------------------------------------------本文系本站原创,欢迎转载!转载请注明出处:http://ericxiao.cublog.cn/------------------------------------------一: 前言本文主要是对trace的框架做详尽…
写给Python开发者:机器学习十大必备技能
作者 | Pratik Bhavsar译者 | 明明如月,编辑 | 夕颜来源 | CSDN(ID:CSDNnews)有时候,作为一个数据科学家,我们常常忘记了初心。我们首先是一个开发者,然后才是研究人员,最后才可能是数学家。我…

Linux环境程序栈溢出原理
当在缓冲区中输入过多的数据时,缓冲区溢出就会发生,C语言提供了多种方法,可以使在缓冲区中输入的数据比预期的多。 局部变量可以被分配到栈上。这就意味着在栈的某个地方有一个固定大小的缓冲区。 而栈是向下增长的,而且一些重要…

[翻译]Joomla 1.5架构(十一) model 包
这个包包含了跟数据表交互的所有相关类 JModel This abstract class is the base class for all Joomla! data access objects. 所有数据访问类的抽象基类。 以下的类都分别实现对不同表的访问,不再翻译了。 Adapter Folder JModelCategory This is a data access …

度量快速开发平台端口映射的介绍
度量快速开发平台在客户中部署的时候,可能会想内网与外网用户同时使用。一般情况下,服务端都是部署在内网的,那外网用户要访问,就可能用到端口映射的功能。端口映射基本都是在路由器上进行。下面就是几个常用的路由器上的设置方法…

为什么栈和堆的生长方向不一样
栈的生长方向 8051的栈是向高地址增长,INTEL的8031、8032、8048、8051系列使用向高地址增长的堆栈;但同样是INTEL,在x86系列中全部使用向低地址增长的堆栈。其他公司的CPU中除ARM的结构提供向高地址增长的堆栈选项外,多数都是使用…
简单粗暴理解与实现机器学习之逻辑回归:逻辑回归介绍、应用场景、原理、损失以及优化...
作者 | 汪雯琦责编 | Carol来源 | CSDN 博客出品 | AI科技大本营(ID:rgznai100)学习目标知道逻辑回归的损失函数知道逻辑回归的优化方法知道sigmoid函数知道逻辑回归的应用场景应用LogisticRegression实现逻辑回归预测知道精确率、召回率指标的区别知道如…

生命的脆弱——悼念朋友
生命的脆弱让我们敲希望的钟啊多少祈祷在心中让大家看不到失败叫成功永远在让地球忘记了转动啊四季少了夏秋冬让宇宙关不了天窗叫太阳不西沉让欢喜代替了哀愁啊微笑不会再害羞让时光懂得去倒流叫青春不开溜让贫穷开始去逃亡啊快乐健康留四方让世界找不到黑暗幸福像花开放让大家…

VMware Tools手动下载
2019独角兽企业重金招聘Python工程师标准>>> VMware自己下载VMware Tools非常慢。你可以自己手动下载它。 下载地址为: version: 8.8.2 http://softwareupdate.vmware.com/cds/vmw-desktop/ws/8.0.3/ 选择最新的build,例如: http:…

Linux查看多核CPU利用率
1.top 使用权限:所有使用者 使用方式:top [-] [d delay] [q] [c] [S] [s] [i] [n] [b] 说明:即时显示process的动态 d :改变显示的更新速度,或是在交谈式指令列( interactive command)按s q :没有任何延迟的显示速度…

仓央嘉措《那一天,那一月,那一年,那一世》
那一天, 我闭目在经殿的香雾中, 蓦然听见你颂经中的真言; 那一月, 我摇动所有的经筒, 不为超度, 只为触摸你的指尖; 那一年, 磕长头匍匐在…
AI+大数据助力抗疫,带你认识百度地图的新玩法!
作者 | Aholiab责编 | Carol出品 | AI科技大本营(ID:rgznai100)“喂,你好,我是百度地图的客服,请问是xx店铺对吗?”“嗯,什么事?”“您家在疫情期间还照常营业,对吗&…

Coursera Machine Learning 作业提交问题
关于作业提交问题的解决办法 Octave 4.0.0无法正常提交 解决办法:打两个补丁 补丁1:平台通用补丁2:Win,Linux or Mac 注:补丁文件中有安装说明

Linux查看进程内存状况
查看全部进程 通过top或ps -ef | grep 进程名 得到进程的PID。该命令可以提供进程状态、文件句柄数、内存使用情况等信息。 #pa aux 先查看进程 nginx的工作进程是5757 pmap命令 可以显示一个或多个进程所使用的内存数量。你可以使用这个工具来了解服务器上的某个进程分配…
用于小型图形挖掘研究的瑞士军刀:空手道俱乐部的图表学习Python库
作者 | Benedek Rozemberczki译者 | 天道酬勤 责编 | Carol出品 | AI科技大本营(ID:rgznai100)空手道俱乐部(Karate Club)是NetworkX Python软件包的无监督机器学习扩展库。详细可以参阅此处的文档:https://github.com…

电子商务创造的第二次产业机会
即将迎来冬至节气的这个周末,天寒地冻,却是电子商务的饕餮之季。淘宝网商交易大会刚刚在成都落下帷幕,而比网货交易会更令业界期待的“2009中国电子商务创新发展高峰论坛”也在北京顺利召开。大会由国内最大的电子商务软件及服务提供商ShopEx…

C#趣味程序---个位数为6,且能被3整出的五位数
using System;namespace ConsoleApplication1 {class Program{static void Main(string[] args){int count 0;int k;for (int i 1000; i < 9999; i){k i * 10 6;if (k % 3 0){Console.WriteLine(k);count;}}Console.WriteLine(count); }} }

c# winform 用子窗体刷新父窗体,子窗体改变父窗体控件的值
第一种方法: 用委托,Form2和Form3是同一组 Form2 usingSystem; usingSystem.Collections.Generic; usingSystem.ComponentModel; usingSystem.Data; usingSystem.Drawing; usingSystem.Text; usingSystem.Windows.Forms; namespaceTestMouseMove { pub…

TCMalloc
tcmalloc 业界最有名的内存分配库,当数google 的tcmalloc。Tcmalloc 在管理小 内存块时非常有效,而且能够避免在大内存分配时的mmap()系统调用。它在多 线程中的表现也不错能很好的减少锁碰撞(glibc 致命的问题)。Tcmalloc 现在基 本上成了mysql DBA 的标…
前沿技术探秘:知识图谱构建流程及方法
作者 | 郑毅封图| CSDN│下载于视觉中国出品 | CSDN云计算(ID:CSDNcloud)随着AI技术的发展和普及,当今社会已经进入了智能化时代。与以往不同的是,在这一波浪潮中,企业不仅是向数字化转型,更是向…