Más contenido relacionado La actualidad más candente (19) Similar a Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509 (20) Linux c++ 编程之链接与装载 -提高篇--v0.3--2012050916. Elf64_Rela
// Relocation table entry with addend (in section of type SHT_RELA).
typedef struct
{
Elf64_Addr r_offset; /* Address of need relocation*/
Elf64_Xword r_info; /* Relocation type and symbol index */
Elf64_Sxword r_addend; /* Addend */
} Elf64_Rela;
#define ELF64_R_SYM(i) ((i) >> 32) // 符号表中的下标
#define ELF64_R_TYPE(i) ((i) & 0xffffffff) // 重定位入口的类型
#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32)
+ (type))
17. 重定位类型表
名字 值 计算
R_X86_64_32 1 S+A
R_X86_64_PC32 2 S+A-P
R_X86_64_GOT32 3 G+A
R_X86_64_PLT32 4 L+A- P
R_X86_64_COPY 5 none
R_X86_64_GLOB_DAT 6 S
R_X86_64_JUMP_SLOT 7 S
R_X86_64_RELATIVE 8 B+A
R_X86_64_GOTPCREL 9 S + A - GOT
21. 常见链接错误--库的顺序问总结
• 在链接静态库时, 如果目标文件(.o) 与静态库之间存在依赖关系,
则有依赖关系的目标文件(.o)与静态库存在链接顺序问题。
• 在链接静态库时, 如果动态库 与静态库之间存在依赖关系,则有
依赖关系的动态库与静态库存在链接顺序问题。
• 在链接静态库时,如果多个静态库之间存在依赖关系,则有依
赖关系的静态库之间存在链接顺序问题。
• 静态库之间存在循环依赖的时候经常需要根据依赖关系,需将静
态库列出多次.
• 最好遵守从左到右排序对象文件的惯例.
22. 动态链接
主要实现技术
显式运行时加载(dlopen/dlsym/dlclose)
动态链接过程
符号的优先级与全局符号介入
C++全局变量的构造与析构
23. 动态链接的主要实现技术
• 方便程序开发,部属: • 性能优化:
方法:程序的各模块独立, 方法:延迟绑定(Lazy
装载时才链接(符号查找,
Binding)
重定位).
技术实现:函数链接表
• 节约内存:
(PLT)
方法: 地址无关代码(PIC)
• 程序的可扩展性与兼容性:
技术实现:全局偏移量表
方法: 显式运行时加载
(GOT)
24. 主要实现技术—相关数据结构
• .interp 节: 动态链接器 ld.so
• .dynamic 节: 保存了动态链接器所需的基本信息,
• 动态符号表:
.dynsym: 只保存与动态链接相关的符号;
.dynstr: 动态符号字符串表:
.hash .gnu.hash: 输助的符号哈唏表
• 动态链接相关的重定位表:
.rela.plt : 对数据引用的修正,它所修正的位置
位于".got" 和数据段.
.rela.dyn : 对函数引用的修正,它所修正的位
置位于".got.plt"
26. 动态链接的实现--地址无关代码
类型 2:模块内部的数据访问
类型 4:模块外部的数据访问
类型 1:模块内部的函数调用
类型 3:模块外部的函数调用
29. 显式运行时加载
#include <dlfcn.h>
void *dlopen(const char *filename, int flag);
功能:指定模式打开指定的动态连接库文件,并返回
一个句柄给调用进程.
Flags 取值:
RTLD_LAZY: 延迟绑定,等有需要时再解出符号
RTLD_NOW: 立即绑定,返回前解除所有未决定的符号。
RTLD_LOCAL: 与RTLD_GLOBAL作用相反,动态库中定义
的符号不能被其后打开的其它库重定位。没有指定,则
缺省为RTLD_LOCAL。
RTLD_GLOBAL 动态库中定义的符号可被其后打开的其
它库重定位。
RTLD_DEEPBIND:符号查找优先在本共享库的符号表,找
不到才去全局符号表中查找
30. 显式运行时加载
void *dlsym(void *handle, const char *symbol);
• 功能:返回指定符号的地址
• handle 取值:
RTLD_DEFAULT: 直接在可执行程序的全局符号
表中查找
RTLD_NEXT: 在可执行程序的全局符号表中查找
第2次出现的符号。
dlopen 返回的 handle
31. dlsym 之RTLD_NEXT应用
--Hook内存函数malloc
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
void *malloc(size_t size) {
size_t *(*_malloc)(size_t size) = NULL;
_malloc = (size_t *(*)(size_t size)) dlsym(RTLD_NEXT,
"malloc");
return NULL;
}
52. C++全局变量的构造与析构--.ctors 节的形成
• g++ -o $@ $^ -L./ -Wl,-Bstatic -lclass_a -Wl,-Bdynamic
-ldl --verbose
/usr/libexec/gcc/x86_64-redhat-linux/4.1.2/collect2
--eh-frame-hdr -m elf_x86_64 --hash-style=gnu -
dynamic-linker /lib64/ld-linux-x86-64.so.2 -o main
/usr/lib64/crt1.o /usr/lib64/crti.o /usr/lib/gcc/x86_64-
redhat-linux/4.1.2/crtbegin.o -L./ -L/usr/lib/gcc/x86_64-
redhat-linux/4.1.2 -L/usr/lib/gcc/x86_64-redhat-
linux/4.1.2 -L/usr/lib64 -L/lib64 -L/usr//lib64 main.o -
Bstatic -lclass_a -Bdynamic -ldl -lstdc++ -lm -lgcc_s -lgcc -
lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-redhat-
linux/4.1.2/crtend.o /usr/lib64/crtn.o
68. ELF 文件结构概述
int printf(const char * format,...);
int global_init_var=84;
int global_uninit_var;
void func1(int i )
{
printf("%dn",i);
}
int main(void)
{
static int static_var=85;
static int static_var2;
int a=1;
int b;
func1(static_var+static_var2+a+b);
return a;
}
70. ELF 文件结构概述
名称 说明
文件头 位于目标文件最开始的位置,含有整个文件的一些基本信息.
程序头表 一个可执行文件或共享目标文件的程序头表是一个数组,数组
中的每一个元素称为“程序头”.描述了一个
“段(segment)”或者一块用于准备执行程序的信息。
节头表 是一个数组,每一项是一个 Elf32(64)_Shdr 结构,通过每一个表
项可以定位到对应的节。
.strtab 表 字符串表包含有若干个以’null’结尾的字符序列,即字符串. 保存
符号的名字或者节的名字
.symtab 表 符号表包含用来定位、重定位程序中符号定义和引用的信息。
重定位表 含如何修改其节区内容的信息,从而允许可执行文件和共享目
标文件保存进程的程序映像的正确信息.静态链接:.rela.text
和 .rela.data); 动态链接:.rela.plt 和.rela.dyn
71. ELF 文件结构概述
名称 说明
.dynstr 表 动态字符串表包含有若干个以’null’结尾的字符序列,即字符串.
保存动态符号的名字的名字
.dynsym 表 动态符号表包含的信息用于动态重定位程序中的符号定义和引用
.interp 节 动态链接器 , /lib64/ld-linux-x86-64.so.2
.dynamic 节 保存动态链接器所需要的基本信息,如依赖的DSO, dynsym 表的位
置 ,动态链接重定位表的位置等.
全局偏移表 全局偏移表在私有数据中包含绝对地址,从而使得地址可用,并
(GOT) 且不会影响位置独立性和程序代码的可共享性。如果程序需要直
接访问某个符号的绝对地址,该符号就会具有一个全局偏移表项.
重定位项的类型 R_386_GLOB_DAT ,表示对全局偏移表的引用
过程链接表 过程链接表(PLT)能够把位置独立的函数调用重定向到绝对位
(PLT ) 置.
哈希表(Hash 哈希表支持符号表访问
Ta ble)
73. ELF Loading View
• Much simpler view, divides
executable into ‘Segments’
• Only includes data to be loaded
into memory at runtime
• Segments have:
– A simple type
– Requested memory location at run
time
– Permissions
(readable/writeable/executable)