相信很多同学知道Windows下的可执行程序是*.exe,但是除了*.exe之外,Windows下动态库*.dll和*.lib也是可执行程序。不过,小师妹问沃的是什么是Linux下的可执行程序?
为了不让小师妹伤心,师兄沃再次拿起《程序员的自我修养》第三章肝了一晚上,呕心沥血才完美回答出小师妹的问题,回答让小师妹十分满意,对师兄好感爆棚。好了,吹牛到此为止,正经脸(咳咳咳 ^_^),接下来让我们来看看师兄回答了什么,让小师妹万分满意?
一、目标文件格式
现在PC平台流行的可执行文件格式(executable)主要是Windows下的PE(Portable Executable)和Linux下的ELF(Executable Linkable Format),它们都是COFF(Common file format)格式的变种。其中,Windows下可执行文件还包括动态链接库(DLL,Dynamic Linking Library)和静态链接库(lib,Static Linking Library),Linux下动态链接库(*.so)和静态链接库(*.a)以及目标文件object(*.o)。在Windows下可执行文件按PE-COFF格式存储,Linux下按照ELF格式存储。ELF可以理解为是一系列的目标文件或者加上链接库组合而成的文件包。下面是ELF文件类型和说明。
ELF文件类型 | 说明 | 实例 |
---|---|---|
可重定位文件 (Relocatable File) |
这类文件包含了代码和数据,可以被用来链接成可执行文件或共享目标文件,静态链接库也可以归类为这一类 | Linux的*.o文件 Windows的*.obj文件 |
可执行文件 (Executable File) |
这类文件包含了可以直接执行的程序,它的代表就是ELF可执行文件,它们一般都没有扩展名 | 比如/bin/bash文件 Windows的*.exe文件 |
共享目标文件 (Shared Object File) |
这类文件包含了代码和数据,可以在一下两种情况使用, 一种是连接器可以使用这种文件跟其它的可重定位文件和共享目标文件链接,产生新的目标文件; 另一种是动态链接器可以将几个这种共享目标文件与可执行文件结合,作为进程映像的一部分来运行。 |
Linux的*.so,如/lib/glibc-2.5.so Windows的DLL |
核心转存储文件 (Core Dump File) |
当进程意外中职生时,系统可以将该进程的地址空间的内容及终止时的一些其他信息转存储到核心转存储文件 | Linux下的Core dump |
- 小知识:Unix的可执行程序是*.out;COFF主要贡献在目标文件引入“段”机制。
二、目标文件结构
2.1样例代码
我们先给小师妹上一段经典代码,惊呆小师妹一脸。
(注:文本分析的是ubuntu20.04 x86 64位系统下的ELF文件)
#include <iostream>
int globalVar1 = 100;
int globalVar2;
void fun1(int var)
{
std::cout<<var<<std::endl;
}
struct St
{
St() : var(200) {}
~St() {}
int getVar() const {return var;}
private:
int var;
};
int main(int arc, char* argv[]) {
static int staticVar1 = 666;
static int staticVar2;
int var1 = 555;
int var2;
fun1(staticVar1 + staticVar1 + var1 + var2);
return 0;
}
2.2生成可执行文件
编译成main.o文件命令如下:(-c表示只编译不链接)
g++ -c main.cpp -o main.o
编译成main文件命令如下:
g++ main.cpp -o main
2.3分析main.o文件
Linux下查看和操作目标文件许多工具,比如hexdump、objdum、objcopy、readelf,本文主要介绍ELF的文件结构,故主要用objdump工具足够,具体文件结构里面每个部分将在下一篇文章结合源码详细分析。
查看main.o内部结构命令
objdump -h main.o