链接地址和运行地址
链接地址:给链接器指定将来程序希望被运行的内存地址
运行地址:程序实际运行时的内存地址,由程序实际被加载到的实际内存地址决定
PS:程序的链接地址和运行地址是不一定相同的
位置无关代码
位置无关代码(Position-independent Code,PIC):代码的链接地址和运行地址无关。
位置有关代码:代码的链接地址和运行地址必须一致,否则无法运行。
什么是代码重定位
很多时候程序的链接地址和运行地址无法一致,导致程序无法正常运行。这个时候可以通过执行一段位置无关码,将原来的那份代码全部复制到链接地址那里去,然后自己再跳转到新的那份代码刚刚的那个位置继续执行。
为什么需要代码重定位
代码的链接地址和运行地址不一致时,且程序中存在位置有关代码时,这时候就需要通过代码重定位来解决问题。
程序段
程序存在各种不同的段,链接器可以通过段进行查找和链接。程序段分为固定段和自定义段。
固定段包括:
- 文本段(.text):又叫代码段,是函数编译后生成的段
- 数据段(.data): 存放程序中已初始化的全局变量
- 只读数据段(.rodata): 存放字符串和 #define 定义的常量
- 零初始化段(.bss):存放程序中未初始化的全局变量
自定义由用户自定义。
链接脚本
链接地址是在链接脚本中指定的。链接脚本用于指导链接器如何链接。我之前提供的代码中都有这样一个链接脚本 link.lds。之前的程序都没由真正使用这个链接脚本,后面的代码实战中就会使用这个链接脚本
SECTIONS
{
/* 指定链接地址为 0x02023400, 需保证位置有关代码需运行在相应的内存地址上 */
. = 0x02023400;
/* 代码段(文本段),存储代码编译后的二进制文本 */
.text : {
start.o
* (.text)
}
/* 只读数据段(read only data) */
.rodata ALIGN(4) : {
*(.rodata*)
}
/* 数据段 */
.data ALIGN(4) : {
*(.data)
}
/* bss段(Block Started by Symbol)未初始化的或者初始化为 0 的全局变量和静态变量,又叫 ZI 段(Zero Inital) */
bss_start = .;
.bss ALIGN(4): {
* (.bss)
* (COMMON)
}
bss_end = .;
}
2021年9月5日
Kilento