Atmel Studio生成PIC时冗余代码致ApplicationFooter内存溢出
首先,你遇到的冗余代码问题本质是启用-fpic编译选项后,GCC会生成位置无关代码所需的辅助结构,这些结构默认被链接到ROM区域的末尾,挤占了你预留的ApplicationFooter空间。
具体原因
当使用-fpic(Position Independent Code)时,GCC需要生成支持动态重定位的代码结构,主要包括:
- 全局偏移表(GOT):存储全局变量的地址,用于在运行时动态计算位置
- 过程链接表(PLT):处理函数的动态调用
- 相关的重定位段(如
.rel.plt、.got.plt)
这些段默认会被链接器放置在.text段之后,也就是你定义的rom区域(0x004000000x00407E00)的后半部分。当这些额外结构的大小超过`rom`区域剩余空间时,就会溢出到相邻的`ApplicationFooter`区域(0x00407E000x00408000),导致你看到的712字节溢出问题。而关闭-fpic时,这些结构不会生成,所以不会占用额外空间。
你可能遗漏的配置
你没有在链接脚本中明确指定-fpic相关段的存放位置,导致链接器按照默认规则分配段地址,最终和预留的ApplicationFooter区域冲突。
解决方案
针对这个问题,你可以尝试以下几种方法:
1. 在链接脚本中明确指定GOT/PLT等段的位置
修改你的链接脚本,将-fpic相关的段强制放在rom区域内,且在ApplicationFooter之前结束。示例如下:
SECTIONS { /* 先放置.text、.rodata等常规段 */ .text : { /* 你的原有.text段内容 */ } > rom /* 专门放置fpic相关的段 */ .got : { *(.got .got.plt) } > rom .rel.plt : { *(.rel.plt) } > rom /* 最后放置ApplicationFooter,确保它在ROM的最末尾 */ .ApplicationFooter : { KEEP(*(.ApplicationFooterData .ApplicationFooterData.*)) } > ApplicationFooter /* 其他段定义... */ }
这样能保证-fpic生成的辅助结构不会挤占ApplicationFooter的空间。
2. 使用-fpie替代-fpic(更适合嵌入式可执行文件)
如果你的程序是独立的可执行文件而非共享库,推荐使用-fpie(Position Independent Executable)代替-fpic。-fpie生成的是针对可执行文件的位置无关代码,产生的辅助结构更小,且更适合嵌入式系统的场景,可能不会触发空间溢出问题。
3. 检查段大小变化,定位具体溢出的段
使用Atmel Studio自带的工具(或GCC的size、objdump命令)对比开启和关闭-fpic时各段的大小,找到具体是哪个段占用了额外的712字节。比如执行:
size your_program.elf
或者查看objdump -h your_program.elf的输出,找到新增的大段,再针对性调整链接脚本的段布局。
4. 调整ROM区域的划分(临时方案)
如果上述方法暂时无法生效,你可以临时调整Memory Spaces Definitions中的区域大小,比如缩小rom区域的长度,给-fpic的辅助结构预留足够空间,同时保证ApplicationFooter的0x200字节不受影响:
MEMORY { rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x00007C00 /* 减少0x200字节,给fpic结构预留空间 */ ApplicationFooter(rx) : ORIGIN = 0x00407C00, LENGTH = 0x00000200 /* 同步调整起始地址 */ ram (rwx) : ORIGIN = 0x20400020, LENGTH = 0x00060000 }
不过这只是临时方案,更推荐通过链接脚本的段布局来根本解决问题。
内容的提问来源于stack exchange,提问作者Antoine Boré

