ARM v7平台下如何将libc/libgcc共享库符号加入GOT以实现PIC固件?
解决ARM v7 PIC固件中libc非fPIC符号的GOT适配问题
针对你遇到的utoa无法正确引用digits字符串的问题,核心是非fPIC编译的libc库中全局符号未通过GOT寻址,以下是几种可行的解决思路:
1. 替换为fPIC编译的libc/libgcc库
arm-none-eabi工具链在Debian中通常提供支持PIC的嵌入式库变体:
- 安装
libnewlib-arm-none-eabi包(Debian官方仓库),该库默认包含fPIC编译的版本。 - 编译时明确指定PIC相关选项:
链接时添加arm-none-eabi-gcc -mcpu=cortex-a7 -mthumb -fPIC -DPIC -c your_code.c -o your_code.o-Wl,-pie以生成位置无关可执行,同时确保链接到PIC版本的库:
注意路径需根据你的工具链版本调整,可通过arm-none-eabi-ld -pie -L/usr/lib/arm-none-eabi/thumb/v7-m/fpu -lc -lgcc your_code.o -o firmware.elfarm-none-eabi-gcc -print-search-dirs查询库路径。
2. 手动强制全局符号进入GOT
如果无法获取fPIC库,可通过代码和链接器技巧将特定符号(如digits)纳入GOT:
- 在你的代码中添加对目标符号的弱引用并显式使用,强制编译器生成GOT条目:
// 声明digits为弱引用,确保编译器为其生成GOT项 extern const char digits[] __attribute__((weak)); // 显式引用以触发GOT生成(即使代码中实际不用) static const char *dummy = digits; - 链接时使用
-Wl,-y,digits验证符号是否被正确引用,并用readelf -r firmware.elf检查是否生成了R_ARM_GOT_PREL或R_ARM_GOT_BREL类型的重定位。
3. 自定义链接器脚本处理符号
编写链接器脚本,将指定符号标记为需通过GOT寻址:
SECTIONS { /* 保留原有脚本内容 */ .got : { __got_start = .; /* 将digits符号加入GOT */ PROVIDE_HIDDEN (__got_digits = .); LONG(digits - __got_start); __got_end = .; } }
然后在你的GOT初始化代码中,手动修正__got_digits指向的地址,将其加上固件加载基地址,完成digits的GOT寻址适配。
4. 调整链接器重定位行为
使用链接器选项强制将全局符号重定向到GOT:
- 添加
-Wl,-q选项,禁止链接器对全局符号进行绝对地址绑定,强制使用GOT寻址。 - 结合
-Wl,-z,relro启用只读重定位段,提升安全性的同时确保GOT条目被正确初始化。
内容的提问来源于stack exchange,提问作者PTB
相关产品推荐
相关产品推荐

