如果从部分中删除 NOLOAD,则从 elf 文件生成的二进制文件会爆炸

Generated binary file from elf file explodes if NOLOAD is removed from section

我们有一个链接描述文件,其中包含出于某些 IEC 合规性测试原因而添加的自定义部分。但是,自从添加此部分后,通过 objcopy -O binary input output 创建的二进制大小已从 ~150kbytes 激增至 ~512Mbytes。

我已将其追溯到缺少 (NOLOAD) 属性的部分。而且我也可以从某种程度上解释为什么二进制文件是 512Mbytes。

我们的记忆如下:

MEMORY
{
    rom    (rx)  : ORIGIN = 0x00000000, LENGTH = 0x00040000
    ram    (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00007580

    CUSTOM_SECTION (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00001000
}

最初定义的部分是:

    CUSTOM_LOCATION:
    {
        CUSTOM_BEGIN = .;
        KEEP(*(CUSTOM_LOCATION));
        CUSTOM_END = .;

    } > CUSTOM_SECTION AT > ram

如果CUSTOM_LOCATION:替换为CUSTOM_LOCATION (NOLOAD):生成的二进制文件是正常的。没有 (NOLOAD) 二进制大小是 ~512Mbytes。

我正在寻找这个二进制文件变得如此之大的原因。 (NOLOAD)(或没有它)对 objcopy 生成二进制文件意味着什么?

第二个问题,在本节末尾我们说 } > CUSTOM_SECTION AT > ram 我们可以不用这个指令吗?可以直接换成} > ram吗? (我可以从 MEMORY 部分删除 CUSTOM_SECTION 吗?

我在生成的 map 文件中没有发现任何差异

当 objcopy 创建二进制文件时,它基本上与 OS ELF 加载器执行相同的工作:它将可加载的 ELF 文件部分写入代表 运行 时间的内存的文件中。

二进制文件将包含您的代码和数据的每个字节,从基地址到最高字节。如果内存映像是稀疏的(有 "nothing" 的区域),那么二进制文件也会包含大面积的空白。这只能在哑二进制文件中表示为零。

您的 elf 文件包含从地址 0x00000000(ROM 的基址)到 0x20000fff(CUSTOM_SECTION 的顶部)的数据,范围刚好超过 500MB,因此按理说二进制文件文件必须有那么多字节才能容纳所有内容。通过使该部分不可加载,您是说在 运行 时间不需要数据,因此不需要在二进制图像中。这通常是调试信息、注释和其他非程序 ELF 数据的情况。

好消息是 a) 许多文件系统只会将磁盘 space 用于文件的非零部分,因此它使用的磁盘并不像看起来那么多(a "sparse file"), b) 二进制文件很容易压缩。