You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何objcopy会从ARM裸机程序二进制文件中移除startup段?

ARM裸机项目自定义启动段转二进制丢失问题解决

你遇到的问题核心是自定义的STARTUP_SECTION段缺少ALLOC(内存分配)属性,并非默认是NOLOAD类型。

原因分析

GNU汇编的.section指令中,第二个参数的属性字符决定了段的特性:

  • "x"仅表示段是可执行的,但没有告诉链接器需要为该段分配内存空间。
  • 只有带有"a"(ALLOC)属性的段,链接器才会将其标记为需要加载到目标内存的段。没有这个属性的段,虽然会保留在ELF文件中,但objcopy生成二进制镜像时会跳过这类无需加载的段——这就是你看到.startup段在ELF里存在但二进制里缺失的原因。

你的汇编代码里只写了.section STARTUP_SECTION, "x",遗漏了"a"属性,导致链接后的段不具备ALLOC标记。

解决方法

方法1:修改汇编代码的段属性

在section定义里加上"a"属性,同时保留"x"(可执行):

.section STARTUP_SECTION, "ax"
_reset:
    b reset_handler     @ Reset
    b .                 @ Undefined instruction
    b .                 @ SWI
    b .                 @ Prefetch Abort
    b .                 @ Data Abort
    b .                 @ reserved
    b .                 @ IRQ
    b .                 @ FIQ

reset_handler:
    @ some code here
    b .

@ then .text and .data section

"ax"表示该段既是可执行的,又需要分配内存空间。重新编译链接后,段会被标记为ALLOC,objcopy转二进制时就会包含这段内容。

方法2:在链接脚本中显式指定段加载属性

如果不想修改汇编代码,可以在链接脚本的.startup段定义中,通过AT()指定加载地址,并确保段被分配到内存区域:

ENTRY(_reset)
SECTIONS
{
    . = 0;
    .startup . : AT(0)
    {
        startup.o (STARTUP_SECTION)
        reset_section_end = .;
    } >ROM  # 根据你的实际内存类型调整

    .text . : {*(.text)}
    .data . : {*(.data)}
    .bss  . : {*(.bss COMMON)}
}

不过更推荐方法1,因为这是从根源上给段设置正确的属性,逻辑更清晰。

验证

修改后重新编译链接,用arm-none-eabi-readelf -S startup.elf查看段信息,你会看到.startup段的属性中包含ALLOC和EXECINSTR标记,此时再执行arm-none-eabi-objcopy -O binary startup.elf startup.bin,生成的二进制文件就会包含启动段的内容了。

内容的提问来源于stack exchange,提问作者ardabro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 10:30:44