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

能否从单个源文件按ELF段生成多个目标文件?

解决方案:通过GNU Binutils拆分目标文件(无需额外工具)

可以利用GCC工具链自带的objcopy(属于GNU Binutils,不属于elfutils类外部工具),从单个源文件生成的目标文件中按ELF段提取内容,生成独立的目标文件,完美适配你的受控构建环境和嵌入式空间需求。

具体步骤

假设你的源文件dynamic_syms.c通过宏将符号指定到自定义段(比如__my_initcalls):

#define INITCALL(fn) \
    static void fn(void) __attribute__((used, section("__my_initcalls")))

INITCALL(foo_init) { /* 初始化逻辑 */ }
INITCALL(bar_init) { /* 初始化逻辑 */ }
// 更多注册符号
  1. 编译源文件为完整目标文件
    先将源文件编译成包含所有段的目标文件:

    # 替换为你的交叉编译工具链前缀
    arm-linux-gnueabihf-gcc -c dynamic_syms.c -o dynamic_syms.o
    
  2. 按ELF段提取独立目标文件
    使用objcopy的--only-section参数,提取指定段到单独的目标文件:

    arm-linux-gnueabihf-objcopy --only-section=__my_initcalls dynamic_syms.o initcalls.o
    

    若源文件包含多个自定义段(比如__my_cmds),可重复此命令生成多个目标文件:

    arm-linux-gnueabihf-objcopy --only-section=__my_cmds dynamic_syms.o commands.o
    
  3. 归档独立目标文件为小型静态库
    将提取出的目标文件单独归档,避免影响其他库:

    arm-linux-gnueabihf-ar rcs libinitcalls.a initcalls.o
    
  4. 链接时精准保留符号
    链接主二进制时,仅对这个小型库使用-Wl,-whole-archive,确保段内所有符号被保留,同时不浪费空间:

    arm-linux-gnueabihf-gcc main.o -o firmware -L. \
        -Wl,-whole-archive -linitcalls -Wl,-no-whole-archive \
        -lother_required_libs
    

为什么这个方案适合你

  • 无需额外工具:objcopy是GCC交叉编译工具链的标准组件,受控环境通常允许使用。
  • 无空间浪费:仅对包含目标段的小型库启用whole-archive,不会引入无关符号。
  • 无需提前知晓符号名:仅需指定段名即可提取所有对应符号,避开GCC 8.4不支持通配--undefined的限制。
  • 灵活拆分:可按任意ELF段拆分目标文件,适配类似U-Boot命令注册、Linux initcall的动态符号场景。

验证方法

可以用objdump -h initcalls.o查看提取后的目标文件,确认仅包含指定段;再用nm -D firmware检查主二进制中是否存在所有目标符号。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 00:56:28