zoukankan      html  css  js  c++  java
  • 动态链接PIC的疑问

    动态共享对象的装载时重定位

    最近读程序员的自我修养--链接 装载与库,其中有句话:动态链接模块被装载映射到虚拟空间后,指令部分是在多个进程之间共享的,由于装载时重定位的方法需要修改指令,所以没有办法做到同一份指令被多个进程共享,因为指令被重定位后对于每个进程来讲是不同的。一直没搞懂,花了不少时间查阅资料,了解原理。觉得自己一直理解的东西都太浅了。 以下是对这块内容的总结,作为记录。
    其中的关键点在于掌握内存映射,重定位的实现以及共享对象的装载。搞清楚虚拟内存空间和物理内存空间。
    共享对象在被装载时,是如何确定它在进程虚拟地址空间中的位置?
    一种方法是固定装载,这种方法弊端明显:地址冲突;共享库升级困难;空间受限等等。(基本不用)
    那么只能采用另一种思路,即共享对象能在任意地址装载。这种情况叫做装载时重定位。当程序被装载时,系统的动态链接器会将程序所需的所有动态链接库(例如最基本的libc.so)装载到进程的地址空间,且将程序中所有未决议的符号绑定到相应的动态链接库中,并进行重定位工作(术语叫装载时重定位-load time relocation,在windows中,又叫基址重置-rebasing,区别于静态链接的链接时重定位-link time relocation)。也即,动态链接是把可执行elf的形成过程从本来的程序链接前推迟到装载时。共享对象的最终装载地址在编译时是不确定的,而是在装载时,装载器根据当前地址空间的空闲情况,动态分配一块足够大小的虚拟地址空间给相应的共享对象。
    装载时重定位的原理来自链接时重定位,但是对于共享对象,单纯的装载时重定位显然会引发问题,也就是文章开头说到的那句话。动态链接模块被装载映射到虚拟空间后,指令部分是在多个进程之间共享的,由于装载时重定位的方法需要修改指令,所以没有办法做到同一份指令被多个进程共享,因为指令被重定位后对于每个进程来讲是不同的。
    在网上看到有不少人问了这个问题,答案看得我也是迷迷糊糊。折腾了一下午,发现其实是自己对基本的原理都没搞清楚才会看不懂这句话。关键在于共享对象也就是动态链接库在被装载到物理内存后,始终是只有一份的,不管有多少个进程使用它。但是对于每一个进程,共享对象会映射一次到虚拟地址空间,也就是每个进程空间都有一份共享对象的映射,此时,对于不同的进程,映射的地址(基址)是不一样的(大部分情况下)。紧接着,进行装载时重定位。装载时重定位由动态链接器完成,动态链接器会被一起映射到进程空间中。它根据共享对象在虚拟内存空间中的地址修改在物理内存中的共享对象中的指令,为什么会修改指令,原因在于绝对地址访问(如模块内的变量访问)是直接用mov指令完成的,也就是直接将地址打入寄存器,所以,此时的重定位会直接修改指令。进一步,共享对象中修改的指令是根据共享对象被映射到虚拟空间中的地址(基址)决定的,而每个进程对共享对象的映射不可能都是在相同地址。所以也就无法完成这一部分代码的共享。
    批注:{
假设,可执行文件为X1和X2,他们同时需要共享库LIB,且LIB中有全局变量A,且A相对于LIB的符号位置偏移为PA;
    已知,全局变量A的调用方式是直接寻址,如move A 0x01,向A地址写入0x01数据;
    假设,LIB映射到X1进程的虚拟地址是P1,LIB映射到X2进程的虚拟地址是P2,且X1和X2将要调用LIB内的指令CODE为向A中写数据:move A的虚拟内存地址 0x01 ;
    那么,当X1调用CODE时,move P1+PA 0x01;当X2调用CODE时,move P2+PA 0x01;此时意味着两个进程调用的指令不一样,因为不能共享此条指令!
    为什么不直接用A的物理地址进行move呢?这样不是指令就都一样了?
    因为有虚拟内存的存在,所有操作都是在虚拟内存中完成的,再由MMU映射到物理内存,所以不能直接move 物理内存地址。
    又因为LIB在内存中只有一份,所以当X1调用A时,程序将指令修改为move P1+PA 0x01;当X2调用A时,程序将指令修改为move P2+PA 0x01;
    }
    那么如何解决这个问题,就要用到位置无关代码(PIC),也有叫地址无关代码的。基本思路是把指令中那些需要被修改的部分分离出来,跟数据部分放到一起,这样,剩下的指令就可以保持不变,而数据部分在每个进程中拥有一个副本。ELF针对各种可能的访问类型(模块内部指令调用、模块内部数据访问、模块间指令调用、模块间数据访问),实现了对应地址引用方式,从而实现了PIC。具体的细节不在这里赘述。
     
    参考资料:
    https://blog.csdn.net/parallelyk/article/details/42747239?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-3.not_use_machine_learn_pai&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-3.not_use_machine_learn_pai
    http://www.360doc.com/content/14/0902/09/19184777_406438267.shtml
    http://blog.chinaunix.net/uid-26983585-id-3364514.html
    http://blog.163.com/shi_shun/blog/static/2370784920122875910467/

  • 相关阅读:
    Qtranslate是Win10系统的一款非常小众的翻译神器,真的是办公人员利器
    大文件查找软件(WizTree) v3.37 ---非常快
    DirPrintOK --- 将文件以树的形式列出、可导出到excel、html文件,用于整理电脑的文件,非常好用
    Linux五大类常用命令
    Android pm list 命令查看手机安装的apk信息
    Android adb命令列出当前设备所有apk安装的路径和包名
    Win10 Python2.7.6 如何使用pip命令?如何离线安装第三方模块?PyCharm设置Python2.7.6,、wxPython安装
    证件照在线免费移除背景或更换背景
    Ubuntu wps办公软件快捷键
    根据书籍的ISBN号查询书籍信息
  • 原文地址:https://www.cnblogs.com/chendeqiang/p/14312122.html
Copyright © 2011-2022 走看看