我有一个链接描述文件,其中定义了一个包含软件映像校验和的部分。像这样:
...
.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
和bin
文件(使用适当的偏移量)复制与上述相同的步骤,则可以从bin
文件({{ 1}}和elf
给出相同的结果。
我的第一个问题是:我知道您可以使用bin
定义节,但是如果您使用链接器脚本中已经定义的节,此命令是否会更改其行为?将变量放置在该部分中,而不是创建一个新变量?
我的第二个问题是:这是阻止__attribute__((section))
删除此特定部分的唯一方法吗?
答案 0 :(得分:1)
让我们先回答您的第二个问题,
这是防止objcopy删除此特定部分的唯一方法吗?
您需要{strong>部分下的gnu LD manual中记录的概念。
4.6.8.1。输出节类型
每个输出节可以有一个类型。类型是括号中的关键字。定义了以下类型:
NOLOAD
应将该部分标记为不可加载,以便在程序运行时不会将其加载到内存中。
DSECT, COPY, INFO, OVERLAY
支持这些类型名称以实现向后兼容,并且很少使用。它们都有相同的效果:应将该节标记为不可分配,以便在程序运行时不为该节分配内存。
链接器通常根据映射到输出节中的输入节来设置输出节的属性。您可以使用节类型来覆盖它。例如,在下面的脚本示例中,ROM部分的地址为内存位置0,并且在程序运行时无需加载。 ROM部分的内容将照常显示在链接器输出文件中。
SECTIONS {
ROM 0 (NOLOAD) : { … }
…
}
那是什么意思?假设您的对象中有调试信息。如果要刻录ROM映像,则可能不希望将调试信息放入对象中。同样,BSS段全为零,无需将其存储到ROM,但是您需要清除RAM(在加载地址处)以为其预留空间。 .data
部分的'init value'是从ROM初始化的,但位于RAM中。这些概念是“可加载的”和“可分配的”,并且在ELF文件中具有用于它们的标志。默认情况下,您的.my_checksum
没有标志。即,未分配且无法像调试信息一样加载。
我知道您可以使用属性((section))定义节,但是如果您使用链接器脚本中已经定义的节,此命令是否会更改其行为以将变量放入该部分,而不是创建一个新的?
从上面
链接器通常根据映射到输出节中的输入节来设置输出节的属性。
您的输入节标志被您的输出节继承。因此,您至少已分配了可分配的标志。
我建议您将校验和放在.text
或.data
的末尾。例如,输入部分.rodata
(恒定值)通常与输出.text
放在一起。除非您希望保留一些不会影响最终图像的记录,否则通常无需发明其他输出部分。您的__checksum_is_here
标签足以找到它,您可以在CRC上查看this question。