能否通过GCC或链接器将指定变量置于ELF文件.rodata段首位?
控制.rodata段中常量字符串的存储顺序
问题背景
现有以下三个C文件:
main.c
#include <stdio.h> #include "ext.h" const char greeting[] = "hello world"; const char greeting_two[] = "another hello"; int main() { printf("%s!\n", greeting); printf("%s!\n", greeting_two); printf("%s!\n", mystring_one); printf("%s!\n", mystring_two); return 0; }
ext.h
extern const char mystring_one[]; extern const char mystring_two[];
ext.c
const char mystring_one[] = "my string one"; const char mystring_two[] = "my string two";
使用常规命令编译:
gcc -c -g main.c -o main.o gcc -c -g ext.c -o ext.o gcc -o main.exe main.o ext.o
通过readelf -p .rodata ./main.exe查看.rodata段布局,结果如下:
String dump of section '.rodata': [ 8] hello world [ 18] another hello [ 26] %s!^J [ 30] my string one [ 40] my string two
需求:将mystring_two放到.rodata段的首位,得到如下布局:
String dump of section '.rodata': [ 8] my string two [ ww] hello world [ xx] another hello [ yy] %s!^J [ zz] my string one
实现方案
可以通过GCC属性标记结合自定义链接器脚本实现这个需求,具体步骤如下:
1. 用GCC属性指定符号到自定义子段
修改ext.c,给mystring_two添加section属性,将其放到.rodata.first子段(自定义名称,符合段命名规则即可):
const char mystring_one[] = "my string one"; // 将mystring_two指定到.rodata.first子段 const char mystring_two[] __attribute__((section(".rodata.first"))) = "my string two";
2. 编写自定义链接器脚本
链接器默认按目标文件顺序和默认段规则组织内容,需要自定义脚本让.rodata.first子段排在.rodata的最前面。
首先通过gcc -Wl,--verbose查看当前环境的默认链接器脚本,复制其中的核心段定义,然后调整.rodata的顺序,创建custom.ld脚本:
/* 保留默认链接脚本的其他段定义,这里只展示.rodata的修改部分 */ SECTIONS { .rodata : { *(.rodata.first) /* 优先放置这个子段的内容 */ *(.rodata .rodata.* .gnu.linkonce.r.*) /* 再放置默认的.rodata内容 */ } /* 其他段(如.text、.data等)的定义直接从默认脚本复制即可 */ }
注:如果是Windows下的MinGW环境,链接器脚本的写法可能略有差异,但核心逻辑一致——让自定义子段优先加载。
3. 使用自定义脚本编译
将编译命令修改为使用自定义链接器脚本:
gcc -c -g main.c -o main.o gcc -c -g ext.c -o ext.o gcc -o main.exe -T custom.ld main.o ext.o
验证结果
编译完成后,再次执行readelf -p .rodata ./main.exe,即可看到mystring_two已经排在.rodata段的首位。
内容的提问来源于stack exchange,提问作者sdbbs
相关产品推荐
相关产品推荐

