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

时间:2019-05-19 21:32:00

标签: c ld

我有以下链接描述文件: 将.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))-但这是语法错误。

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

1 个答案:

答案 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 的未来修订版中会起作用。

<块引用>

注意:此技巧不适用于黄金链接器。