如何获取输入部分的大小(将其放在内存末尾)
Posted
技术标签:
【中文标题】如何获取输入部分的大小(将其放在内存末尾)【英文标题】:How to get the size of an input section (to place it at the end of memory) 【发布时间】:2019-10-06 07:22:11 【问题描述】:我有以下链接器脚本:
.data
& .bss
被放入内存中,然后.heap
部分填充剩余的内存。
现在我想添加一个始终放在内存末尾的.noinit
部分。所以它会被引导加载程序等忽略。
我仍然希望我的.heap
部分占据.bss
和.noinit
之间的所有可用空间,但为此我需要知道.noinit
部分的大小。
一种天真的方法失败了:
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
. = ALIGN(4);
_sbss = . ;
_szero = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
_ezero = .;
> ram
/* heap section */
.heap (NOLOAD) :
. = ALIGN(4);
_sheap = . ;
. = ORIGIN(ram) + LENGTH(ram) - SIZEOF(.noinit);
_eheap = . ;
> ram
/*
* collect all uninitialized sections that go into RAM
*/
.noinit (NOLOAD) :
. = ALIGN(4);
__noinit_start = .;
*(.noinit)
__noinit_end = .;
> ram
这里SIZEOF(.noinit)
始终为 0,因为该部分是在该语句之后定义的。
但实际上我想要的是SIZEOF(*(.noinit))
- 但是这是一个语法错误。
那么如何在不先将输入部分放入输出部分的情况下获得输入部分的大小?
【问题讨论】:
在这里查看一些有趣的答案/cmets:***.com/questions/18647590/… 回答这里可以得到你想要的:***.com/a/55126837/3869724 【参考方案1】:不完全是 kosher,但在挖掘了 GNU ld 的 source code 之后,看起来您可以在定义部分后指定它的地址。
以下链接描述文件应该为您提供所需的行为:
MEMORY
ram (rwx) : ORIGIN = 0x10000, LENGTH = 0x0002000
SECTIONS
.bss (NOLOAD) :
. = ALIGN(4);
_sbss = . ;
_szero = .;
*(.bss .bss.*)
*(COMMON)
/* Note: Just for example - padding .bss by 0x100 bytes so its not empty */
. = 0x100;
. = ALIGN(4);
_ebss = . ;
_ezero = .;
> ram
/* create .noinit section */
.noinit (NOLOAD):
. = ALIGN(4);
__noinit_start = .;
/* Note: Just for example - padding .noinit by 0x100 bytes so its not empty */
. = 0x100;
*(.noinit)
__noinit_end = .;
> ram
/* place .heap after .bss */
.heap _ebss (NOLOAD) :
. = ALIGN(4);
_sheap = . ;
. = ABSOLUTE(ORIGIN(ram) + LENGTH(ram) - SIZEOF(.noinit));
_eheap = . ;
> ram
/* update .noinit to be placed at end of heap */
.noinit _eheap (NOLOAD) : > ram
与上述脚本链接的空二进制文件的输出显示了节和符号的正确位置:
echo | gcc -x c++ - -nostartfiles -T linkerScript.ld -Xlinker --orphan-handling=discard -fuse-ld=bfd && objdump -th a.out
a.out: file format elf64-x86-64
Sections:
Idx Name Size VMA LMA File off Algn
0 .bss 00000100 0000000000010000 0000000000010000 00001000 2**0
ALLOC
1 .noinit 00000100 0000000000011f00 0000000000011f00 00001000 2**0
ALLOC
2 .heap 00001e00 0000000000010100 0000000000010100 00001000 2**0
ALLOC
SYMBOL TABLE:
0000000000010000 l d .bss 0000000000000000 .bss
0000000000011f00 l d .noinit 0000000000000000 .noinit
0000000000010100 l d .heap 0000000000000000 .heap
0000000000010100 g .heap 0000000000000000 _sheap
0000000000010000 g .bss 0000000000000000 _sbss
0000000000010000 g .bss 0000000000000000 _szero
0000000000010100 g .bss 0000000000000000 _ebss
0000000000010100 g .bss 0000000000000000 _ezero
0000000000011f00 g .noinit 0000000000000000 __noinit_start
0000000000012000 g .noinit 0000000000000000 __noinit_end
0000000000011f00 g .heap 0000000000000000 _eheap
注意:我找不到有关此行为的任何文档,因此我不能保证此技巧在 ld 的未来修订版中有效。
注意:此技巧不适用于黄金链接器。
【讨论】:
以上是关于如何获取输入部分的大小(将其放在内存末尾)的主要内容,如果未能解决你的问题,请参考以下文章