动态链接器

动态链接器

动态链接器属于glibc的一部分, 本文章用glibc2.17分析

link map

一个可执行文件或一个共享库对应一个link map, link map有三种类型, lt_executable, lt_library和lt_loaded。 其中lt_executable代表可执行文件,lt_loaded代表dlopen的共享库, lt_library代表lt_executable或lt_loaded或lt_library的DT_NEEDED项的link map。(或是预加载的共享库?)
link map 是got.plt的第二项的值, 数据结构为 struct link_map。结构体中的成员含义如下:

成员含义
l_typelink map类型
l_ld指向dynamic section
l_ldnumdynamic section entity 数量
l_infodynamic section 解析后的数据
l_direct_opencoundlopen次数
l_rpath_dirsDT_RPATH数据
reallink map的地址
l_global对应RTLD_GLOBAL和RTLD_LOCAL,该动态库的符号是否可以用于后续的符号解析(PS:manpage 上写的是后续加载的动态库的符号解析, 我理解的是后续的符号解析,因为当先打开main program的link_map再加载该动态库, 用main program的link map 也可以解析到该动态库函数的地址)
l_reserved获取新模块的link map时用于判断模块否加载过
l_loader装载该模块的模块,main program 和 dlopen的共享库都是NULL
l_namelink_map 对应的模块的名字 main program对应的是"“,所以可以用dlopen(”")获取 main program的link map
l_scope[0]等于loader的l_scope[0],如果没有loade,指向l_searchlist
l_local_scope[0]指向本模块的l_searchlist
l_scope_meml_scope指向的内存空间
l_symbolic_searchlist.r_list
l_libnamelibname 共享库有4个名字, libname, realname,soname, linkname
l_initfini用于调用构造析构函数
l_searchlist包括可执行文件模块和依赖的所有共享库的link map
l_nsnamespace, 和loader共享一个namespace
l_phdr程序头虚拟地址偏移
l_map_start模块映射的起始地址
l_map_end模块映射的终止地址, 通过PT_LOAD的segment算出来
l_contiguous模块映射各个segment之间是否有空洞
l_versions.gnu.version_r section 数据
l_used是否有符号被引用
l_serial进程第几个加载该共享库
l_ino共享库inode
l_dev

特殊的link map
1 RTLD_DEFAULT 搜索 base namespace
2 RTLD_NEXT 按namespace的搜索顺序搜索, 略过调用的link map及前面的link map
3 vdso的link map 属于base namespace, 但是loader不是main program, 没有loader

关键函数

_dl_map_object 在已经加载的模块中寻找object, 如果找不到的话,获取共享库的realname并打开, 接着调用_dl_map_object_from_fd加载object, 创建link map

_dl_map_object_deps 调用_dl_map_object, 打开依赖的模块

_dl_map_object_from_fd 调用_dl_new_object创建link map并加载object

_dl_new_object 创建一个 link map, 初始化内容

open_aux 调用_dl_map_object, 通过原模块的link map类型确认打开的新模块的link map 类型

do_sym 根据handle类型确认

_dl_lookup_symbol_x

全局变量

GL(dl_ns)[] 0指向全局符号的模块链表的名字空间,其它指向dlmopen的名字空间

GL(dl_rtld_map) 动态链接器的link map

GL(dl_nns) 使用的名字空间的数量

GL(dl_load_adds) 装载的共享库的数量

GLRO(dl_lazy) 是否默认为lazy加载

常量

LM_ID_BASE main program 和它的依赖所在的nsid
__LM_ID_CALLER dlopen打开的link map的默认nsid,会重新赋值loader的nsid

RTLD_NOW
RTLD_LAZY
在加载的时候还是引用的时候重定位RELA和JMPREL中的符号

RTLD_LOCAL
RTLD_GLOBAL
GLOBAL的话可以使用dlsym(RTLD_DEFAULT) dlsym(RTLD_NEXT) 和直接引用获取到该共享库定义的动态符号的地址, RTLD_LOCAL只能通过 dlsym(handle)获取到地址

重定位类型

R_X86_64_COPY 非fPIC的object引用shared object的变量

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值