准备:可重定位文件(Relocatable file),可执行文件(Executable file),共享文件(Shared object file)。
Relocatable file: an object file that holds code and data
suitable for linking with other object files to create an executable or a
shared object file. In other word, you can say that relocatable file is
a foundation for creating executables and libraries.
This is kind of file you get if you compile a source code like this:
$ gcc -c test.c That will produce test.o, which is a relocatable file.
Kernel module (either suffixed with .o or .ko) is also a form of relocatable file.
Executable file: object file that holds a program suitable for
execution. Yes, that means, your XMMS mp3 player, your vcd software
player, even your text editor are all ELF executable files.
This is also a familiar file if you compile a program:
$ gcc -o test test.c After you make sure the executable bit of "test" is enabled, you can execute it. The question is, what about ? Shell script is NOT ELF executable, but the interpreter IS.
Shared object file: This file holds code and data suitable for linking in two contexts:
- The link editor may process it with other relocatable and shared shared object file to create another object file.
- The combines it with an executable file and other shared objects to create a process image.
In
simple words, these are the files that you usually see with suffix .so
(normally located inside /usr/lib on most Linux installation).
重定位:就是把符号的value进行重新定位,value可是地址也可是其他类型值.要重点理解
编译器、连接器和装载器各个职能,熟悉编译、连接和加载过程、符号(symbol)、段(section)等概念
符号:高级语言经编译处理后,在binary层面上,统一以符号表示各个变量、函数实体。是连接和重定位桥
梁。不同编译器有不同的地符号影射,比如c语言中,以前有的编译器固定变量前加下划线 int a ==>_a
段:binary层面对指令和数据的组织,方便管理、理解。深入参考汇编中有关段概念。
符号和段都是属于ELF表示范畴,是对binary层面的描述。深入可参考ELF或者coff相关文档
重定位分为两大类:普通和动态。普通就是连接时候重定位,动态是指加载、运行时
重定位,一般有程序启动时动态加载
符号来重定位,和
函数符号被调用时候动态加载。
重定位过程要用到一些表,来辅助定位,有.rel.text、 .rel.dyn和.rel.plt、.plt.下面根据他们来展开说明。
.rel.text
重定位的地方在.text段内,以offset指定具体要定位位置。在连接时候由连接器完成。注意比较.text段前后变化。指的是比较.o文件和最终的执行文件(或者动态库文件)。就是重定位前后比较,以上是说明了具体比较对象而已。
.rel.dyn
重定位的地方在.got段内。主要是针对外部数据变量符号。例如全局数据。重定位在程序运行时定位,一般是在.init段内。定位过程:获得符号对应value后,根据rel.dyn表中对应的offset,修改.got表对应位置的value。另外,.rel.dyn 含义是指和dyn有关,一般是指在程序运行时候,动态加载。区别于rel.plt,rel.plt是指和plt相关,具体是指在某个函数被调用时候加载。
.rel.plt
重定位的地方在.got.plt段内(注意也是.got内,具体区分而已)。 主要是针对外部函数符号。一般是函数首次被调用时候重定位。可看汇编,理解其首次访问是如何重定位的,实际很简单,就是初次重定位函数地址,然后把最终函数地址放到.got.plt内,以后读取该.got.plt就直接得到最终函数地址(参考过程说明)。 所有外部函数调用都是经过一个对应桩函数,这些桩函数都在.plt段内。
过程说明:调用对应桩函数--->桩函数取出.got表(具体是.got.plt)表内地址--->然后跳转到这个地址.如果是第一次,这个跳转地址默认是桩函数本身跳转处地址的下一个指令地址(目的是通过桩函数统一集中取地址和加载地址),后续接着把对应函数的真实地址加载进来放到.got.plt表对应处,同时跳转执行该地址指令.以后桩函数从.got.plt取得地址都是真实函数地址了。
.plt段,存放重定位桩函数的。
重要区别
.rel.text属于普通重定位辅助段 ,他
由编译器编译产生,
存在于obj文件内。连接器连接时,他 用于最终可执行文件或者动态库的重定位。通过它修改原obj文件的.text段后,和并 到 最终可执行文件或者动态文件的.text段。
注:readelf -r a.o 查看 .rel.text。其类型一般为R_386_32和R_386_PC32
.rel.dyn和.rel.plt是动态定位辅助段。
由连接器产生,
存在于可执行文件或者动态库文件内。借助这两个辅助段可以动态修改对应.got和.got.plt段,从而实现运行时重定位。
.rel.dyn 对应地点在.got表内;.rel.plt 在.got.plt,注意不是在.text,这点和普通不同,也是重要点。
.rel.text由编译器产生,然后在连接时候,由链接器负责根据.rel.text对.text段进行修改,从而达到重定位目的;
.rel.dyn和.rel.plt由连接器产生,然后在运行时候,动态加载符号地址。
对于数据,根据.rel.dyn找到.got中的offset位置;
对于函数则通过.plt桩函数和.rel.plt段来获取函数真实地址,然后存在于.got.plt。
要理解动态连接中访问外部符号是通过.got和.got.plt
注1:规律:.rel.plt和.got.plt偏移 有对应,另外和.dynsym好似有次序对应关系(不很确定)。通过这可方便解析函数符号地址,详细可参考连接器解析函数(连接器一般是动态加载,像全局数据符号那样,程序启动时加载)。注2:readelf -r a.out 查看 .rel.dyn 和.rel.plt.其中 .rel.dyn 类型一般为R_386_GLOB_DAT和R_386_COPY;.rel.plt为R_386_JUMP_SLOT例子在此不举了,分析这个重定位过程,最好还是自己动手写个例子来,比单纯看文章好理解。
分析没多久,还有好多问题需要慢慢分析透彻,大家多多指正。参考http://blog.chinaunix.net/space.php?uid=52437&do=blog&id=2108840 和
http://blog.chinaunix.net/space.php?uid=52437&do=blog&id=2108843
附注:
- .text – contains the module code
- .data – initialized variables
- .bss – non-initialized variables
- .symtab – the module symbols: functions and static variables
- .strtab – the names for module symbols
- .rel.text –the relocation for functions (for statically linked modules)
- .rel.data – the relocation for static variables (for statically linked modules)
- .rel.plt – the list of elements in the PLT (Procedure Linkage
Table), which are liable to the relocation during the dynamic linking
(if PLT is used)
- .rel.dyn – the relocation for dynamically linked functions (if PLT is not used)
- .got – Global Offset Table, contains the information about the offsets of relocated objects
- .debug –the debug information
阅读(1075) | 评论(0) | 转发(0) |