您的位置:首页 > 运维架构 > Linux

linux 动态链接器相关

2016-04-01 13:38 423 查看
linux下程序的链接方式分为两种:静态链接

动态链接。

静态链接就是在生成可执行文件的时候,把程序用到的各个库和目标文件链接到一块儿生成一个可执行文件。静态链接看起来很简单,但是有些不足。其中之一就对磁盘空间和内存空间的浪费。标准库中那些函数会被放到每个静态链接的可执行文件中,在运行的时候,这些重复的内容也会被不同的可执行文件加载到内存中去。同时,如果静态库有更新的话,所有可执行文件都得重新链接才能用上新的静态库。动态链接就是为了解决这个问题而出现的。

所谓动态链接就是在运行的时候再去链接。理解动态链接需要从两个角度来看,一是从动态库的角度,二是从使用动态库的可执行文件的角度。

动态库和普通的可执行文件一样,有代码段和数据段。为了实现动态库在不同程序之间的共享,需要做到不管动态库被装在到内存的什么位置,都不需要修改动态库代码段的内容,也就是要做到PIC(position independent code),为了达到这个目的,动态库把变化的部分全部放到了数据段中,代码段采用相对定位的方式实现。

动态链接的程序由于用到了外部动态库中的函数和变量,因此不能直接运行,需要动态链接器帮助加载该可执行文件需要的外部动态库,并完成符号解析和变量的重定位,之后才会从入口点开始运行。

在Linux下,这一过程大致如下。

假如我们要运行linux的ls命令,在ls可执行文件的头部记录了动态链接器的路径,如:

$readelf -l /bin/ls

Elf file type is EXEC (Executable file)

Entry point 0x4048c5

There are 9 program headers, starting at offset 64

Program Headers:

Type Offset VirtAddr PhysAddr

FileSiz MemSiz Flags Align

PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040

0x00000000000001f8 0x00000000000001f8 R E 8

INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238

0x000000000000001c 0x000000000000001c R 1

[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]

LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000

0x000000000001bad4 0x000000000001bad4 R E 200000

LOAD 0x000000000001bdf0 0x000000000061bdf0 0x000000000061bdf0

0x0000000000000864 0x00000000000016d0 RW 200000

DYNAMIC 0x000000000001be08 0x000000000061be08 0x000000000061be08

0x00000000000001f0 0x00000000000001f0 RW 8

NOTE 0x0000000000000254 0x0000000000400254 0x0000000000400254

0x0000000000000044 0x0000000000000044 R 4

GNU_EH_FRAME 0x0000000000018cdc 0x0000000000418cdc 0x0000000000418cdc

0x0000000000000744 0x0000000000000744 R 4

GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000

0x0000000000000000 0x0000000000000000 RW 10

GNU_RELRO 0x000000000001bdf0 0x000000000061bdf0 0x000000000061bdf0

0x0000000000000210 0x0000000000000210 R 1

其中/lib64/ld-linux-x86-64.so.2就是该系统用到的动态链接器,动态链接器本身也是一个可执行文件,相关参数如下:

Usage: ld.so [OPTION]... EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]

--list list all dependencies and how they are resolved

--verify verify that given object really is a dynamically linked object we can handle

--inhibit-cache Do not use /etc/ld.so.cache

--library-path PATH use given PATH instead of content of the environment variable LD_LIBRARY_PATH

--inhibit-rpath LIST ignore RUNPATH and RPATH information in object names in LIST

--audit LIST use objects named in LIST as auditors

—list参数显示一个可执行文件用到的动态库列表,例如:

$/lib64/ld-linux-x86-64.so.2 --list /bin/ls

linux-vdso.so.1 => (0x00007fffded4d000)

libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f9b1b3d3000)

libacl.so.1 => /lib/x86_64-linux-gnu/libacl.so.1 (0x00007f9b1b1ca000)

libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9b1adff000)

libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f9b1ab92000)

libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f9b1a98e000)

/lib64/ld-linux-x86-64.so.2 (0x00007f9b1b602000)

libattr.so.1 => /lib/x86_64-linux-gnu/libattr.so.1 (0x00007f9b1a788000)

libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f9b1a56a000)

关于动态链接器的更多选项可以man ld.so来查看,例如想调试动态链接器工作的具体细节,可以通过设置LD_DEBUG环境变量来进行,

$LD_DEBUG=help ls

Valid options for the LD_DEBUG environment variable are:

libs display library search paths

reloc display relocation processing

files display progress for input file

symbols display symbol table processing

bindings display information about symbol binding

versions display version dependencies

scopes display scope information

all all previous options combined

statistics display relocation statistics

unused determined unused DSOs

help display this help message and exit

当LD_DEBUG为libs的时候,可以查看动态库的搜索路径,如LD_DEBUG=libs
ls
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: