(N)ASM、ELF64 - 内存中的 .data 和 .bss 顺序

(N)ASM, ELF64 - .data and .bss order in memory

我对 .data 和 .bss 部分在内存中的顺序有疑问, 不能 google 我一辈子都做不到。

我想了解是否可以保证 .bss 部分 总是 在内存地址方面位于 .data 部分之后。

我的具体需求是这样的:

section .data
malloc_pointer:
    dq start_of_my_malloc

start_of_data:
; more stuff...

section .bss
; more stuff
start_of_my_malloc:
    resb 1 << 30 ; pre-allocate 1gig

我有时需要使用偏移量 [malloc_pointer] - start_of_data,所以我需要它是正数,因此出现了关于 .bss 和 .data 顺序的问题。


另一方面 - 很高兴知道我是否可以参考标签 start_of_data 来帮助我选择要在 start_of_my_malloc 中保留的尺码。 我真正想做的是:

start_of_my_malloc:
    resb (1 << 30) - start_of_data ; this won't compile though

谢谢!

有关节定位的决定由链接器完成,可以通过 linker scripts(默认或自定义)进行控制。我尽量不依赖它们,因为它们会使您的代码不那么独立。

关于你的第二个问题 - 你可以 assemble 文件一次,从目标文件中提取 .data 的大小,然后用适当的 -DSTART_OF_DATA=... 重新assemble 它。

传统上,内存布局是文本在前,然后是数据,最后是 bss。这种设计是出于方便,因为您可以简单地将整个二进制文件复制到内存中,然后将一块内存清零,然后(可选)设置内存保护。要扩展 bss 段,可以使用 brksbrk 系统调用。

etextedataend三个标签由链接器定义,分别指向文本段末尾、初始化数据末尾和数据段。不存在标签 start,因为程序传统上映射到地址 0,因此不需要标签。

不能保证布局是这样的,但由于相当多的程序依赖于这种设计,因此在不久的将来不太可能改变。

如果你想写一个内存分配例程,我推荐你使用sbrk系统调用。这消除了对布局假设的全部需求,因为 sbrk 总是做正确的事情。

注意 sbrk 今天有点过时了,所以如果你想使用现代的东西,我建议你在 mmap 之上实现你的内存管理。