STM32 GCC下位置无关代码(-fpic)中的函数指针问题
解决STM32 GCC PIC固件中编译期初始化函数指针的硬 fault问题
针对你遇到的编译期初始化全局/静态函数指针在偏移运行时失效的问题,可通过以下几种方式解决:
方法1:运行时通过GOT初始化函数指针
避免编译期直接给函数指针赋值链接地址,改为在启动阶段从已被Bootloader修补的GOT段中获取函数的运行时地址来初始化指针:
#include <stdint.h> void function() { // 业务逻辑 } // 声明未初始化的函数指针,避免编译期写入无效的链接地址 void (*function_ptr)(); static void init_pointers() { // 使用GCC内置函数__builtin_gotptr获取函数在GOT中的条目地址 uintptr_t* got_entry = (uintptr_t*)__builtin_gotptr(function); // 读取GOT条目中已修正的运行时地址,赋值给函数指针 function_ptr = (void(*)())*got_entry; } int main() { init_pointers(); function_ptr(); // 可正常调用,无硬 fault return 0; }
方法2:强制编译器将初始化的函数指针关联到GOT
通过编译器属性将函数指针放入GOT相关段,让Bootloader在修补GOT时一并修正该指针:
void function() { // 业务逻辑 } // 将函数指针放入GOT段,链接器会将其视为GOT条目 void (*function_ptr)() __attribute__((section(".got"))) = &function; int main() { function_ptr(); // Bootloader修补GOT后即可正常调用 return 0; }
注意:此方法需要确保链接器脚本允许将用户变量放入
.got段,部分默认链接器脚本可能需要调整。
方法3:调整编译/链接选项强制GOT寻址
在现有编译选项基础上,添加以下选项,强制GCC对全局函数指针使用GOT寻址:
-fpie -mpic-data-is-text-relative
说明:
-mpic-data-is-text-relative会让数据段中的指针以文本段为基准计算偏移,在固件整体偏移运行时,该偏移量保持有效;配合-fpie进一步强化位置无关代码的生成逻辑。
内容的提问来源于stack exchange,提问作者Matteo Vittorio Ricciutelli
相关产品推荐
相关产品推荐

