如何获取输入节的大小(将其放置在内存的末尾)

我有以下链接脚本: .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))-不过这是一个语法错误。

那么,如何在不首先将输入部分放入输出部分的情况下获得输入部分的大小呢?

2602 次浏览

Not exactly kosher, but after digging through the source code for GNU ld it looks like you can specify the address of section after it is defined.

The following linker script should give you the desired behavior:

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
}


The output of an empty binary linked with the above script show the correct placement of sections and symbols:

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

Note: I couldn't find any documentation regarding this behavior so I can't guarantee this trick will work in future revisions of ld.

Note: This trick doesn't work for the gold linker.