计算机的目标文件是什么? 在程序中充当什么角色?

文章目录

  • 不同系统的目标文件
  • 不同形式的目标文件
    • 1.可重定位目标文件
    • 2.可执行目标文件
    • 3.共享目标文件
  • 参考

不同系统的目标文件

从贝尔实验室诞生的第一个 Unix 系统使用的是 a.out 格式,直到今天,可执行文件仍然称为a.out 文件。

Windows 使用可移植可执行(Portable Executable,PE)格式。

MacOS-X使用 Mach-O格式。

x86-64 Linux和 Unix系统使用可执行可链接格式(Executable and Linkable Format,ELF)。

尽管我们的讨论集中在 ELF 上,但是不管是哪种格式基本的概念是相似的。
目标文件。

不同形式的目标文件

目标文件有3种形式:

1.可重定位目标文件

包含二进制代码和数据,其形式可以在编译时与其他可重定位目标文件合并起来,创建一个可执行目标文件。
计算机的目标文件是什么? 在程序中充当什么角色?_第1张图片

ELF头以一个 16 字节的序列开始,这个序列描述了生成该文件的系统的字的大小和字节顺序。ELF 头剩下的部分包含帮助链接器语法分析和解释目标文件的信息。其中包括 ELF头的大小、目标文件的类型(如可重定位、可执行或者共享的)、机器类型(如 x86-64)、节头部表(section header table)的文件偏移,以及节头部表中条目的大小和数量。不同节的位置和大小是由节头部表描述的,其中目标文件中每个节都有一个固定大小的条目(entry)。夹在 ELF 头和节头部表之间的都是节。

一个典型的 ELF 可重定位目标文件包含下面几个节:

.text:已编译程序的机器代码。

.rodata:只读数据,比如 printf 语中的格式串和开关语句的跳转表。

:bss:未初始化的全局和静态 C变量,以及所有被初始化为0的全局或静态变量。在目标文件中这个节不占据实际的空间,它仅仅是一个占位符。目标文件格式区分已初始化和未初始化变量是为了空间效率,在目标文件中,未初始化变量不需要占据任何实际的磁盘空间。运行时,在内存中分配这些变量,初始值为 0。

用术语.bss 来表示未初始化的数据是很普遍的。它起始于IBM 704 汇编语言(大约在1957年)中“块存储开始(Block Storage Start)”指令的首字母缩写,并沿用至今。一种记住.data和.bss 节之间区别的简单方法是把“bss”看成是“更好地节省空间(Better Save Space)”的缩写。

.symtab:一个符号表,它存放在程序中定义和引用的函数和全局变量的信息。一些程序员错误地认为必须通过-g 选项来编译一个程序,才能得到符号表信息。实际上,每个可重定位目标文件在symtab 中都有一张符号表(除非程序员特意用 STRIP 命令去掉它)。然而,和编译器中的符号表不同,.symtab 符号表不包含局部变量的条目。

rel.text:一个.text 节中位置的列表,当链接器把这个目标文件和其他文件组合时,需要修改这些位置。一般而言,任何调用外部函数或者引用全局变量的指令都需要修改。另一方面,调用本地函数的指令则不需要修改。注意,可执行目标文件中并不需要重定位信息,因此通常省略,除非用户显式地指示链接器包含这些信息。

.rel.data: 被模块引用或定义的所有全局变量的重定位信息。一般而言,任何已初始化的全局变量,如果它的初始值是一个全局变量地址或者外部定义函数的地址,都需要被修改。

.debug:一个调试符号表,其条目是程序中定义的局部变量和类型定义,程序中定义和引用的全局变量,以及原始的 C 源文件。只有以-g 选项调用编译器驱动程序时,才会得到这张表。

.line:原始 C源程序中的行号和text 节中机器指令之间的映射。只有以-g 选项调用编译器驱动程序时,才会得到这张表。

.strtab:一个字符串表,其内容包括.symtab 和.debug 节中的符号表,以及节头部中的节名字。字符串表就是以 nul1结尾的字符串的序列。

2.可执行目标文件

包含二进制代码和数据,其形式可以被直接复制到内存并执行。

可执行目标文件是一种包含计算机程序可直接运行的二进制代码的文件。这种文件包含了经过编译和链接处理后的机器代码,可以由操作系统加载到内存中并执行。可执行目标文件通常是由编译器和链接器生成的,其文件格式与特定的操作系统和硬件体系结构相关。

在不同的操作系统中,可执行目标文件可能采用不同的文件格式。

  1. Windows 可执行文件(PE,Portable Executable): 用于 Microsoft Windows 操作系统,包括可执行文件(.exe)、动态链接库(.dll)等。

  2. Linux 可执行文件(ELF,Executable and Linkable Format): 用于大多数 Linux 发行版,包括可执行文件、共享库等。

  3. macOS 可执行文件(Mach-O): 用于 macOS 操作系统,包括可执行文件、动态链接库等。

  4. DOS 可执行文件(COM,EXE): 用于早期的 MS-DOS 等操作系统。

  5. Java 可执行文件(JAR,Java Archive): 用于包含 Java 字节码的可执行文件。

可执行目标文件中包含了程序的机器代码、数据段、符号表、重定位信息等。当执行这个文件时,操作系统会加载它到内存中,并按照文件中的信息执行程序。可执行目标文件的生成过程包括编译、链接和可能的优化步骤,确保程序可以在目标环境中正确运行。

3.共享目标文件

一种特殊类型的可重定位目标文件,可以在加载或者运行时被动态地加载进内存并链接。

从技术上来说,一个目标模块(object module)就是一个字节序列,而一个目标文件(object file)就是一个以文件形式存放在磁盘中的目标模块。

共享目标文件(Shared Object File)是一种包含可执行代码和数据的二进制文件,它可以在运行时被多个程序或进程共享。共享目标文件通常有 .so(Linux/Unix)或 .dll(Windows)的文件扩展名。

下面是关于共享目标文件的一些关键特点和用途:

  1. 动态链接: 共享目标文件是通过动态链接方式加载到内存中的。这意味着多个程序可以在运行时共享同一个文件的实例,而不是每个程序都有一个独立的拷贝。

  2. 节省内存: 由于多个程序可以共享同一个共享目标文件的实例,可以减少内存的占用,提高系统的效率。

  3. 运行时链接: 共享目标文件在程序执行的过程中被动态链接到内存,而不是在编译时将所有代码静态链接到一个可执行文件中。这允许在程序运行时加载新的共享库,支持动态插件和模块化设计。

  4. 符号解析: 共享目标文件可能包含了符号表,以便在加载时进行符号解析,确保正确地解析函数和变量的引用。

  5. 符号导出和导入: 共享目标文件中的函数和变量可以被导出,以便其他程序可以引用。同时,程序在链接时可以导入其他共享目标文件中的符号。

动态链接库(DLL)在 Windows 系统中,共享目标文件通常被称为动态链接库(DLL)。它们是可执行代码和数据的集合,可以由多个程序动态链接到内存中。

共享目标文件的使用可以提高系统的灵活性、可维护性和资源利用率。

在类Unix系统中,共享目标文件在共享库(shared library)的概念下发挥着重要作用。

参考

《深入理解计算机系统》

你可能感兴趣的:(Linux,linux,c语言)