22

我已经广泛搜索了如何做到这一点,但未能找到答案。

我的内存布局如下:

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

在堆栈的末尾,我放置了堆。它长大了,堆栈是我正在使用的 ARM 芯片的完整降序堆栈。

现在,我想做的是.persist在我的 ram 内存中放置一个单独的部分,我们称之为它。我希望它位于 RAM 的最末端,并且我想将它编程到我的链接器脚本中。但是,这.persist部分的大小不是由我定义的,而是由编译器根据它包含的符号计算出来的。

到目前为止,我还没有想出一个好的方法来做到这一点。因为我知道 RAM 起始地址和 SIZE,所以如果我知道部分大小,计算部分需要去的位置将是微不足道的。但是,根据GNU 链接器文档(第 74 页),似乎:

SIZEOF(section) 返回指定节的大小(如果已分配该节)。如果在评估时该节尚未分配,则链接器将报告错误。

所以我无法计算出链接描述文件中部分的大小(因为我想在放置/分配它之前计算它的大小)。

有谁知道这样做的好方法?

4

5 回答 5

7

通过链接一个两步过程,我能够完成类似的事情。首先,我将相关部分编译为它自己的目标文件。就我而言,我有一个从程序集文件生成的元数据部分。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,我可以在链接器脚本中引用它的大小。

于 2016-09-13T19:23:10.600 回答
4

我设法通过使用链接器命令计算代码的大小来解决它:size。在我的 Makefile 中,我将 SIZE 设置为代码的大小。然后我调用 cpp(预处理器)来计算所有绝对地址(使用 c 语法)。然后我使用生成的链接文件进行链接:tmp.ld

%.elf: %.o
    $(eval SIZE := $(shell arm-none-eabi-size -B $<  | tail -n 1 | awk -F ' ' '{print $$1}'))
    $(CC) -DSEG_SIZE=$(SIZE) -P -E -x c link.ld -o tmp.ld
    $(CC) -o $@ $< $(LDFLAGS)

在 link.ld 文件中,我可以进行各种计算(因为 SEG_SIZE 是一个常数):

#define SEG_LAST_ADDR 1234
#define MY_SEG        (SEG_LAST_ADDR - SEG_SIZE)

MEMORY
{
  bootloader     (rx)  : ORIGIN = MY_SEG,     LENGTH = SEG_SIZE
  ...
}

我终于链接到 tmp.ld 文件。

于 2019-03-12T16:54:30.013 回答
1

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

/* 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
于 2017-04-19T18:24:26.487 回答
-1

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

例如,在这个 Red Hat GNU Linker 文档页面中,您可以将 .data 部分定义为从地址 0x8000000 开始:

SECTIONS
{
  . = 0x10000;
  .text : { *(.text) }
  . = 0x8000000;
  .data : { *(.data) }
  .bss : { *(.bss) }
}
于 2015-04-08T08:45:35.420 回答
-2

我想要做的是在我的 ram 内存中放置一个单独的部分,我们称之为 .persist。我希望它位于 RAM 的最末端,并且我想将它编程到我的链接器脚本中。

链接描述文件有一个名为Location Counter的特殊变量,它允许通过在地址空间中创建间隙或孔来修改当前地址,以及节或符号的大小或地址。

于 2014-11-03T22:08:32.647 回答