链接器脚本 - 将一个部分放在内存区域的末尾

时间:2013-09-05 23:33:55

标签: c++ c memory linker linker-scripts

我已经广泛搜索了如何做到这一点并未能得出答案。

我的内存布局如下:

Fake Address | Section
     0       |  text
     7       |  relocate
    15       |  bss
    23       |  stack

在堆栈的末尾,我放置了堆。它正在成长,堆栈是我正在使用的ARM芯片的完全下降堆栈。

现在,我想要做的是将一个部分(我称之为.persist)放入我的ram内存中。我希望它驻留在RAM的最后,我想将其编程到我的链接器脚本中。但是,这个.persist部分的大小不是由我定义的,而是由编译器根据它包含的符号计算的。

到目前为止,我还没有想出一个好办法。因为我知道RAM起始地址和SIZE,如果我知道部分大小,那么计算部分需要去的位置是微不足道的。但是,根据the GNU linker documentation (pg 74),它似乎是:

  

SIZEOF(section)返回named的大小(以字节为单位)   部分,如果该部分已分配。   如果在评估此部分时尚未分配该部分,则链接器将   报告错误。

所以我无法弄清楚链接器脚本中节的大小(因为我想在放置/分配它之前计算大小)。

有没有人知道这样做的好方法?

4 个答案:

答案 0 :(得分:5)

我能够通过连接两个步骤来完成类似的事情。 首先,我将有问题的部分编译为自己的目标文件。在我的例子中,我有一个从汇编文件生成的元数据部分。 gcc -c会将源代码编译为目标文件,但不会链接它们。

gcc -c  metadata.s  -o metadata.o

您还可以构建整个程序,然后使用objcopy提取相关部分。

gcc -c  main.cc  -o main.o
objcopy --only-section=.metadata  main.o  metadata.o

现在我构建并链接程序的其余部分,并在链接器的输入中包含目标文件。

gcc metadata.o  ../main.o  -o Program.elf  -T linkerscript.ld   

链接器从目标文件中读取.metadata部分,我可以在链接描述文件中引用它的大小。

答案 1 :(得分:2)

我有类似的问题 我是这样做的

/* heap section */
.heap (NOLOAD):
{
    . = ALIGN(8);
     _sheap = .;
    . = . + HEAP_SIZE;
    . = ALIGN(8);
    _eheap = .;
} > ram

_ram_end_ = ORIGIN(ram) + LENGTH(ram) -1 ;
_stack_size = _ram_end_ - _eheap ;

/* stack section */
.stack (NOLOAD): 
{
    . = ALIGN(8);
    _sstack = .;
    . = . + _stack_size;
    . = ALIGN(8);
    _estack = .;
} > ram

.LastSection (NOLOAD): /* for test in dump file */
{
    . = ALIGN(8);
} > ram

答案 2 :(得分:0)

您可以在特定位置强制执行部分。

例如,在此Red Hat GNU链接器文档page中,您可以将.data部分定义为从地址0x8000000开始:

SECTIONS
{
  . = 0x10000;
  .text : { *(.text) }
  . = 0x8000000;
  .data : { *(.data) }
  .bss : { *(.bss) }
}

答案 3 :(得分:-1)

  

我想要做的是放置一个部分,让我们称之为.persist,进入我的ram内存。我希望它驻留在RAM的最末端,我想将其编程到我的链接器脚本中。

链接器脚本具有名为Location Counter的特殊变量,它允许通过在地址空间中创建间隙或孔来修改当前地址,以及部分或符号的大小或地址。