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

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 的未来修订版中有效。

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

【讨论】:

以上是关于如何获取输入部分的大小(将其放在内存末尾)的主要内容,如果未能解决你的问题,请参考以下文章

如何获取可用系统内存的大小?

如何将堆栈对齐到 SRAM 的末尾?

java如何获取一个对象的大小

如何在 Go 中获取变量的内存大小?

如何在没有 WMI 的情况下使用 PowerShell 获取总物理内存大小?

如何获取由函数“malloc”锁定的内存段指针的大小 [重复]