链接脚本的学习
网上有个英文的官方文档:
ftp://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_mono/ld.html#SEC21
1、主要的格式
SECTIONS { ... secname start BLOCK(align) (NOLOAD) : AT ( ldadr ) { contents } >region :phdr =fill ... }
(1)secname:段名
(2)start:起始地址;运行时地址;重定位地址
(3)AT(ldadr) :load addr;加载地址。不写的时候,load addr = runtime addr
2、代码重定位与位置无关码
问:怎么写位置无关的程序呢?
答:使用位置无关码!不使用绝对地址!最根本的方法就是看反汇编。
a. 调用程序时,使用B/BL相对跳转命令
例子:
30 3000005c: eb000106 bl 3000047c <sdram_init>
31 30000060: e3a01000 mov r1, #0 ; 0x0
32 30000064: e59f204c ldr r2, [pc, #76] ; 300000b8 <.text+0xb8>
33 30000068: e59f304c ldr r3, [pc, #76] ; 300000bc <.text+0xbc>
我们看bl 3000047c,这个不是跳到3000047c内存地址的地方,而是跳到0x47c。
b. 重定位之前,不可以使用绝对地址,因为这时候绝对位置的地方还没有内容,比如:
不可以访问全局变量/静态变量
不可以访问数组(rodata, data)
c. 重定位之后,使用绝对跳转命令跳到runtime addr,比如;
ldr pc, =main
这样就可以调到绝对地址为main的地方
3、C函数中怎么使用lds链接脚本中的变量abc呢?
a. 在C函数中声明该变量为extern类型,比如:
extern int abc;
b. 使用时,要取址,比如:
int *p = &abc; //p的值即为lds文件中的abc的值