1.前言
本文主要介绍链接脚本赋值相关的内容
2.通过链接脚本修改目标文件符号地址
在目标文件内定义的符号可以在链接脚本内被赋值. (注意和C语言中赋值的不同!)
此时该符号被定义为全局的. 每个符号都对应了一个地址, 此处的赋值是更改这个符号对应的地址.
/* a.c */
#include
int a = 100;
int main(void)
{
printf( “&a=0x%p “, &a );
return 0;
}
/* a.lds */
a = 3;
输出:
$ gcc -Wall -o a-without-lds a.c
&a = 0×8049598
$ gcc -Wall -o a-with-lds a.c a.lds
&a = 0×3
注意: 对符号的赋值只对全局变量起作用!
3.链接脚本赋值表达式
SYMBOL = EXPRESSION ;
SYMBOL += EXPRESSION ;
SYMBOL -= EXPRESSION ;
SYMBOL *= EXPRESSION ;
SYMBOL /= EXPRESSION ;
SYMBOL >= EXPRESSION ;
SYMBOL &= EXPRESSION ;
SYMBOL |= EXPRESSION ;
- 除了第一类表达式外, 使用其他表达式需要SYMBOL被定义于某目标文件。
注:. 是一个特殊的符号,它是定位器,一个位置指针,指向程序地址空间内的某位置(如果它在SECTIONS命令内的某section描述内则表示某section内的偏移),该符号只能在SECTIONS命令内使用。
-
赋值语句包含4个语法元素:符号名、操作符、表达式、分号;一个也不能少。
-
被赋值后,符号所属的section被设值为表达式EXPRESSION所属的SECTION(参看11. 脚本内的表达式)
-
赋值语句可以出现在连接脚本的三处地方
- SECTIONS命令内
- SECTIONS命令内的section描述内
- 全局位置
举例:
floating_point = 0; /* 全局位置 */
SECTIONS
{
.text :
{
*(.text)
_etext = .; /* section描述内 */
}
_bdata = (. + 3) & ~ 4; /* SECTIONS命令内 */
.data : { *(.data) }
}
4. PROVIDE关键字
该关键字用于定义这类符号:在目标文件内被引用,但没有在任何目标文件内被定义的符号。
例子:
SECTIONS
{
.text :
{
*(.text)
_etext = .;
PROVIDE(etext = .);
}
}
当目标文件内引用了etext符号,确没有定义它时,etext符号对应的地址被定义为.text section之后的第一个字节的地址。
参考文档
The GNU linker