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

GCC环境下裸机应用中无需汇编代码获取自定义段大小的可行性问询

回答

无需汇编代码获取自定义段大小

当然可以!你完全可以跳过汇编代码,直接在C语言中引用链接脚本里定义的段起始和结束符号。具体做法很简单:

  1. 在C代码中声明链接脚本里的_modules_s和_modules_e为外部符号,推荐用字符数组类型来表示地址——这样我们可以直接通过数组名拿到地址,而且减法操作会直接得到段的字节数:
extern char _modules_s[];
extern char _modules_e[];
  1. 直接计算段大小和模块数量:
// 计算自定义段的总字节数
size_t modules_section_size = (size_t)(_modules_e - _modules_s);
// 计算模块总数(AArch64架构下函数指针占8字节,按需调整)
size_t module_count = modules_section_size / sizeof(int (*)(void));

这样就彻底摆脱了汇编代码,GCC本身就支持直接访问链接器定义的全局符号。


无需链接脚本的实现方式

GNU链接器(ld)有个实用的内置特性:当你使用自定义段时,它会自动为该段生成__start_<section_name>和__stop_<section_name>符号,分别对应段的起始和结束地址。利用这个特性,你可以完全省去自定义链接脚本。

步骤1:优化宏定义(防止指针被优化)

为了避免编译器因为没有直接引用函数指针变量,就把它优化掉,需要给宏加上__attribute__((used))属性:

#define _ADD_FUNC_PTR(_section, _func) \
int (*fp_ ## _func)(void) \
__attribute__((section(#_section), used)) \
= _func ;

步骤2:引用链接器自动生成的段符号

直接用链接器自动生成的__start_.modules和__stop_.modules符号(注意段名里的.要保留):

extern char __start_.modules[];
extern char __stop_.modules[];

步骤3:计算段信息并调用初始化函数

和之前的逻辑一样计算大小和数量,然后遍历调用所有模块的初始化函数:

size_t section_size = (size_t)(__stop_.modules - __start_.modules);
size_t module_count = section_size / sizeof(int (*)(void));

// 遍历调用所有模块初始化函数
int (**modules)(void) = (int (**)(void))__start_.modules;
for (size_t i = 0; i < module_count; i++) {
    modules[i]();
}

额外注意事项

  • 如果你的段需要特定对齐(比如之前的4K对齐),可以在宏里加上aligned属性:
    #define _ADD_FUNC_PTR(_section, _func) \
    int (*fp_ ## _func)(void) \
    __attribute__((section(#_section), used, aligned(4096))) \
    = _func ;
    
  • 大部分现代GCC/ld版本都支持这个自动生成段符号的特性,无需担心兼容性问题。

这种方式既省去了汇编代码,又不用手动维护链接脚本,整体更简洁也更易维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 05:37:31