Windbg查看调用堆栈(k*)
无论是分析程序崩溃原因,还是解决程序hang问题,我们最常查看的就是程序调用堆栈。学会windbg调用堆栈命令,以及理解堆栈中的各个参数的意义就显得至关重要。
上图就是一个典型的Windbg堆栈,如果不理解ChildEBP、RetAddr、Args to Child等参数意义,以及它们之间的来龙去脉,调试工作将很难进行下去。
1. 函数参数
函数的参数传递有二种方式:堆栈方式、寄存器方式。如果是堆栈方式传递的,就需要定义参数在堆栈中的传递顺序,并约定函数被调用之后,由谁来平衡堆栈;如果是寄存器方式传递的,就需要确定参数存放在哪个寄存器中。每一种方式都有其优缺点,而且与使用的编程语言有关系,不存在哪种方式好与坏。
如Visual Studio中的C++工程,可以C++ --> 高级 --> 调用约定中进行设置:
常用的调用约定类型有__cdecl、stdcall、PASCAL、fastcall。除了fastcall可以支持以寄存器的方式来传递函数参数外,其他的都是通过堆栈的方式来传递函数参数的。
利用堆栈传递参数
堆栈是一种“后进先出”的数据结构,ESP寄存器始终指向栈顶。栈中数据地址从底部到顶部依次减小,也就是说,栈底对应高地址,栈顶对应低地址。
调用函数时,调用者依次把参数压栈,然后调用函数,函数被调用之后,在堆栈中取得参数数据。函数调用结束以后,堆栈需要恢复到函数调用之前的样子,具体由调用者来恢复还是由函数自身来恢复,根据不同的调用约定类型采用不同的方式。
约定类型 | __cdecl | stdcall | PASCAL | fastcall |
---|---|---|---|---|
参数传递顺序 | 从右到左 | 从右到左 | 从左到右 | 使用寄存器 |
平衡堆栈者 | 调用者 | 函数自身 | 函数自身 | 函数自身 |
__cdcel是C/C++/MFC程序默认的调用约定。
stdcall是Win32中绝大多数 API函数的约定方式,也有少部分使用__cdcel约定方式,如wsprintf等。
在windows C/C++开发中常用的就是__cdecl和stdcall这2种调用约定。
假设调用函数int add(int a, int b)
, 按照不同的调用约定来调用它。从调用者的视角来看,其汇编代码分别表示如下:
__cdecl
push b ;参数按从右到左传递
push a
call add
add esp, 8 ;调用者在函数外部平衡堆栈
stdcall
push b ;参数按从右到左传递
push a
call add ;函数自己内部平衡堆栈
在函数调用过程中,参数入栈的过程:
上图中,EBP和函数返回地址都是地址,在32位程序中地址占4个字节。在函数的一次调用过程中EBP是不会变化的,函数调用完之后会将EBP恢复为暂存在堆栈中的原EBP值。所以,通过EBP可以获取函数各个参数的值:
参数a = EBP + 0x8
参数b = EBP + 0xC
2. Windbg堆栈命令
2.1 显示堆栈信息k*
[~Thread] k[b|p|P|v] [c] [n] [f] [L] [M] [FrameCount]
[~Thread] k[b|p|P|v] [c] [n] [f] [L] [M] = BasePtr [FrameCount]
[~Thread] k[b|p|P|v] [c] [n] [f] [L] [M] = BasePtr StackPtr InstructionPtr
[~Thread] kd [WordCount]
参数:
Thread 指定显示哪个线程的调用堆栈。如果省略该参数,则显示当前线程的调用堆栈。*显示所有线程的调用堆栈。
b 显示每个函数的前3个参数。
p 显示每个函数的所有参数。参数列表包括每个参数的类型、名称、值。
如上图,可以看到函数的每个参数的类型,名称,值。但是这个需要有对应的符号文件(pdb),没有应用程序的符号文件只能显示系统API的参数信息。
P 类似p。不同之处在于,每个参数显示在单独的行上面。
n 显示调用堆栈中每帧的序号(一般称栈帧,如栈帧3)。
FrameCount 指定显示调用堆栈的帧数,即调用堆栈的深度。默认为16进制格式。默认帧数为0x14=20
2.2 切换到指定帧信息.frame
调用堆栈显示出来之后,如果想知道调用某帧时的相关信息,可以使用.frame
来切换指定帧,然后就可以使用如dv命令显示局部变量等。
.frame [/c] [/r] [FrameNumber]
/c
/r 显示执行该帧时寄存器的值。
FrameNumber 指定要切换到的帧号。
3. 实例分析
kbn
显示堆栈信息:
栈帧12:
调用add函数,参数1=00000001,参数2=000000002,EBP=0015fc0c
根据图1得知,函数返回地址=EBP+4,我们使用dw命令来验证。
参考:
《软件调试》张银奎 著
《格蠹汇编》张银奎 著
《加密与解密》第三版 段刚编著
Windbg查看调用堆栈(k*)的更多相关文章
- VC调试篇:ASSERT(FALSE)时怎么办?查看调用堆栈
问题简述 我们在调试程序时,经常会遇到程序中断的情况,就像下图这样. 我艹,这该怎么办,我们一下子就懵逼了.我们选择中断,常常会跳到一个莫名其妙的地方去. 正是这个断言 ASSERT(::IsWind ...
- Windbg Call Stack(调用堆栈)窗口的使用
调用堆栈是指向程序计数器当前位置的函数调用链.调用堆栈的顶部函数是当前函数,下一个函数是调用当前函数的函数,依此类推.显示的调用堆栈基于当前程序计数器,除非更改寄存器上下文. 在 WinDbg 中,可 ...
- vs2010 调试 调用堆栈 窗口
msdn 如何使用call stack窗口: http://msdn.microsoft.com/zh-cn/library/a3694ts5(v=vs.90).aspx 使用“调用堆栈”窗口可以查看 ...
- c# 如何获取当前方法的调用堆栈
c# 调试程序时常常需要借助 call stack 查看调用堆栈,实际上通过code也可以获取: class Program { static void Main(string[] args) { T ...
- [转]如何利用ndk-stack工具查看so库的调用堆栈【代码示例】?
如何利用ndk-stack工具查看so库的调用堆栈[代码示例]? http://hi.baidu.com/subo4110/item/d00395b3bf63e4432bebe36d Step1:An ...
- 怎样重建一个损坏的调用堆栈(callstack)
原文作者:Aaron Ballman原文时间:2011年07月04日原文地址:http://blog.aaronballman.com/2011/07/reconstructing-a-corrupt ...
- 如何重建一个损坏的调用堆栈(callstack)
原文作者:Aaron Ballman原文时间:2011年07月04日原文地址:http://blog.aaronballman.com/2011/07/reconstructing-a-corrupt ...
- 在 Visual Studio 中调试时映射调用堆栈上的方法
本文转自:https://msdn.microsoft.com/zh-cn/library/dn194476.aspx 1.创建代码图,以便在调试时对调用堆栈进行可视化跟踪. 你可以在图中进行标注以跟 ...
- Linux 如何使用gdb 查看core堆栈信息
转载:http://blog.csdn.net/mergerly/article/details/41994207 core dump 一般是在segmentation fault(段错误)的情况下产 ...
随机推荐
- thinkphp分页带数据
因为用thinkphp做分页时候点击下一页后搜索栏的数据会清空,然后点击下一页后刷新完了就没有内容了,感觉网上查找和我自己研究在不适用ajax做分页的情况下用以下代码就可以实现!!通过把值扔地址栏来进 ...
- tcp入门(唐唐的故事)
1,互联网的实现,分成好几层.每一层都有自己的功能,就像建筑物一样,每一层都靠下一层支持.把互联网分成五层,容易让人理解. 2,对这五层的理解(唐唐讲故事): 实体层:目的就是把计算机连接起来,用电气 ...
- Java集合类小结-思维导图
java集合类分为collection 和 map两类Collection List ArrayList LibnkedList Vector Set HashSet TreeSet LinkedHa ...
- 如何将 Microsoft Bot Framework 机器人部署以及网页应用
<Bot Framework>是微软开发的一款可让任何人制作自己的聊天机器人.该工具可以理解自然语言并对图片进行分析等,初期开放了 22 个可集成到应用的 API. 首先说到Bot大家的第 ...
- Java 学习内容总结
最近对Core Java基础做了一些学习.有自己的见解,也有别人的总结,供大家参考. 1 实现多线程的方式有几种? 其实这个问题并不难,只是在这里做一个总结.一共有三种. 实现Runnable接口,并 ...
- Java大数据应用领域及就业方向
最难毕业季,2017高校毕业生达到795万,许多学生面临着毕业即失业的尴尬.面对着与日俱增的竞争形势和就业压力,很多毕业生选择去知了堂学习社区镀金,以提高自己的就业竞争力,其中Java大数据是学生选择 ...
- 【chrome】 chrome 开发者工具
1. 常用控制台工具 console.log console.info console.error console.warn console.assert console.count conso ...
- jsp变量的使用规则
jsp是一种弱类型的交而不能语音,虽然看似没有像强类型语言那么多的代码规范,但是在实际使用的过程当中依然有不少的问题.下面就简单的梳理一下. 1.首先,jsp是一种弱类型的脚本语言,变量在使用之前无需 ...
- jquery中防止冒泡事件
冒泡事件就是点击子节点,会向上触发父节点,祖先节点的点击事件. 下面是html代码部分: <body> <div id="content"> 外层div元素 ...
- [补档][Poi2014]FarmCraft
[Poi2014]FarmCraft 题目 mhy住在一棵有n个点的树的1号结点上,每个结点上都有一个妹子. mhy从自己家出发,去给每一个妹子都送一台电脑,每个妹子拿到电脑后就会开始安装zhx牌杀毒 ...