c - 了解某些 ELF 文件结构

标签 c gcc linker arm elf

来自 ARM 的信息中心,关于 static linking and relocations 部分:

** Section #1 'ER_RO' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR]
Size : 28 bytes (alignment 4)
Address: 0x00008000
$a
.text
bar
    0x00008000: E59f000C .... LDR r0,[pc,#12] ; [0x8014] = 0x801C
    0x00008004: E5901000 .... LDR r1,[r0,#0]
    0x00008008: E2411001 ..A. SUB r1,r1,#1
    0x0000800C: E5801000 .... STR r1,[r0,#0]
    0x00008010: E12FFF1E ../. BX lr
$d
    0x00008014: 0000801C .... DCD 32796
$a
.text
foo
    0x00008018: EAFFFFF8 .... B bar ; 0x8000

来自ELF for the ARM architecture :

Table 4-7, Mapping symbols
Name Meaning
$a - Start of a sequence of ARM instructions
$d - Start of a sequence of data items (for example, a literal pool)

如您所见,ELF 文件包含一个部分,其中有代码 (bar),然后是 data/ro (32796) ),然后是连续地址中的更多代码 (foo)。

现在,关于任何 SW 文件结构的基本原则是 SW 由不同且独立的部分组成 - text(代码)、data bss。 (和 rodata,如果我们想学究气的话)如果我们检查 MAP 文件,我们可以看到。

那么,这个ELF结构是不符合这个基本原理的,所以我的问题是这里到底是怎么回事?我是否误解了这个基本原则?如果不是,那么这个 ELF 结构是否会在运行时更改以满足部分分离? 为什么 ELF 部分在某个顺序地址空间中包含混合类型?

注意:我假设示例中使用的分散文件是默认文件,因为包含示例的文档没有随示例一起提供任何分散文件。

最佳答案

在运行时,段无关紧要,重要的是程序头中的 PT_LOAD 段。 ELF 规范在那里也非常灵活,但是一些加载器对它们可以处理的 PT_LOAD 段有限制。

以这种方式拆分代码和数据的原因可能是该体系结构仅支持有限范围的 PC 相对寻址,并且需要一个常量池来加载大多数常量(因为通过立即数构造它们太昂贵了)。拥有尽可能少的大常量池是有吸引力的,因为它可以提高数据和指令缓存的利用率(而不是缓存类型不正确且永远无法使用的内存),但如果代码大小超出了可以直接处理的范围。

关于c - 了解某些 ELF 文件结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48753850/

相关文章:

c - 引导加载程序如何在二进制文件中找到 DS 部分

c - 函数声明对于 C 编程来说是必不可少的吗?

c++ - 将 libnoise 库链接到 Visual Studio 2010 中的项目时遇到问题

c - C pthreads 问题和 malloc/seg 错误

c - 使用 pulseaudio API 播放 wav 文件?

c++ - 如何在 g++ 中使用不同的 STL

android - 无法运行由 NDK 编译的 x86 可执行文件

android - 带有 clang 的 Android 上的 LTO - 它应该工作吗?

c++ - 除非复制到新字符串,否则比较从 Lua 中的 C 函数推送的字符串失败

c - 使用 assert 而不是使用简单的 "if"有什么好处?