gcc与obj文件,动态链接文件和ELF文件
来源:互联网 发布:廖雪峰2.7 python pdf 编辑:程序博客网 时间:2024/06/15 23:15
1、obj文件
程序员编写程序,其实就是编写出一个2进制(binary)文件。假如我们声明一个变量char c,也就是声明需要一个8bit的空间,那么就需要向系统声明豫留8bit的空间,怎么做到这一点呢?就是编译一个特殊的2进制文件--obj文件,用gcc编译的C语言得到的执行文件,里面不仅包含CPU指令,还有很多别的信息在里面,它有很多格式COFF、ELF……等等,在最后一道编译过程中,链接器(linker)ld会加载一堆信息进入可执行文件。例如,当有多个编译后等待链接的.o这种可重定位(relocatable)文件,既然这些文件里面参数或者函数名的相对位置只是本身所在.o文件的相对位置,就有一些信息要告诉链接编辑器(link editor)怎么修改section的内容,来做relocate,也就是做地址的重新参照以便合成一个新的可执行文件。
一个obj文件有两个重要时期,一个是正在链接(link)的时候,也就是处在
硬盘(disk)里的时候;一个是正在执行的时候,当然这时它位于内存里。我们平时说的ldlinker其实叫link editor,最后编译的步骤ld把该有的信息写进可执行文件。如果是static link就会去找libxxx.a的函数库文件,把想要的程序代码片段拷贝一份进可执行文件,并且做成relocation后,把跳来跳去的参照写进可执行文件,这个文件就可以执行。
2、动态链接文件
相对于静态链接(static link)拷贝原有的程序代码进可执行文件,动态链接不那样做,link editor把一些信息写进可执行文件而已。例如,需要的程序库名、函数名等,最后执行的时候,必须呼叫dynamic linker來做program
intepreter,dynamiclinker会根据需要的函数库名称,把想要的函数名字创造一个可执行的image放到内存,所以执行有动态链接的执行文件,最后通常都是由OS的exec系列的system call与dynamic linker如ld.so联合完成。
dynamiclinker通常会做如下工作:
(1)把可执行文件的内容加载到processimage
(2)把sharedobj需要的东西加载到process image
(3)完成relocation
本来这些obj文件里面的虚拟地址应该和文件的地址有相对应的偏移(offset),而文件首地址通常是0x08040800,这是绝对虚拟地址,但它只适合可执行文件,例如Linux extuable file通常是:
file offset virtual address
----------- ----------------
0x0 0x08048000
0x100 0x08048100
shared obj函数库里的程序代码必须为位置无关代码Position
IndependentCode (PIC),也就是说它的地址可能会随不同process而有不同,例如,一个程序只用了libc.so、ld-linux.so,通常这时候lib.so是从0x40017000开始的,但如果另一个程序多用一个libm.so,那么libc.so从0x40034000开始两个的printf参照(reference),就会有不同的地址,所以这种动态函数库的内部资料就要说明这些code是PIC。
3、ELF文件
(1)简介
现在最常用的是一种叫ELF格式(executable and linkable format)的执行文件,ELF定义了一些变量与信息使得动态链接更有弹性,一个ELF的2进制文件按照spec 1.1版的说法有6种,下列是较常见的:
relocatable:它就是编译时产生的.o文件,包含了代码和数据(这些数据是和其他 重定位文件和共享的object文件一起连接时使用的)
executable:它就是最后的可执行文件,包含了代码和数据sharedobj:它就是在/lib /usr/lib下那些可动态链接的函数库文件,包含了代码和数据(这些数据是在连接时候被连接器ld和运行时动态连接器使用的)
core:CoreDump时产生的文件,包含了一堆garbage数据
注意:这些ELF文件已经是广义的2进制文件,不单指可执行文件。
(2)ELF组成
一个ELF obj文件随它存在的时期有不一样的需求和组成名字,在要链接linking时期位于硬盘,包含了:
ELFheader
programheader table (可以不要)
section0
section1
section2
section3
section...
sectionn
sectionheader table
ELF header放了ELF定义的一些ELF格式识别字串(俗称magic number),还有obj文件(shared obj,relocatable或者executable)这些一般(general)的信息;program header table是描述了段(segment)信息的结构数组和一些为程序运行准备的信息。segement和section不大一样,是属于程序执行时期的元素,所以在程序执行时期是必要的,在链接时期是不必要的,所以如果程序不做链接动作,只要有program header table就可以;section header table就是一个索引表,来记录各个section的索引,sections就是把需要的资料根据属性用途分门别类后的小集合,有.bss .data .init .debug .dynamic .fini .text………,其中比较重要的有:
.text
里面保存真的CPU指令
.bss
保存没有initialize的data
主要是声明的global与static变量
.data
保存initialize的data
写程序用到的函数名,变量名分布在多个source code目录里时,需要一个
参照(reference)的信息做连接这些名字,symbol是着被给linker来做连接用的,因为obj文件分散存在,要把这些obj文件的代码集合起来,就要靠symbol
来辨别,stringtable存有很多行字串,每行字串用NULL来分开,每行字串就是symbol和section的名字。symbol table是一张表,存有将来要定址或重新定址所要的symbol定义和参照信息。shared lib的obj文件还有.dynsym这个section,里面存有dynamic symbol table,动态链接的时候使用。另外,如果将来的程序要用debug工具调试,编译时要加-g这个选项,它会根据sumbol
和stringtable放进debug多需要的信息给obj文件,这样的信息现在大都用一种叫stab的格式存放,这同时也会让执行文件大小增加到将近3倍。
硬盘(disk)里的时候;一个是正在执行的时候,当然这时它位于内存里。我们平时说的ld
2、动态链接文件
intepreter,dynamic
dynamic
(1)把可执行文件的内容加载到process
(2)把shared
(3)完成relocation
Independent
3、ELF文件
(1)简介
relocatable:它就是编译时产生的.o文件,包含了代码和数据(这些数据是和其
executable:它就是最后的可执行文件,包含了代码和数据shared
core:Core
(2)ELF组成
ELF
program
section
section
section
section
section
section
section
.text
.bss
.data
参照(reference)的信息做连接这些名字,symbol是着被给linker来做连接用的,因为obj文件分散存在,要把这些obj文件的代码集合起来,就要靠symbol
来辨别,string
和string