我正在了解elf文件。我读了一些东西,对它的了解却很少,但是有些事情困扰着我。我想继续学习并掌握它,但是首先我要确保自己做对了最简单的事情。我将在下面声明我所知道的,请纠正我犯错的地方。
当您编写C应用程序并对其进行编译时(例如使用gcc),它将被翻译成代表代码和数据的机器指令。调用编译器的输出是一个elf文件。elf文件包含(除其他事项外)一个节标头,该节标头基本上是一系列Elf64_Shdr,每个该标头用于编译的应用程序包含的每个节。因此,基本上,一个部分只是一些机器指令,它们代表代码或数据,以及一些有关其的信息,例如它的位置(第一条指令的地址)和长度(大小),可写或可读(一些标志) )等我对节和节标题的理解正确吗?
[当我们运行make命令并将其传递给elf文件时,链接器开始起作用,并查看编译器创建的所有节的名称和属性,并按照ld脚本文件的规则将它们分组为'segments',创建我们可以运行的可执行文件因此,基本上,片段不过是在具有特定名称的公共部分中分组给gheter的相同属性的部分。这对吗?
然后,当我们实际运行所创建的可执行文件时,加载程序开始工作,查看链接程序创建的这些段,并通过读取其中包含的信息,将机器指令映射到各个内存位置,以便进程可以运行。这就是所谓的(按照我的理解)内存映像。对吗?
感谢您阅读并帮助我清除我的疑问,谢谢。
您的描述中存在多个不准确之处,目前尚不清楚您是不准确地理解所涉及的处理还是描述。
[编写C应用程序并对其进行编译时(例如使用gcc),它将被翻译成代表代码和数据的机器指令。
这并不完全准确:“机器指令”和“机器代码”之间存在区别。
[编译.c
文件时,某些编译器会将其转换为机器指令(汇编),然后将其传递给汇编器以产生机器代码(GCC会这样做)。其他编译器已经集成了汇编器,并有效地跳过了汇编生成步骤(Clang就是这样做)。
调用编译器的输出是一个elf文件。
在some而不是all系统上,编译的结果是可重定位的ELF文件。其他系统会生成其他格式的目标文件,例如XCOFF或Mach-O。
elf文件包含(除其他事项外)一个节头,该节头基本上是一系列Elf64_Shdr,每个编译的应用程序包含的每个节。
application尚未构建,因此不准确。同样,Elf64_Shdr
仅适用于64位ELF平台;在32位计算机上,它是Elf32_Ehdr
。
当我们运行make命令时
make
命令与nothing无关。它仅在适当时调用编译器和链接器(或其他工具)。您可以将其替换为Shell脚本,也可以只手动键入命令。
并将其传递给elf文件
链接步骤涉及一个或更多(通常是更多)可重定位的ELF
对象文件,档案库和动态库。
链接器会起作用,并查看由编译器创建的所有部分的名称和属性,并按照ld脚本文件的规则将它们分组为'segments'[段]”>
要了解链接器是什么,您可以阅读此series of blog posts。
您的描述使链接程序的工作变得无关紧要。链接器更加复杂,并执行您未提及的重定位解析以及许多其他任务。
并创建我们可以运行的可执行文件。
通常是。
您可以要求链接程序将几个可重定位的目标文件组合成一个[[combined
目标文件(带有ld -r foo.o bar.o -o combined.o
),在这种情况下,结果将not是一个可执行文件。您还可以要求链接器链接共享库,而不是链接可执行文件。因此,基本上,片段无非就是将具有相同名称的相同属性的片段分组到具有特定名称的公共片段中。假。与链接在一起的部分相比,
lot
链接要多得多。
然后,当我们实际运行所创建的可执行文件时,加载程序便开始起作用
加载程序仅对动态链接的可执行文件起作用。完全静态的可执行文件没有加载程序,而是由内核本身直接启动。
并查看链接器创建的这些段,并通过阅读其中包含的信息,将机器指令映射到各个内存位置,以便进程可以运行。这就是所谓的(按照我的理解)内存映像。
最正确。内存映像的某些部分根本不是来自磁盘的(例如,线程本地存储和组合的.bss
节的内容)