1

我有一个链接器脚本,我在其中定义了一个包含软件映像校验和的部分。就像是:

...
.my_checksum :
  {
    __checksum_is_here = .;
    KEEP (*(.my_checksum))
    . = ALIGN(4);
    _sw_image_code_end = .;  
  } > IMAGE
...

使用 . 将校验和放入该部分objcopy --update-section

elf我使用编译器构建了一个文件arm gcc,我可以在其中看到此部分及其值:

> arm-none-eabu-objdumph -h my_elf_file.elf
...
0 .text         0001496c  08010000  08010000  00010000  2**4
...
7 .my_checksum     00000004  080250c0  080250c0  000350c0  2**2
...

// Notice that 000350c0 is the file offset and 080250c0 is the LMA.
// The starting LMA is 08010000

我可以检索它的值:

> xxd -s 0x000350c0 -l 4 my_elf_file.elf
000350c0: 015e 028e // I have checked this value and it is correct.

现在我bin通过执行生成一个文件

> arm-none-eabi-objcopy -O binary --gap-fill 0xFF -S my_elf_file.elf my_elf_file.bin

现在,如果我尝试再次读取校验和值,使用校验和 LMA 和第一部分 LMA 之间的差异(见上文):

> xxd -s 0x150c0 -l 4 my_elf_file.bin

我这里得到的结果和elf文件中得到的结果不同,就是校验和部分已经被objcopy去掉了。(至少我是这么认为的)。

不过,如果我在我的main.c文件中定义它:

static volatile unsigned int __aux_checksum __attribute__((section(".my_checksum")));
...
int main() {
  ...
  ((void)__aux_checksum); // Avoid compiler/linker optimizations.
  ...
}

elf现在,如果我用and文件复制与上述相同的步骤bin(使用适当的偏移量),我可以从bin文件中检索校验和(elfbin给出相同的结果)。

问题

我的第一个问题是:我知道您可以使用 定义一个部分__attribute__((section)),但是如果您使用链接描述文件中已经定义的部分,此命令是否会更改其将变量放置在该部分中的行为,而不是创建一个新的?

我的第二个问题是:objcopy这是防止删除此特定部分的唯一方法吗?

4

1 回答 1

1

让我们先回答你的第二个问题,

这是防止 objcopy 删除此特定部分的唯一方法吗?

您需要gnu LD 手册中SECTIONS下记录的概念。


4.6.8.1。输出段类型

每个输出部分可能有一个类型。类型是括号中的关键字。定义了以下类型:

NOLOAD

该部分应标记为不可加载,以便在程序运行时不会将其加载到内存中。

DSECT, COPY, INFO, OVERLAY

支持这些类型名称是为了向后兼容,并且很少使用。它们都具有相同的效果:该部分应标记为不可分配,以便在程序运行时不为该部分分配内存。

链接器通常根据映射到输出节的输入节设置输出节的属性。您可以使用节类型覆盖它。例如,在下面的脚本示例中,ROM 部分在内存位置 0 处寻址,并且在程序运行时不需要加载。ROM 部分的内容将照常出现在链接器输出文件中。

SECTIONS {
  ROM 0 (NOLOAD) : { … }
  …
}

那是什么意思?假设您的对象中有调试信息。如果您正在刻录 ROM 映像,您可能不想将调试信息放在对象中。同样,BSS 段全为零,无需将其存储到 ROM 中,但您需要清除我们的 RAM(在加载地址处)为它让路。该.data部分的“初始值”从 ROM 初始化,但驻留在 RAM 中。这些概念是“可加载的”和“可分配的”,它们在 ELF 文件中具有它们的标志。默认情况下,您.my_checksum不会获得任何标志。即,未分配且不可加载,如调试信息。

我知道您可以使用属性((section)) 定义一个部分,但是如果您使用链接描述文件中已定义的部分,此命令是否会更改其将变量放置在该部分中的行为,而不是创建一个新的?

综上所述,

链接器通常根据映射到输出节的输入节设置输出节的属性。

您的输入部分标志由您的输出部分继承。所以你至少把可分配的作为一个标志。

我建议您将校验和放在.textor的末尾.data。例如,输入部分.rodata(常量值)通常与输出一起放置.text。通常不需要发明另一个输出部分,除非你想要一些不会得到最终图像的簿记。您的__checksum_is_here标签足以找到它,您可以在 CRCs 上查看此问题。

于 2019-02-22T17:14:09.010 回答