Chapter 07
第七章讲的就是动态链接了,这里比较复杂,但是书上讲的特别好。
1. 首先是一个问题:为什么要使用动态链接?两点:节省空间、便于链接库的更新 (P180)
2. 然后就是 P191 开始讲的例子,将地址无关代码分为四种类型进行说明。
1. 前两种比较简单,看书上例子。
2. 第三种主要是一个关键问题:GOT 表中存储的是物理地址还是虚拟地址?
??? question "GOT 表中存储的是物理地址还是虚拟地址"
GOT 表中存储的还是虚拟地址。现在有两个程序 a.out 和 b.out,假设都需要动态加载 test.so,其装载后的物理地址是 0xDEAD0000,我们访问的数据在 test.so 偏移位置是0x100。
现在首先是 a.out 要使用 test.so,test.so 加载到内存 0xDEAD0000 中。但同时对于 a.out 来说,它会认为 test.so 加载到了它的虚拟地址中,如下面所示。
```
0x08048000 0x08049000 0x00000000 r-x a.out
0x08049000 0x0804a000 0x00000000 r-- a.out
0x0804a000 0x0804b000 0x00001000 rw- a.out
0xf7d5a000 0xf7d77000 0x00000000 r-- test.so
0xf7d77000 0xf7ed4000 0x0001d000 r-x test.so
0xffeb6000 0xffed7000 0x00000000 rw- [stack]
```
但是对于 A 的 MMU 来说,它会存储(0xf7d5a000, 0xDEAD0000) 这一对。
同样的,当 b.out 需要使用 test.so 时,它的虚拟地址假设如下。
```
0x08048000 0x08049000 0x00000000 r-x b.out
0x08049000 0x0804a000 0x00000000 r-- b.out
0x0804a000 0x0804b000 0x00001000 rw- b.out
0xf7d95000 0xf7db2000 0x00000000 r-- test.so
0xf7db2000 0xf7f0f000 0x0001d000 r-x test.so
0xffd84000 0xffda5000 0x00000000 rw- [stack]
```
对于 B 的 MMU 来说,他会存储(0xf7d95000, 0xDEAD0000) 这一对。
3. PLT 那里讲的很好,P200-202,直接看就行,很容易理解。
4. 几个比较容易混淆的 Section:
- `.got` && `.got.plt` && `.plt`
- `.rel.text` && `.rel.data` && `.rel.dyn` && `.rel.plt`
5. 一个问题:为什么使用 fPIC 还需要动态重定向??
6. 一个很重要的问题:如果 A 和 B 同时使用 test.so 的某个全局变量,会相互影响吗?
??? question "如果 A 和 B 同时使用 test.so 的某个全局变量,会相互影响吗?"
P198,不会!!!对于数据而言,每个进程都会创立副本,所以对于刚才所说的 2.2,如果 A 和 B 访问函数,那么 MMU 都是映射到 0xDEAD0000,如果访问数据,那么 MMU 映射到各自创立的副本。