链接库和地址无关码

【静态连接和动态链接库】

[静态链接]--->静态库:和源程序链接和并装载到虚拟内存
[动态链接]--->共享库:
                    <1>静态共享库:针对每个库,操作系统分配特定虚拟内存地址,模块装载到该特定的虚拟地址,若当前共享库未被装载,那么这个地址空间闲置。即最终装载地址在编译时未确定,在链接时由于知道了库所以确定了;
                    <2>动态共享库:动态共享库装载时,由装载器根据当前虚拟内存中地址空间情况,动态分配虚拟地址,即最终装载地址在链接时依然未确定直到装载。

 [名词分析]
        链接:源文件和库文件建立链接;
        装载:链接后的文件建立和虚拟内存间的映射;
        链接重定位:
            是指在静态链接时,链接之前在源文件中引用的库文件函数名(如add)地址都记作0x0000,链接之后分类合并得到了该函数的相对于链接后文件起始地址0的相对地址(如0x1000),从0x0000-->0x1000地址的转变就是链接重定位;链接后装载时仅需同时偏移相应的量即可。
        装载重定位:
            动态链接由于链接时是动态加载库文件到虚拟内存中的,链接后的文件不是一个整体而且无法计算相对地址,所以只能在装载到虚拟内存时得到该库当前的内存地址。
            
【共享对象结构分析】
    [.data]数据段:自动存入ELF文件数据段
        共享库中的全局变量数据段(.data段)在装载时都并入了可执行文件的数据段(.got段),即在每一个进程的可执行文件中都存在其子共享库全局变量的副本。
        共享库中的局部变量都存放在代码段(.text段)中,当开始执行后加载到内存中的堆栈里
    
    [.interp]动态链接解释段:指定动态链接器路径。
    
    [.dynamic]动态链接段:存放动态链接基本信息
            DT_SYMTAB:[.dynsym]动态链接符号表地址;
            DT_STRTAB:动态连接字符串表地址;
            DT_REL:动态链接重定位表地址,包括代码段重定位表(.rel.text)和数据段重定位(.rel.data)。
            DT_NEED:当前ETF文件所的共享对象文件
                ... ...
    [.symtab]静态链接符号表:存放静态链接符号表    
    --------------------------------------------------------------------------------------------------
    Q:动态链接段中的符号表和静态链接符号表关系?
    A:动态链接表(.dynsym)只存放动态链接符号,而静态链接符号表(.symtab)存放所有符号(包括动态的)。
    --------------------------------------------------------------------------------------------------
    [.text]代码段:需要进行地址无关码转换!
        代码段与绝对地址有关:
            即代码段对应这某个确定的虚拟地址,那么它就不能被多个进程共享,因为它不是被操作系统随机分配的,就是说我们编译之后就已经知道了它的地址,这就是静态共享库了(已淘汰了);
            当其他进程想要使用这个绝对地址,可以!因为这个地址早就知道了。
        代码段与绝对地址无关:
            即代码段的绝对地址当装载时候才能得到绝对地址,装载之前我们只知道相对地址,装载过程中操作系统按照内存空间随机的分配了一个绝对地址(已知了)!
            当其他进程想使用这个绝对地址时,把当前虚拟内存中的代码和数据映射到其他进程的地址空间中。
       

---------------------------------------------------------------------------------------------------------------
        静态链接:链接时重定位;
        静态共享库:不需要重定位;
        动态共享库:装载时重定位;
        动态共享库:在装载时分配虚拟内存,各个动态库首地址一定要进行重定位-shared,但是动态共享库的代码段可能会产生和地址有关的代码:这个时候我们就需要-fPIC来帮助我们把代码段中的地址有关代码转换成地址无关代码,就多个可以很easy的使用共享对象中的代码段(只读)和数据段(读写);如果我们没有做出地址无关码这一步,那么共享库复用的时候从某个进程的虚拟内存映射到另外一个进程中,可以算得共享对象内部的代码,但这样就必须预留出空间,和自动分配空间就违背了。---------------------------------------------------------------------------------------------------------------
            [代码段无关码实现方式]:
            <1>内部:保留偏移量来计算当前地址,即与绝对地址无关。
                模块内部函数调用和跳转;
                模块内部数据访问。
            <2>外部:依靠地址依赖/符号表查找绝对地址,
                模块间数据访问; ---> 存放到本文件的全局变量地址段(.got段),ATT:不是可执行文件
                模块间函数调用/跳转;--->保存到本文件的的函数引用地址段 (.got.plt段),ATT:不是可执行文件
                    Att:.got段中存放本文件全局变量的符号和地址,使用该某个变量只需在段中索引。
                    Att:.got.plt段中存放三项
                        <1>.dynamic段地址,使用某个函数名只需在动态链接符号表中索引即可找到引用的地址;
                        <2>存放本模块链接库的ID,如test.so中存放的就是test。
                        <3>存放_dll_runtime_resolve()函数地址,用来根据地址和符号完成地址绑定工作。
        
        
        [简而言之]
        装载共享对象:保证多个进程所需共享对象的内部代码段与绝对地址无关,把和绝对地址有关的数据/函数在动态链接后存放到各个共享对象的.dynamic段中。
        
        void main(){
            CPU控制权转交动态链接器;
            操作系统告诉了动态链接器有关可执行文件的基本信息(包括入口地址,段的基本信息等);
            动态链接器通过本身的静态链接自举,自举结束后把可执行文件静态链接到内存的某个特定地址;
            然后通过查看可执行文件的.dynamic段中的DT_NEED把当前文件所依赖的共享对象文件找出来,
            
            while(每映射一个依赖的动态对象){
                查看该动态对象的.dynamic段观察该对象是否依赖别的对象,如果依赖,返回上一步循环;
                
                把当前动态对象文件中的符号表合并到虚拟空间中的全局符号表中;
                把当前依赖文件中的全局变量和静态局部变量装载映射到虚拟内存中的静态区;
                把可执行文件和依赖文件的局部变量存放到栈中,栈中作用量会在离开栈时自动销毁;
                把程序代码映射到虚拟内存程序代码区;
                if(所有依赖对象装载完毕)
                    break;
            }    /*ELF和LInux进程虚拟空间映射完毕*/
    
            CPU控制权转交可执行文件入口地址;
            可执行文件开始执行;
            Process Virtual Space --> Physical Space
            /*虚拟空间和物理空间映射完毕*/
        }

时间: 2024-08-10 19:17:50

链接库和地址无关码的相关文章

位置无关码(BL)与绝对位置码(LDR)

BL :带连接分支跳转指令,也是位置无关码(相对位置),一般用于带返回的子程序跳转,B指令是用于无返回的跳转. LDR:通常都是作加载指令的,但是它也可以作伪指令,通常有两种不同的表示:  1)LDR pc, =MyHandleIRQ 表示将MyHandleIRQ地址放入pc寄存器中,相当于PC=MyHandleIRQ . 2)LDR PC,MyHandleIRQ 表示将 MyHandleIRQ地址中的值放入pc寄存器中,类似于C语言中的指针形式,相当于PC=*(MyHandleIRQ ). 实

了解动态链接(二)—— 地址无关代码

把指令中需要修改的部分剥离出来,放到数据区,保持指令部分不变,数据部分可以由每个进程拥有一个副本.这就是——地址无关代码(Position-independent Code, PIC),好处是实现指令部分由多进程共享,节省内存. 要实现PIC,就得解决指令中的地址定位问题.指令中的地址引用可分为: 1.模块内部的函数调用和变量访问: 2.模块外部的函数调用和变量访问. 第1种情况,由于大家都在同一个模块中定义,相互之间有一定的相对位置,所以可以通过相对地址调用解决问题. 第2种情况,也就是对于模

libcurl的源码,编译为静态链接库出现的问题

libcurl的源码,编译为静态链接库出现的问题如下图所示: 解决方案: 具体步骤就是: 1.给工程添加依赖的库:项目->属性->链接器->输入->附加依赖项,把libcurl.lib ws2_32.lib winmm.lib wldap32.lib添加进去 注意,debug配置用libcurld.lib 2.加入预编译选项:项目->属性->c/c++ ->预处理器->预处理器,把  ;BUILDING_LIBCURL;HTTP_ONLY复制进去(注意不要丢

[C] linux静态链接库与动态链接库详解

http://blog.chinaunix.net/u2/76292/showart.php?id=1274181 一顺便说说了哦  通常情况下,对函数库的链接是放在编译时期(compile time)完成的.所有相关的对象文件(object file)与牵涉到的函数库(library)被链接合成一个可执行文件(executable file).程序在运行时,与函数库再无瓜葛,因为所有需要的函数已拷贝到自己门下.所以这些函数库被成为静态库(static libaray),通常文件名为"libxx

C++中的动态链接库和静态链接库

转自 作者:吴秦出处:http://www.cnblogs.com/skynet/ 这次分享的宗旨是--让大家学会创建与使用静态库.动态库,知道静态库与动态库的区别,知道使用的时候如何选择.这里不深入介绍静态库.动态库的底层格式,内存布局等,有兴趣的同学,推荐一本书<程序员的自我修养--链接.装载与库>. 什么是库 库是写好的现有的,成熟的,可以复用的代码.现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常. 本质上来说库是一种可执行代码的二进制形式

linux静态链接库与动态链接库详解

转:http://bbs.chinaunix.net/thread-1281954-1-1.html 二动态链接库的特点与优势  首先让我们来看一下,把库函数推迟到程序运行时期载入的好处:  1.可以实现进程之间的资源共享.   什么概念呢?就是说,某个程序的在运行中要调用某个动态链接库函数的时候,操作系统首先会查看所有正在运行的程序,看在内存里是否已有此库函数的拷贝了.如果有,则让其共享那一个拷贝:只有没有才链接载入.这样的模式虽然会带来一些“动态链接”额外的开销,却大大的节省了系统的内存资源

C++ 动态链接库和静态链接库

概论 先来阐述一下DLL(Dynamic Linkable Library)的概念,你可以简单的把DLL看成一种仓库,它提供给你一些可以直接拿来用的变量.函数或类.在仓库的发展史上经历了"无库-静态链接库-动态链接库"的时代. 静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib中的指令都被直接包含在最终生成的EXE文件中了.但是若使用DLL,该DLL不必被包含在最终EXE文件中,EXE文件执行时可以"动态"地引用和卸载这个与EXE

35.静态链接库和动态链接库

35.1.函数库的前世今生 (1)函数库就是一些事先写好的函数的集合,因为函数是模块化的,因此可以被复用:我们写好了某个函数,可以被反复使用,譬如A写好了某个函数然后共享出来,当B有相同的需求时就不需自己写直接用A写好的这个函数即可. (2)最开始是没有函数库的,每个人写程序都要从零开始自己写,时间长了慢慢的早期的程序员就积累下来了一些有用的函数:早期的程序员经常参加行业聚会,在聚会上大家互相交换各自的函数库:后来程序员中的一些大神就提出把大家各自的函数库收拢在一起,然后经过校准和整理,最后形成

Qt DLL总结【一】-链接库预备知识

1.链接库概念 静态链接库和动态链接库介绍 我们可以创建一种文件里面包含了很多函数和变量的目标代码,链接的时候只要把这个文件指示给链接程序就自动地从文件中查找符合要求的函数和变量进行链接,整个查找过程根本不需要我们操心. 这个文件叫做 "库(Libary)",平时我们把编译好的目标代码存储到"库"里面,要用的时候链接程序帮我们从库里面找出来. 静态链接库: 在早期库的组织形式相对简单,里面的目标代码只能够进行静态链接,所以我们称为"静态库",静态