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

如何在GNU链接器脚本中获取C符号大小,实现堆与变量的地址布局

GNU链接器脚本:低地址堆+高地址全局变量实现方案

需求

在APPL_STATE内存段中同时放置:

  • 可变长度堆(位于低地址,可向高地址扩展)
  • 全局变量foo(位于高地址)
    要求无需硬编码foo的大小,由链接器自动计算空间。

原实现(堆在高地址)

原脚本将全局变量放在低地址,堆占据剩余高地址空间:

MEMORY {
    APPL_STATE  (rwx): ORIGIN = 0x002B8000, LENGTH = 0x00030000 /* 192kb */
}

SECTIONS
{
    .shared_state (NOLOAD) : ALIGN(16) {
        *(SORT_BY_ALIGNMENT(.shared_state*))
        shared_state_heap_start = .;
        shared_state_heap_end = ORIGIN(APPL_STATE) + LENGTH(APPL_STATE);
    } >APPL_STATE
}

正确实现(堆在低地址)

通过反向定位的方式,先为全局变量预留高地址空间,再确定堆的范围,无需硬编码变量大小:

方案1:先标记堆起始,再放置全局变量

MEMORY {
    APPL_STATE  (rwx): ORIGIN = 0x002B8000, LENGTH = 0x00030000 /* 192kb */
}

SECTIONS
{
    .shared_state (NOLOAD) : ALIGN(16) {
        // 堆的起始地址 = 段的起始(低地址)
        shared_state_heap_start = .;

        // 跳转到内存段末尾,反向对齐以满足变量的16字节对齐要求
        . = ORIGIN(APPL_STATE) + LENGTH(APPL_STATE);
        . = ALIGN(16, DOWN);

        // 放置全局变量foo所在的段(KEEP避免被链接器优化)
        KEEP(*(SORT_BY_ALIGNMENT(.shared_state*)));

        // 堆的结束地址 = 全局变量的起始地址
        shared_state_heap_end = .;
    } >APPL_STATE
}

方案2:先确定全局变量位置,再计算堆范围

MEMORY {
    APPL_STATE  (rwx): ORIGIN = 0x002B8000, LENGTH = 0x00030000 /* 192kb */
}

SECTIONS
{
    .shared_state (NOLOAD) : ALIGN(16) {
        // 跳转到内存段末尾,反向对齐
        . = ORIGIN(APPL_STATE) + LENGTH(APPL_STATE);
        . = ALIGN(16, DOWN);

        // 记录全局变量的起始地址
        foo_segment_start = .;
        // 放置全局变量段
        KEEP(*(SORT_BY_ALIGNMENT(.shared_state*)));

        // 堆的范围:从段起始到全局变量起始
        shared_state_heap_start = ORIGIN(APPL_STATE);
        shared_state_heap_end = foo_segment_start;
    } >APPL_STATE
}

核心逻辑

  • 利用ALIGN(16, DOWN)从内存段末尾反向对齐,确保全局变量的地址符合对齐要求
  • 依赖链接器自动计算.shared_state*段的大小,无需手动指定foo的长度
  • KEEP关键字确保全局变量段不会被链接器优化丢弃

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 06:37:18