作为链接器输入的文件称为对象文件.链接器生成一个Image文件,该文件又被加载器用作输入.
来自" Microsoft可移植可执行文件和通用对象文件格式规范 "的模糊
RVA(相对虚拟地址).在图像文件中,将项目的地址加载到内存后,从中减去图像文件的基地址.项目的RVA几乎总是与其在磁盘上的文件位置(文件指针)不同.
在目标文件中,RVA的意义不大,因为未分配内存位置.在这种情况下,RVA将是一个部分内的地址(在本表后面描述),稍后在链接期间将重定位应用于该地址.为简单起见,编译器应该只将每个部分中的第一个RVA设置为零.
VA(虚拟地址).与RVA相同,但不删除图像文件的基址.该地址称为"VA",因为Windows为每个进程创建了一个独立的VA空间,与物理内存无关.对于几乎所有目的,VA应仅被视为地址.VA不像RVA那样可预测,因为加载程序可能无法将图像加载到其首选位置.
即使在读完这篇文章之后,我仍然没有得到它.我有很多问题.任何人都可以用实际的方式解释它.请遵守Object File
&Image File
所述的术语.
我所知道的就是地址
.data
和.text
(对于函数名称)的地址.如果我知道有什么问题,请纠正我.
编辑:
在阅读弗朗西斯给出的答案之后,我清楚了解物理地址,VA和RVA是什么以及它们之间的关系.
所有变量和方法的RVAs必须在重定位期间由链接器计算.那么,(方法/变量的RVA值)==(它从文件开头的偏移量)?一定是真的.但令人惊讶的是,它没有.为什么这样?
我用选中此PEView 上c:\WINDOWS\system32\kernel32.dll
,结果发现:
.text
这是dll的第一部分)..text
通过.data
,.rsrc
直到最后一节的最后一个字节(.reloc
)RVA&的FileOffset是不同的.并且第一部分的第一个字节的RVA"始终"显示为0x1000
我猜:
所有,第一个(.text
此处)部分之前的数据字节"不"实际加载到进程的VA空间中,这些数据字节仅用于定位和描述这些部分.它们可以被称为"元部分数据".
因为它们没有加载到VA空间的过程中.术语RVA的使用也没有意义,这就是为什么RVA == FileOffset
这些字节的原因.
以来,
.text
,.data
,.rsrc
,.reloc
是这样的字节.0x00000
PEView软件是从它开始的 …作为编写编译器的先驱,我正在尝试理解Windows(32位)可移植可执行格式.特别是我想看一个简单的可执行文件的例子,除了正确加载,运行和退出之外什么都不做.
我已经尝试编写和编译一个简单的C main函数,除了生成的.exe是〜22KB并且包含许多来自KERNEL32.DLL的导入(可能由LIBC用于设置环境,堆等).甚至DOS标题也可能更小(它当前打印默认的'此程序无法在DOS模式下运行').
最小的Windows 32位可执行文件的结构是什么?
最终目标是在完全相同的环境中比较从完全相同的源构建的2个二进制文件,并且能够告诉它们确实在功能上是等效的.
一个应用程序就是将QA时间集中在发布之间实际发生变化的事情上,以及一般的变更监控.
MSVC与PE格式串联自然使得这很难做到.
到目前为止,我发现并中和了这些事情:
我解析PE,找到所有这些东西的偏移量和大小,并在比较二进制文件时忽略字节范围.像魅力一样工作(好吧,我运行它的少数测试).我可以说,只要编译器版本和所有源和头都相同,在Win Server 2008上构建的版本1.0.2.0的已签名可执行文件等于版本10.6.6.6的无符号版本,在我的Win XP开发框上构建.这似乎适用于VC 7.1 - 9.0.(适用于发布版本)
有一点需要注意.
两个绝对路径建立 必须是相同的 ,必须具有相同的长度.
cl.exe将相对路径转换为绝对路径,并将它们与编译器标志一起放入对象中,依此类推.这对整个二进制文件具有不成比例的影响.路径中的一个字符更改将导致在此处更改一个字节,并且在整个.text部分上有几次(但是我怀疑链接了很多对象).改变路径的长度会导致明显更多的差异.在obj文件和链接二进制文件中.
感觉像带有编译标志的文件路径被用作某种哈希,这使得它成为链接二进制或甚至影响不相关的编译代码片段的放置顺序.
所以这是三部分的问题(总结为"现在是什么?"):
我是否应该放弃整个项目并回家,因为我想要做的事情违反了物理法则和MS的公司政策?
假设我处理绝对路径问题(在策略级别或通过查找神奇的编译器标志),还有其他我应该注意的事项吗?(之类的东西__TIME__ 做意味着改变的代码,所以我不介意那些没有被忽略)
有没有办法强制编译器使用相对路径,或欺骗它认为路径不是它是什么?
最后一个的原因是令人讨厌的Windows文件系统.你永远都不知道什么时候删除几个有价值的源和对象,并且svn元数据会因为流氓文件锁而失败.至少创建新根总是成功,而剩下空间.一次运行多个构建也是一个问题.运行一堆虚拟机虽然是一个解决方案,但却是一个相当繁重的虚拟机.
我想知道是否有办法为进程及其子进程设置虚拟文件系统,以便多个进程树将看到不同的 "C:\ build"目录,仅对它们是私有的,所有这些都是同时...重量级的虚拟化......
更新:我们最近在GitHub上开源了这个工具.请参阅文档中的比较部分.
在解释词法分析器和解析器之后,关于如何创建编译器的所有文本都会停止.他们没有解释如何创建机器代码.我想了解端到端流程.
目前我的理解是,Windows exe文件格式称为Portable Executable.我读到了它的标题,我还没有找到一个可以轻松解释这个问题的资源.
我的下一个问题是,我没有看到任何解释机器代码如何存储在文件中的资源.是否像32位固定长度指令一样接一个地存储在该.text
部分?
有没有地方至少解释如何创建一个什么都不做的exe文件(它有一个No Op指令).然后我的下一步是链接到dll文件以打印到控制台.
windows compiler-construction linker executable portable-executable
我在IDA注意到,我分析的PE文件不仅包括该.rdata
部分,还包括.idata
.有什么不同?
如果我通过签名设置时间戳,会发生什么?
如果我没有设置怎么办?
这是必要的吗?为什么推荐?
cryptography code-signing portable-executable trusted-timestamp
我正在寻找可以帮助我在使用C++的非Windows平台上验证Windows PE文件(.exe,.dll,.cab,.etc)的数字签名的示例代码(或库).我正在寻找一种独立于平台的方法.
谢谢!
c++ validation cross-platform digital-signature portable-executable
我正在尝试使用JetBrains dotPeek 1.4符号服务器但是我遇到了一些失败的第三方程序集,dotPeek状态为:
Pdb has not been generated because assembly does not contain debug directory
Run Code Online (Sandbox Code Playgroud)
使用CFF Explorer我发现这些程序集具有空的"调试目录"可移植可执行(PE)标头值.
是否有一种(简单)方法来编辑PE以添加Debug Directory标头值?
我正在重新构建我的构建系统,我已经读过带有grunt的node.js是一个很好的方法.我也没用过,而且我遇到了一些麻烦.
问题是我想建立一个可移植的构建环境,我可以将其包含在我的项目的版本控制中(也许这是不可能的).获取node.js和npm工作一直没有问题.但是,我看到安装grunt的每条指令都说使用-g
带有npm 的标志,它会全局安装它.由于我想要一个完全可移植的环境,我试图将其关闭,但我无法工作.
我错过了什么,或者我试图做的不可行?
Windows是否有可执行文件,我可以在命令shell中运行,它返回可执行文件(.exe)的版本号?
我看到很多问题显示如何使用不同的语言,并引用第三方软件来编写它,但我找不到一个简单的shell命令来执行它.如果我不需要安装任何东西,还有其他要点.
它必须以普通用户身份运行.不是管理员.
windows ×5
c++ ×2
executable ×2
linker ×2
assembly ×1
batch-file ×1
code-signing ×1
command-line ×1
cryptography ×1
debugging ×1
dotpeek ×1
gruntjs ×1
loader ×1
node.js ×1
portability ×1
validation ×1
version ×1
visual-c++ ×1
winapi ×1