位置无关代码

首先是书:

《深入理解计算机系统》《程序员的自我休养》这两本书中都有详细地讲到位置无关代码。


位置无关代码(PIC)


==============================================


什么是位置无关代码(Position Independent Code —— PIC)?


理解这个,首先需要理解代码加载域和运行域的概念。


加载域是代码存放的地址,运行域是代码运行时的地址。


在一些场合,一些代码并不在存放这部分代码的地址上执行地址。比如说,放在 NorFlash 中的代码可能最终是放在 RAM 中运行,那么 NorFlash 中的地址就是加载域,而在 RAM 中的地址就是运行域。


在汇编代码中我们常常会看到一些跳转指令,比如说 b、bl 等,这些指令后面是一个相对地址而不是绝对地址,比如说b main,这个指令应该怎么理解呢?main这里究竟是一个什么东西呢?


这时候就需要涉及到链接地址的概念了。链接地址实际上就是链接器对代码中的变量名、函数名等东西进行一个地址的编排,赋予这些抽象的东西一个地址,然后在程序中访问这些变量名、函数名就是在访问一些地址。


一般所说的链接地址都是指链接这些代码的起始地址,代码必须放在这个地址开始的地方才可以正常运行,否则的话当代码去访问、执行某个变量名、函数名对应地址上的代码时就会找不到,接着程序无疑就是跑飞。


但是上面说的那个b main的情形有点特殊,b、bl等跳转指令并不是一个绝对跳转指令,而是一个相对跳转指令,什么意思呢?


就是说,这个main标签最后得到的地址并不是main被链接器编排后的绝对地址,而是main的绝对地址减去当前的这个指令的绝对地址所得到的值。也就是说b、bl访问到的是一个相对地址,不是绝对地址。


因此,包括这个语句和main在内的代码段无论是否放在它的运行域,这段代码都能正常运行。这就是所谓的位置无关代码。


由上面的论述可以得知,如果你的这段代码需要实现位置无关,那么你就不能使用绝对寻址指令,否则的话就是位置有关了。


==============================================


(1) 可重定位代码(Relocatable code):所谓代码的重定位,就是把可执行代码移动到内存中的另外一个地址去。OS一般会把内核从硬盘COPY到内存中去执行,就是用到了重定位这个技术。


生成动态库时假定它被加载在地址 0 处。加载时它会被加载到一个地址(base),这时要进行一次重定位(Relocation),把代码、数据段中所有的地址加上这个 base 的值。这样代码运行时就能使用正确的地址了。


(2) 位置无关代码(Position Independent Code):使用 -fPIC 的 Linux SO。


这样的代码本身就能被放到线性地址空间的任意位置,无需修改就能正确执行。通常的方法是获取指令指针(如 IA32 的 EIP 寄存器)的值,加上一个偏移得到全局变量/函数的地址。




==============================================


PIC vs. Relocatable:


(1) PIC 的缺点主要就是代码有可能长一些。例如 IA32,由于不能直接使用 [EIP+constant] 这样的寻址方式,甚至不能直接将 EIP 的值交给其他寄存器,要用到 GOT(Global Offset Table)来定位全局变量和函数。这样导致代码的效率略低。


(2) PIC 的加载速度稍快,因为不需要做重定位。


(3) 多个进程引用同一个 PIC 动态库时,可以共用内存。这一个库在不同进程中的虚拟地址不同,但操作系统显然会把它们映射到同一块物理内存上。对于可重定位代码,则必须为每个库都在物理内存中复制一份副本,因为需要修改其中的地址。当然,主流现代操作系统都启用了分页内存机制,这使得重定位时可以使用 COW(Copy On Write)来节省内存(32 位 Windows 就是这样做的);然而,页面的粒度还是比较大的(例如 IA32 上是 4KiB),至少对于代码段来说能节省的相当有限。




==============================================

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值