我有以下链接描述文件:
将.data
和.bss
放在ram中,然后.heap
节将填充剩余的内存。
现在,我想添加一个.noinit
节,该节始终放置在内存的末尾。这样一来,引导加载程序等就会忽略它。
我仍然希望我的.heap
部分占据.bss
和.noinit
之间的所有可用空间,但是为此,我需要知道.noinit
部分的大小。 / p>
幼稚的方法失败了:
/* .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))
-但这是语法错误。
那么如何在不先将其放入输出部分的情况下获得输入部分的大小?
答案 0 :(得分:0)
不完全是 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 的未来修订版中会起作用。
<块引用>注意:此技巧不适用于黄金链接器。