认识目标文件的格式—— a.out COFF PE ELF
发布日期:2021-06-29 19:23:40 浏览次数:3 分类:技术文章

本文共 3054 字,大约阅读时间需要 10 分钟。

1.目标文件的常用格式

目标文件是源代码编译后未进行链接的中间文件(Windows的 .obj 和 Linux 的 .o),与可执行文件(Windows 的 .exe 和 Linux 的 ELF)的结构和内容相似,因此跟可执行文件采用同一种格式存储。PC平台常见的可执行文件格式主要有 Windows 的 PE(Portable Executable)和 Linux 的 ELF(Executable and Linkable Format)。PE 和 ELF 都是通用目标文件格式(COFF,Common Object File Format)的变种。在 Windows 下,目标文件(COFF 文件)和可执行文件(PE 文件)统称为 PE-COFF 文件,Linux 统称为 ELF 文件。除此之外,还有些不常用的目标文件与可执行文件格式,比如 Intel 和 Microsoft 以前使用的对象模型文件(OMF,Object Module File)、Unix 最初使用的 a.out 和 MS-DOS 的 .COM 格式等。

不光是可执行文件按照可执行文件格式存储,动态链接库(DLL,Dynamic Linking Library)(Windows的 .dll 和 Linux 的 .so)及静态链接库(Static Linking Library)(Windows 的 .lib 和 Linux 的 .a)都按照可执行文件格式存储。它们在 Windows 下都按照 PE-COFF 格式存储,Linux 下按照 ELF 格式存储。静态链接库稍有不同,它是把所有目标文件打包成一个文件,再加上一些索引,可以简单理解为一个包含很多目标文件的文件包。

Linux 下的 ELF 文件主要有如下几种:

ELF文件类型 说明 实例
可重定位文件(Relocatable File) 包含了代码与数据,可以用来连接成可执行文件或共享目标文件,如目标文件与静态链接库 Linux .o 与 .a,Windows .obj 与 .lib
共享目标文件(Shared Object File) 包含了代码和数据,主要有两种用途,一是与目标文件或其它共享目标文件链接成新的共享目标文件,二是与可执行文件结合,作为进程映像的一部分来运行 Linux .so,Windows .dll
可执行文件(Executable File) 包含了可直接执行的程序 Linux 无后缀的 ELF 可执行文件,Windows .exe 文件
核心转储文件(Core Dump File) 当进程意外终止时,系统可以将该进程的地址空间的内容及终止时的一些其他信息转储到核心转储文件 Linux core dump

Linux 下可以根据 file 命令查看上面表格中列出的四种 ELF 文件的格式。

(1)目标文件 .o。
编译如下代码生成目标文件。

////@file:foo.cpp//#include 
using namespace std;int foo(){ cout<<"hello world"<

编译生成目标文件foo.o:

g++ -c foo.cpp -o foo.o

使用file命令查看foo.o文件类型:

file foo.ofoo.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped

(2)共享目标文件 .so,以 C++ 标准库 /lib64/libstdc++.so.6.0.19 为例。

file /lib64/libstdc++.so.6.0.19/lib64/libstdc++.so.6.0.19: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, BuildID[sha1]=8941888bf8ee9ced585599be5397a385fc1c73ce, stripped

(3)可执行文件,以 GNU 的 Shell /usr/bin/bash 为例。

file /usr/bin/bash/usr/bin/bash: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=d0c7bc3186c85673fb2b14c90ab92eeaa27a18a5, stripped

(4)核心转储文件 core dump。

编译如下代码生成可执行文件a.out,运行a.out访问非法地址NULL后生成core文件。

//@file:main.cpp#include 
using namespace std;int main(){ int* iBar = NULL; cout<<"*iBar"<<*iBar<

编译并运行:

g++ main.cpp./a.outSegmentation fault (core dumped)

使用file命令查看core文件类型:

file core.28355core.28355: ELF 64-bit LSB core file x86-64, version 1 (SYSV), SVR4-style, from './a.out'

可见,Linux下的目标文件.o,共享目标文件.so、可执行文件以及核心转储文件core dump均属于ELF文件。

2.目标文件与可执行文件格式的小历史

目标文件与可执行文件的格式和操作系统和编译器密切相关,不同的系统平台下会有不同的格式,但是这些格式又大同小异,可以说,目标文件与可执行文件格式的历史几乎是操作系统的发展史。

COFF 是由 Unix System V Release 3 首次提出并使用的格式规范,后来 Microsoft 在其基础上,制定了 PE格式标准,并将其应用于自家的 Windows NT 系统。后来,System V Release 4 在 COFF 的基础上引入了ELF 格式,目前流行的 Linux 系统也是以 ELF 作为基本的可执行文件格式。这也是为什么目前 PE 和 ELF 如此相似的原因,因为它们都是源于同一种可执行文件格式 COFF。

在 COFF 之前,Unix最早的可执行文件格式是 a.out 格式,中文意为汇编器输出。因其设计简单,以至于后来共享库出现的时候,a.out 格式变得捉襟见肘,难以满足共享库实现的要求,于是从 Unix System V Release 3 开始被 COF F取代。由于 COFF 格式的设计非常通用,以至于 COFF 的继承者 PE 和 ELF 目前还在被广泛地使用。COFF 的主要贡献是在目标文件中引入了“段”的机制,不同的目标文件可以拥有不同数量及不同类型的段。另外,还定义了调试数据的格式。


参考文献

[1] 俞甲子,石凡.程序员的自我修养——链接、装载与库[M].北京:电子工业出版社,2009-04.C3.1目标文件格式.P56-58

[2]
[3]

转载地址:https://dablelv.blog.csdn.net/article/details/92227310 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Golang 函数耗时统计
下一篇:Golang 方法接收者为值与指针的区别

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2024年04月27日 14时52分35秒