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

Cortex-M7平台GCC编译位置无关代码(PIC)的全局指针偏移问题

问题背景与现象

现有一批需在Cortex-M7嵌入式系统中编译为位置无关代码(PIC)的C代码,原使用ARMCC编译器并添加--ropi --rwpi选项可正常运行。现需切换至GCC 12.2版本编译,加载代码的ThreadX Modules系统约定使用r9作为全局偏移表(GOT)的偏移寄存器,参考编译选项为:-fpie -fno-plt -mno-pic-data-is-text-relative -msingle-pic-base,无特殊链接选项。

当前核心问题:GCC编译后,全局变量地址获取逻辑失效,ARMCC下无此问题。示例代码及输出如下:

示例代码

char buffer[100];
char* pBuffer = buffer;

int appModMain()
{
    printf("buffer address: %p, buffer address via pBuffer: %p\n", buffer, pBuffer);
}

输出结果

buffer address:  60C8C25C, buffer address via pBuffer: 1000025C

可见直接取buffer地址能得到正确的偏移后地址,但通过全局指针pBuffer获取的地址未应用偏移。反汇编证实:加载pBuffer到寄存器传递给printf时,未使用r9寄存器进行必要的偏移调整;且pBuffer被初始化为buffer的未偏移地址,编译器虽识别pBuffer指向GOT内容,但生成代码时未添加偏移处理。

已尝试-mpic-data-is-text-relative/-mno-pic-data-is-text-relative、-msingle-pic-base/-mnosingle-pic-base等选项的多种组合,均无效果。因代码量庞大且包含非自研模块,无法修改源码,需寻求GCC适配的解决方案。

解决方案

以下为针对该问题的可行调整方案:

  1. 指定PIC基址寄存器为r9
    GCC默认使用r10作为ARM架构下的PIC基址寄存器,而ThreadX Modules系统约定使用r9。需添加编译选项-mpic-register=r9,强制GCC使用r9作为全局偏移表的基址寄存器,与系统约定对齐。

  2. 完善编译与链接选项
    将编译链接选项调整为:

    -fpie -pie -fno-plt -mno-pic-data-is-text-relative -msingle-pic-base -mpic-register=r9
    

    其中-pie用于链接阶段生成位置无关可执行文件,确保重定位逻辑正确生效;-mpic-register=r9确保GCC生成的代码使用r9进行偏移计算。

  3. 强制全局变量进入非common段
    添加-fno-common编译选项,强制全局变量(包括初始化的指针变量pBuffer)进入非common存储段,让编译器生成正确的重定位条目,确保加载时通过r9完成地址偏移。

  4. 检查链接脚本的重定位配置
    若上述选项仍无效,需确认链接脚本中是否正确处理RWPI数据的重定位:

    • 确保.data、.bss等可重定位段使用REL类型的重定位条目;
    • 确认GOT表的生成逻辑符合ThreadX Modules的要求;
    • 可添加链接选项-Wl,--verbose查看链接过程,排查GOT相关重定位是否正确生成。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 01:13:27