plc堆栈原理桢的生成原理(调试器是如何生成plc堆栈原理的调

asp.net中的桢结构身份验证问题,100分!
[问题点数:100分,结帖人benediction]
本版专家分:0
结帖率 100%
CSDN今日推荐
本版专家分:0
本版专家分:0
本版专家分:0
本版专家分:7427
本版专家分:526163
年度总版至少三次排名前十即授予名人勋章
2002年 总版技术专家分年内排行榜第一
2003年 总版技术专家分年内排行榜第二
2004年 总版技术专家分年内排行榜第三
匿名用户不能发表回复!|
其他相关推荐Windows程序调试系列文章——使用VC++生成调试信息
使用VC++生成调试信息
ZhangTao,zhangtao., 译自 “”,Oleg Starodumov
当我们使用调试器来调试程序时,我们希望能够单步调试到源代码中,在代码中设置断点,观察变量的值(包括用户自定义的复杂类型的值)。但是可执行文件只含有原始的字节数据——机器指令和操作系统执行程序时所使用的头信息和表信息。操作系统加载并运行可执行文件后,它根据不同的需求使用不同片段的内存(栈、堆)存放数据,其中的存放的依然是原始的字节数据。那么,调试器如何知道当前CPU指令对应哪一行代码?如何知道堆栈中的地址对应哪一个函数的局部变量?答案是“调试信息”,调试信息是高级编程语言和运行程序的原始字节数据之间的桥梁。
位置(location): 在不同的情况有不同的含义。对于函数而言,是函数首字节的地址;对于全局和静态变量而言,是内存中变量的首字节;对局部变量和函数参数而言,通常是该变量的首字节相对于函数堆栈的预先定义的基址的偏移。另外,其他类型的位置也可能出现,如:寄存器、TLS slot(参见:)、元数据标记(metadata token, 参见)。
FPO (frame pointer omission): 帧指针省略,FPO用来链接CodeView或PDB符号。它在编译器没有用EBP寄存器生成标准堆栈桢(a standard stack frame) 的地方帮助调试器查找函数的参数和本地变量。
调试信息的类型
我们只讨论在Intel X86平台上的现有的由微软提供的调试器。
信息的类型
公共函数和变量
用于描述在多个的编译单元(源代码文件)中可见的函数和变量,调试信息保存每个函数和变量的位置(location)和名称。
私有函数和变量
用于描述除公共函数和变量以外的所有函数和变量,包括静态函数、静态和局部变量、函数参数),调试信息保存每个函数和变量的位置、大小和名称。
源文件和代码行信息
用于将每一行代码映射到可执行文件的某个位置上。当然,某些代码行不能做映射,如注释行,这样的代码行在调试信息中不做体现。
用于存储每一个函数和变量的类型信息。对于变量或函数参数,类型信息能够告诉调试器它是整型还是字符串类型,或是用户自定义的类型。对于函数,类型信息记载了参数的个数、调用转换和返回值的类型。
对于做了FPO优化的函数,调试信息保存了一些数据来帮助调试器确定函数堆栈帧的大小,甚至在帧指针无效时也能工作。 如果没有FPO信息,调试器无法正确显示被优化的程序的调用堆栈。
编辑和继续执行信息
用于帮助Visual Studio IDE在调试时实现编辑和继续执行的功能
调试信息格式
现在来探索调试信息是如何存储的。在过去的十年中,微软开发工具使用了几种不同的格式来包装调试信息。这里我们讨论COFF、CodeView和应用的最广泛的PDB(Program Database)格式。在讨论每种格式时,我们从下列几个特性着手:
哪些类型的调试信息可以通过该格式保存?
调试信息究竟保存在哪里(在可执行文件中,还是单独的一个文件)?
该格式是否有文档说明?
COFF是这里要涉及的所有格式中最古老的一种,它只能保存三种调试信息: 公共函数和变量,源文件和代码行信息,FPO信息。COFF总是保存在可执行文件中,不能够单独保存在其他文件中。该格式的文档说明参见:.
CodeView是较COFF更新的而且更复杂的一种格式,它可以存储除编辑和继续执行信息外的所有类型的调试信息。CodeView通常保存在可执行文件中,它也可从可执行文件中导出到一个单独的文件(.DGB文件)。CodeView文档不全,其文档可以在MSDN中的VC++5.0符号调试信息规范(Symbolic Debug Information Specification)中找到。
Program Database 程序数据库
这是三种中最新的一种调试信息格式,可以存储所有类型的调试信息(包括编辑和继续执行信息),也支持增量编译(其余两种格式不支持)。程序数据库信息保存在一个单独的.PDB文件中。遗憾的是,微软没有提供程序数据库格式的文档,只提供特殊的编程接口DbgHelp 和DIA来访问它。目前,程序数据库格式有两个版本,第一版(PDB2.0)为VC6.0所用,第二版(PDB 7.0)被Visual Studio.NET采用。PDB 7.0不能向上兼容,也就是说:VC6.0不能读取PDB 7.0格式。
三种格式对比如下:
是否有文档
公共函数和变量
私有函数和变量
源文件和代码行信息
编辑和继续执行信息
可执行文件中
可执行文件中
或.DBG文件中
Program Database
.PDB文件中
生成调试信息
构造(build)过程
一个典型的可执行文件的构造过程包含两步:编译和链接。首先,编译器分析源文件,生成机器指令(保存在.obj对象文件中);然后链接器将所有可用的对象文件合并到最终的可执行文件。在对象文件之外,链接器也会用到库文件(库文件也是其他一些对象文件的汇集)。整个构造过程如下图:
如果我们想要为可执行文件生成调试信息,也得经历两步:首先,编译器为每一个源文件创建调试信息;然后,链接器合并由编译器创建得调试信息,如下图:
缺省状态下,编译器和链接器不会产生调试信息。因此我们必须通过编译和链接选项来要求编译器和链接器生成调试信息,我们也可以指定生成哪些类型得调试信息,使用什么调试信息格式,将调试信息保存在什么地方。
接下来,我讨论具体得编译器和链接器选项。
Visual C++ 6.0
编译器 Compiler
有下列选项:/Zd 生成COFF格式的调试信息,保存在对象文件中/Z7 生成CodeView格式的调试信息,保存在对象文件中/Zi 生成程序数据库格式的调试信息,保存在.PDB文件中/ZI 与 /Zi 基本一致, 唯一不同的是调试信息中包含编辑和继续执行信息缺省时,/Zi 和 /ZI 选项生成的PDB文件名为VC60.PDB,也可以使用/Fd指定文件名。
公共函数和变量
源文件和代码行信息
公共函数和变量
私有函数和变量
源文件和代码行信息
Program Database
公共函数和变量
私有函数和变量
源文件和代码行信息
Program Database
公共函数和变量
私有函数和变量
源文件和代码行信息
编辑和继续执行信息
链接器Linker
下列选项可用:
/debug 告诉链接器生成调试信息,如果该选项不使用,则其他所有选项都无效
/debugtype 指定调试信息格式,可能的用法包括:
/debugtype:coff
COFF格式。注意:该选项下,调试信息中不包含源文件和代码行信息
/debugtype:cv
CodeView或程序数据库格式。究竟是哪一种格式,由/pdb决定
/debugtype:both
同时使用COFF格式和CodeView/程序数据库格式
/pdb 决定是CodeView还是程序数据库格式。/pdb:none 表示CodeView格式,/pdb:filename(如/pdb:myexe.pdb)表示使用程序数据库格式,文件名为myexe.pdb。在/debugtype:coff 选项下,/pdb 选项无效。
/pdbtype 该选项只在一个或多个对象文件或库文件的调试信息也保存在一个单独的PDB文件中。/pdbtype:sept 选项可以使得调试信息各自保存在各自的PDB文件中,这样可以加快链接速度,不利的是调试信息分散,调试时需要多个PDB文件。相对的,/pdbtype:con 选项使得所有调试信息都保存在与可执行文件对应的最终的PDB文件中。
为便于理解各个选项的配对使用,请见下表:
/debugtype
/pdb:none (无效)
在可执行文件中
/pdb:filename (无效)
在可执行文件中
在可执行文件中
/pdb:filename
Program Database
COFF and CodeView
在可执行文件中
/pdb:filename
COFF and Program Database
COFF 信息在可执行文件中, 程序数据库信息在 .PDB 文件中
Visual C++.NET (2002 and 2003)
编译器 Compiler
下列选项可用:
生成CodeView格式的调试信息,保存在对象文件中/Zd, /Zi 和 /ZI都表示生成程序数据库格式的调试信息,保存在.PDB文件中. 不同之处是调试信息的内容(见下表)。缺省时,/Zd,/Zi 和 /ZI 选项生成的PDB文件名为VC70.PDB或VC71.PDB,也可以使用/Fd指定文件名。注意: VC++.NET 编译器不支COFF。
公共函数和变量
私有函数和变量
源文件和代码行信息
Program Database
公共函数和变量
源文件和代码行信息
Program Database
公共函数和变量
私有函数和变量
源文件和代码行信息
Program Database
公共函数和变量
私有函数和变量
源文件和代码行信息
编辑和继续执行信息
链接器Linker
下列选项可用:
/debug告诉链接器生成调试信息,如果该选项不使用,则其他所有选项都无效。调试信息的格式总是程序数据库格式,保存在PDB文件中。缺省的,链接器使用可执行文件名生成PDB文件名。PDB文件名可包含所有调试信息的变量内容。
/pdb 指定PDB文件名.
/pdbstripped 允许链接器生成附加的PDB文件,该文件的内容限定于:
公共函数和变量
注意: COFF 和 CodeView 格式不被 VC++.NET链接器支持。
静态库的调试信息
由于没有连接过程,静态库的调试信息的生成比可执行文件要简单的多。不考虑编译器版本(VC6 或 VS.NET),我们可以使用(/Zd, /Z7, /Zi, /ZI)中一个选项通知编译器为静态库生成调试信息。
关键问题是将调试信息保存在什么地方。当使用/Z7或/Zd选项时,调试信息保存在.LIB文件中;当使用/Zi或/ZI选项时,调试信息保存在.PDB文件中(当然可以使用/Fd指定文件名)。
调试信息对可执行文件的大小的影响
调试信息对可执行文件的大小的影响,决定于存储调试信息的地方,也间接的决定于所使用的格式。
COFF和CodeView格式下,调试信息保存在可执行文件中,因此可执行文件的大小将显著增长(通常要增长一倍以上,甚至更大)。
程序数据库格式下,调试信息单独保存,对可执行文件的大小几乎没有影响。在这种情况下,可执行文件需要保存一个头信息方便调试器对调试信息进行定位,因此需要增长大约几百个字节。
要避免可执行文件的膨胀,我们需要在使用/debug 同时,将/opt:ref 选项改为opt:noref。这样做,有一个另外的结果就是关闭了链接器的大小优化。如果要恢复大小优化,需要改回/opt:ref。
使用一个小工具——Rebase——可以将CodeView格式的内容从可执行文件中导出,存入到DBG文件中。Rebase包含在Visual Studio中。除了用于导出DBG文件外,它还有其他的一些用途。如果用于导出DBG文件,其命令行格式为:
rebase –b BaseAddr –x SymbolDir [-p] ExeName
-b BaseAddr
指定可执行文件的基地址,如果你不想更改基地址,就指定当前可执行文件所使用的地址
-x SymbolDir
制定存放.DBG文件的目录, 使用“.”表示当前目录
如果该选项被使用,DBG文件只包含公共函数和变量和FPO信息
例如:下面的命令行从DLL中导出调试信息到当前目录下的DBG文件中: rebase –b 0x –x . MyDll.dll
调试器和调试信息的格式
通用的调试器支持的格式如下:
Program Database (2.0)
Program Database (7.0)
Visual Studio.NET
Visual C++ 6.0
WinDbg 6.3
6.3 部分支持CodeView格式,它只能读取下列信息:
公共函数和变量
源文件和代码行信息
它可以单步进入源代码,看到调用堆栈,但无法观察变量的值(因此类型信息不被支持).
操作系统符号文件(symbols)
Windows操作系统所公开的调试系统格式如下:
Windows NT 4.0
CodeView (.DBG files)
Windows 2000
CodeView (.DBG files) and Program Database (2.0)
Windows XP
(including SP1 and SP1a)
Program Database (2.0)
Windows XP SP2
Program Database (7.0)
Windows 2003 Server
Program Database (2.0)
未使用调试信息生成二进制文件
VS2005 未使用调试信息生成二进制文件 解决方法 办法
“无法找到“xxx.exe”的调试信息,或者调试信息不匹配。未使用调试信息生成二进制文件。”
VC++程序调试debug dump
VC2010 MFC中实现printf调试功能,即MFC程序利用控制台输出调试信息。
没有更多推荐了,&|&&|&&|&&|&&
当前位置: >
堆栈桢的生成原理
作者:厚积薄发 & 来源:转载 &
摘要: 堆栈桢的生成原理一直比较好奇,调试器是如何生成堆栈的调用过程的,比如如下代码:int add(int a, int b){
return a +}int main(){
int c = add(1, 2);
system("pause");
return 0;}调用Add时的堆栈截图如下:调试器究竟是如何生成这个堆栈过程的呢?我最初的理解调试器是根据EBP来生成该堆栈
堆栈桢的生成原理
一直比较好奇,调试器是如何生成堆栈的调用过程的,比如如下代码:
return&a&+&b;
int&main()
int&c&=&add(1,&2);
&&&&system("pause");
调用Add时的堆栈截图如下:
调试器究竟是如何生成这个堆栈过程的呢?
我最初的理解调试器是根据EBP来生成该堆栈的,原理如下:
可以看到按照上面的原理, 每次EBP里存放的都是当前函数的堆栈桢基址,所以我们只要一直递推,就可以得到完整的Call Stack.
但是我们很快会发现, 并不是每个函数都是以
push ebp &&
mov ebp, esp
开头的,我们可以写一些裸(naked)函数,
__declspec
&y) 来手动控制函数头,
而且很多编译器优化过的函数代码也是没有该标准函数头的。
那么调试器在这种情况下又是如何生成完整的call stack的呢?
和群里的朋友讨论的结果是调试器很可能是在调用call指令时保存了调用现场,
这样只要在调试器下运行,它就一直可以知道正确而完整的call stack.
这也解释了为什么我们在分析Crash的Dump文件时很多时候得不到正确的堆栈过程?
有可能是堆栈本身被我们的异常代码破坏了;
更有可能是因为我们的代码在直接运行时没有调试器的参与, 所以堆栈过程没有被保存,所以windbg分析dump时只能根据堆栈里内容自己分析和推理堆栈调用过程,所以很多时候得不到正确的堆栈过程。
那么Windbg分析dump时,会如何倒推堆栈过程呢?
如果每个函数都是有标准的push ebp, 那么按照ebp递推就可以了;
否这就只能用其他方法分析,比如看看堆栈里某个地址是不是函数返回地址(该地址属于某个模块的代码段),这样就可以确定该地址是某个函数堆栈桢的起始地址。
上面关于生成call stack的原理只是一些非专业人士的个人看法,如果有不正确的地方,欢迎指正。
注: 和开发过调试器的朋友讨论,上面 关于callstack产生原理的推论,实际上是不正确的, 调试器实际上是通过查询PDB文件的方式获取的callstack.
版权所有 IT知识库 CopyRight (C)
IT知识库 IT610.com , All Rights Reserved.记录技术的点点滴滴!
【工具相关】iOS-Reveal的使用
一,首先下载Reveal工具。
Reveal的下载地址:。
下载界面如下图所示,选择Download Trail蓝色按钮可以进行下载:
二,新建立一个工程,做为Reveal做测试用的Demo.最原始的工程如下图所示:
三,打开Reveal软件,如下图所示:
四,在Reveal软件中,选择Help--&Show Reveal Library in Finder,会出现如下图所示界面。
五,把Reveal.framework从Finder中拷贝到工程文件中。如下图所示:
六,将Reveal.framework添加到工程中,添加完成后效果如下图所示。
七,按下图找到Build Phases----&Link Binary With Libraries---&Reveal.framework.
八,选中Reveal.framework,然后,点击“—”号时行删除操作。
九,按下图,找到,Build Settings----&Other Linker Flags.
十,在Other Linker Flags中添加
"-ObjC -lz -framework Reveal"
十一,设置完Other Linker Flags后,工程目录如下图所示。
十二,在模拟机上开始运行工程。注意一定要选择模拟机,因为如果是真机的话,可能Reveal与工程不在一个网络上面。
十三,开始在模拟机中运行工程。如下图所示。
十四,待模拟机运行成功后,注意,一定要运行成功之后。打开Reveal。
十五,在左上角选择RevealDemo,也就是我们刚才运行的工程文件。
十六,到此为止,Reveal运行成功。
参考资料:
【系列】使用springmvc+mybatis创建Web应用(一)—— 相关概念,工具,搭建Web应用
cocos2dx入门需要了解的工具
ETL工具:kettle(spoon)应用
Oracle常用工具
JVM原理及调优(7)——JDK常用内置工具
vuejs及相关工具介绍
项目相关工具的使用
iwconfig相关工具的使用
Bluez相关工具的使用
没有更多推荐了,DirectShow 播放MPGE4文件 得到视频MediaSample 我怎么知道哪一桢是I桢,哪一桢是P桢呢!?
[问题点数:0分]
本版专家分:1102
结帖率 100%
CSDN今日推荐
本版专家分:1102
本版专家分:567
本版专家分:2728
本版专家分:451
本版专家分:345
本版专家分:1102
本版专家分:1102
匿名用户不能发表回复!|
其他相关推荐
扫描完整版带书签
public class VideoThumbTaker
protected static String ffmpegApublic VideoThumbTaker(String ffmpegApp)
this.ffmpegApp = ffmpegA
@SuppressWarnings(“unused”)
* 获取指定时间内的
帧布局由FrameLayout所代表,FrameLayout直接继承了ViewGoup组件。
帧布局容器为每个加入其中的组件创建一个空白的区域(称为一个帧),每个子组件占据一帧,这些帧都会根据gravity属性执行自动对齐。
&FrameLayout xmlns:android=&http://schemas.android.com/apk/res/android&
关键帧就是独立桢,不以其他桢图像做参考,在mepg标准中图像桢的参考关系如下
图像类型及其相互关系(参考关系如图的箭头所示)
MPEG将图像分成四种类型:I、P、B、D
I图像是帧内编码图像,它不参考其他任何图像而独立编码
P图像是前向预测编码图像,相对于前一参考图像进行有运动补偿的预测编码
B图像是双向预测编码图像,需要前向和后向的参考图像作运动补偿
D图像的目的是提供一种简单的,但
为了能够说明wen
1.函数的调用过程
主函数main里定义了4个局部变量,然后调用同文件里的foo1()函数。4个局部变量毫无疑问都在进程的栈空间上,当进程运行起来后我们逐步了解一下main函数里是如何基于栈实现了对foo1()的调用过程,而foo1()又是怎么返回到main函数里的。为了便于观察的粒度更细致一些,我们对test.c生成的汇编代码进行调试
一直比较好奇,调试器是如何生成堆栈的调用过程的,比如如下代码:
int add(int a, int b)
return a +
int main()
int c = add(1, 2);
system(&pause&);
调用Add时的堆栈截图如下:
调试器究竟是如何生成这个
孔德桢工具箱是孔德桢的个人主页推出的一套便捷的使用工具,通过它,您可以快速了解到有关孔德桢的信息。目前已推出1.0,1.1,2.0,3.0,3.5五个版本
+ (UIImage*) thumbnailImageForVideo:(NSURL *)videoURL atTime:(NSTimeInterval)time {
AVURLAsset *asset = [[[AVURLAsset alloc] initWithURL:videoURL options:nil] autorelease];
NSParameterAssert(a
用delphi做的flash播放器,界面美观,可以在暂停状态下实现拖动,可以显示当前播放桢数及总桢数。
孔德桢工具箱是孔德桢的个人主页推出的一套便捷的使用工具,通过它,您可以快速了解到有关孔德桢的信息。目前已推出1.0,1.1,2.0,3.0,3.5五个版本}

我要回帖

更多关于 微机原理堆栈原理 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信