能否从链接器脚本访问C变量及自定义链接脚本ld报错如何解决
问题解答
1、是否可以从链接器脚本中访问C语言定义的变量?
是可以的。
- C语言中定义的带外部链接的全局变量会作为全局符号暴露给链接器,链接器脚本可以直接读取或修改该符号的取值。
- 注意避坑:你当前代码里C定义的变量名为
prog_sz,但你计划在链接器脚本里写的是proc_sz,拼写不一致会导致赋值失效。 - 补充使用提示:如果是直接在链接器脚本中定义符号(而非修改C中预先定义的变量),C代码引用时需要声明为
extern 类型 符号名[];,通过取地址&符号名的方式获取链接器赋的数值,因为链接器脚本中定义的符号本质是地址标记,没有实际的存储空间。
2、上述链接报错如何解决?
你遇到的报错是因为自定义的极简链接脚本完全替换了ld的默认链接脚本,缺失了glibc和ELF格式要求的必要段、符号、程序头定义:ld默认链接脚本内置了__init_array_start/__init_array_end这类隐式符号、PHDR程序头配置、.init_array/.fini_array等运行时必需的段定义,你编写的脚本没有包含这些内容就会触发报错。
解决方法按易用性排序推荐如下:
方案1:基于默认链接脚本修改(首选)
不要从零开始编写链接脚本,先导出系统默认的链接脚本,再按需添加你的赋值逻辑:
- 执行命令导出默认链接脚本:
ld --verbose > my_linker.ld - 打开
my_linker.ld,删除开头和结尾的冗余输出内容,只保留中间正式的链接脚本代码 - 在你想要获取进程大小的位置(通常是所有可加载段的末尾,比如.bss段定义的末尾)添加语句:
prog_sz = .; - 编译时指定该脚本即可:
gcc your_code.c -T my_linker.ld
方案2:补全极简脚本的必要内容
如果一定要使用精简的链接脚本,需要补充缺失的必要定义:
- 新增
PHDRS块定义ELF程序头,确保PHDR段包含在LOAD段中 - 新增
.init_array/.fini_array等段的定义,同时显式声明__init_array_start/__init_array_end等依赖符号 - 补充.note、.eh_frame等glibc依赖的段定义
内容的提问来源于stack exchange,提问作者user13585978
相关产品推荐
相关产品推荐

