其他分享
首页 > 其他分享> > 22/8/10 深入理解计算机系统第七章笔记

22/8/10 深入理解计算机系统第七章笔记

作者:互联网

7.7重定位

建立定义和引用对应关系之后,就可以进行重定位了,合并输入模块,并为每个符号分配运行时内存。
重定位包括两步:
重定位节和符号定义:合并所有目标文件的类型相同的节,同时链接器把运行时内存的地址赋给新的节和输入模块定义的每个符号。这一步完成之后程序的每条指令和全局变量都有唯一的运行时内存地址了(虚拟内存)
重定位节中的符号引用:
这一步,链接器修改代码节和数据节中每个符号的引用,使它们指向正确的运行时地址。这一步链接器依赖与可重定位目标模块中的重定位条目的数据结构。

7.7.1 重定位条目

重定位条目:由于汇编器不知道代码和数据最终将放在内存的什么地方,也不清楚模块引用的外部定义的函数和全局变量的位置。所以当汇编器遇到最终位置位置的目标引用时,它会生成一个重定位条目。
重定位条目存放在.rel.xxx中,xxx可以为text或者data。

typedef struct
{
    long offset;
    long type:32,symbol:32;
    long addend;
}Elf64_Rela;

offset是需要被修改的引用的节偏移,symbol标识被修改引用应该指向的符号。

7.7.2重定位符号的引用

x86基本重定位类型

宏定义 重定位修正方法 地址计算方式
R_386_32 1 绝对寻址修正 S+A
R_386_PC32 2 相对寻址修正 S+A-P

A = 保存在被修正位置的值(重定位入口)
P = 被修正的位置(相对于段开始的偏移量或者虚拟地址)
S = 符号的实际地址,即由r_info的高24位指定的符号的实际地址。

R_386_PC32 是一条相对位移调用指令。
R_386_32 是把修正一条传输指令的源,该传输指令的源是立即数(符号的绝对地址)。

相对地址修正的地址为被修正位置的地址差
绝对地址修正的地址为符号的实际地址。

书中refaddr为引用的运行时地址。
refptr为程序的实际地址。

7.8 可执行目标文件

ELF可执行文件的结构:P483
ELF头包含程序的入口点,就是程序运行时要执行的第一条指令。
可执行文件的内容初始化两个内存段:
代码段
数据段

7.9 加载可执行目标文件

每个linux程序都有一个运行时内存映像:
先后为只读代码段,.data .bss数据段,运行时堆,堆后面的区域是为了共享模块保留的。
用户栈总是从最大合法用户地址(2^48 - 1)开始,向较小内存地址增长。
如表所示:

地址 区域 其他
2^48 - 1 内核内存 对用户代码不可见
用户栈(运行时创建) <--%rsp(栈指针)
共享库的内存映射区域
运行时堆(由malloc创建) <--brk
读/写段(.data .bss)
0x400000 只读代码段(.init .text .rodata)

由于.data段有对齐要求,所以代码段和.data段是有间隙的。
在分配栈、共享库和堆段运行时地址的时候,链接器还会使用地址空间布局随机化(3.10.4节)

要求:梳理编译链接到可执行文件初始化运行的过程

标签:10,22,符号,修正,地址,内存,第七章,定位,引用
来源: https://www.cnblogs.com/hy227/p/16574035.html