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

如何在链接脚本中从已有ELF二进制导入符号,避免硬编码地址?

实现方案:无需硬编码地址的Bootloader与应用程序链接流程

可以通过自动提取Bootloader符号并生成动态链接脚本片段的方式实现需求,完全避免硬编码地址,具体步骤如下:

1. 在Bootloader中定义关键符号

首先在Bootloader的链接脚本里,显式定义Bootloader的结束地址(以及其他需要被应用引用的符号),确保这些符号能被工具提取:

/* bootloader.ld 片段 */
MEMORY
{
    FLASH (rx) : ORIGIN = 0x10000000, LENGTH = 0x4A000
    /* RAM 定义... */
}

SECTIONS
{
    /* ...其他段定义... */

    /* 所有Bootloader段完成后,添加结束标记 */
    .end_of_bootloader :
    {
        PROVIDE(__bootloader_end = .);
    } > FLASH

    /* 如需让应用引用其他符号(如配置区地址),同样用PROVIDE声明 */
    PROVIDE(__bootloader_config = 0x10048000);
}

也可以在Bootloader代码中通过属性定义全局符号,效果一致:

// bootloader.c 片段
__attribute__((section(".end_of_bootloader"))) const uint32_t __bootloader_end = 0;

2. 自动生成Bootloader符号链接脚本

在构建流程(如Makefile或Shell脚本)中,编译完bootloader.elf后,用nm工具提取关键符号的地址,生成供应用链接脚本引用的片段文件bootloader_symbols.ld:

# 提取__bootloader_end地址并写入符号文件
nm -n bootloader.elf | grep __bootloader_end | awk '{print "__bootloader_end = 0x" $1 ";"}' > bootloader_symbols.ld

# 提取其他需要的符号(比如__bootloader_config)
nm -n bootloader.elf | grep __bootloader_config | awk '{print "__bootloader_config = 0x" $1 ";"}' >> bootloader_symbols.ld

这个步骤会自动同步Bootloader的地址变化,无需手动修改应用配置。

3. 在应用链接脚本中引用动态符号

修改application.ld,通过INCLUDE命令引入自动生成的符号文件,用动态符号替代硬编码地址:

/* application.ld 片段 */
# 引入Bootloader的动态符号
INCLUDE bootloader_symbols.ld

MEMORY
{
    /* Flash起始地址直接使用__bootloader_end,长度自动计算 */
    FLASH (rx) : ORIGIN = __bootloader_end, LENGTH = 0x10080000 - __bootloader_end
    RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x40000
}

SECTIONS
{
    /* 应用程序段从__bootloader_end开始布局 */
    .text :
    {
        *(.text)
    } > FLASH

    /* ...其他段定义... */
}

4. 在应用代码中引用Bootloader符号

在应用代码中,直接声明需要引用的Bootloader符号为extern即可,链接时会自动从bootloader_symbols.ld获取地址:

// application.c 片段
extern uint32_t __bootloader_end;
extern uint32_t __bootloader_config;

void app_init()
{
    // 访问Bootloader的配置区
    uint32_t boot_cfg = *(uint32_t*)__bootloader_config;
}

构建流程自动化

把上述步骤整合到Makefile中,确保构建顺序为:

  1. 编译并链接生成bootloader.elf
  2. 生成bootloader_symbols.ld
  3. 编译并链接生成application.elf

这样每次修改Bootloader后,应用会自动使用新的起始地址和符号,完全无需手动同步地址。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 01:38:29