翻译自:Understanding ld-linux.so.2

前言

ld-linux.so.2是linux的动态加载器(dynamic loader)。本文试图就ld-linux.so.2如何与Linux交互,如何与正在调用的应用程序进行交互 给出一个概述。

什么是ld-linux.so

现在,大多数程序都是动态链接的。 当操作系统加载一个动态链接的应用程序时,它必须找到并加载它执行该应用程序所依赖的动态库。 在linux系统上,这份工作由ld-linux.so.2处理。 你可以对一个应用程序 或 动态库使用ldd命令查看他依赖哪些库。

root@ubuntu:/lib# ldd `which ls`
linux-vdso.so. => (0x00007ffdb075f000)
libselinux.so. => /lib/x86_64-linux-gnu/libselinux.so. (0x00007fb9e3650000)
libc.so. => /lib/x86_64-linux-gnu/libc.so. (0x00007fb9e3286000)
libpcre.so. => /lib/x86_64-linux-gnu/libpcre.so. (0x00007fb9e3016000)
libdl.so. => /lib/x86_64-linux-gnu/libdl.so. (0x00007fb9e2e11000)
/lib64/ld-linux-x86-.so. (0x00005607fd069000)
libpthread.so. => /lib/x86_64-linux-gnu/libpthread.so. (0x00007fb9e2bf4000)

当应用程序ls被加载到内存时,OS将控制权传递给ld-linux.so.2,而不是应用程序ls的正常入口点。 ld-linux.so.2搜索并加载未解析的库,然后将控制权传递给应用程序的起始点。

ld-linux.so.2的man手册页给了动态链接器(dynamic linker)一个高层次的概述。 ld-linux.so.2是链接器(linker)(ld)的运行时组件,它定位应用程序使用的动态库并将其加载到内存中。 通常,在链接期间隐式指定动态链接器。 ELF规范说GCC包含一个名为INTERP的特殊ELF程序头,它的p_type为PT_INTERP。 此程序头指定解释器(interpreter)的路径。 您可以使用readelf命令检查给定程序的程序头:

root@ubuntu:/lib# readelf -l `which ls`

Elf file type is EXEC (Executable file)
Entry point 0x4049a0
There are program headers, starting at offset Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000001f8 0x00000000000001f8 R E
INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238
0x000000000000001c 0x000000000000001c R
[Requesting program interpreter: /lib64/ld-linux-x86-.so.]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x000000000001da64 0x000000000001da64 R E
LOAD 0x000000000001de00 0x000000000061de00 0x000000000061de00
0x0000000000000800 0x0000000000001568 RW
DYNAMIC 0x000000000001de18 0x000000000061de18 0x000000000061de18
0x00000000000001e0 0x00000000000001e0 RW
NOTE 0x0000000000000254 0x0000000000400254 0x0000000000400254
0x0000000000000044 0x0000000000000044 R
GNU_EH_FRAME 0x000000000001a5f4 0x000000000041a5f4 0x000000000041a5f4
0x0000000000000804 0x0000000000000804 R
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW
GNU_RELRO 0x000000000001de00 0x000000000061de00 0x000000000061de00
0x0000000000000200 0x0000000000000200 R Section to Segment mapping:
Segment Sections... .interp
.interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame
.init_array .fini_array .jcr .dynamic .got .got.plt .data .bss
.dynamic
.note.ABI-tag .note.gnu.build-id
.eh_frame_hdr .init_array .fini_array .jcr .dynamic .got

ELF规范要求如果存在PT_INTERP部分,则操作系统必须创建解释器文件段(interpreter's file segments)的进程映像,而不是应用程序的过程映像。 然后控制权转到解释器,解释器负责加载动态库。 ELF规范在如何给出控制方面提供了一定程度的灵活性。 对于x86 / Linux,传递给动态加载程序的参数是指向mmap'd节的指针。

编译细节

Glibc负责创建ld-linux.so.2。在glibc 2.3.2版中,使用以下命令创建文件:

gcc -nostdlib -nostartfiles -shared \
-o /home/dww4s/packages/glibc-build/elf/ld.so \
-Wl,-z,combreloc -Wl,-z,defs \
/home/dww4s/packages/glibc-build/elf/librtld.os \
-Wl,--version-script=/home/dww4s/packages/glibc-build/ld.map \
-Wl,-soname=ld-linux.so. \
-T /home/dww4s/packages/glibc-build/elf/ld.so.lds

通过-shared标志,将构建一个名为ld.so的共享库。ld.so的符号链接是ld-linux.so.2。唯一的输入是librtld.os,它在make过程的早期通过命令创建了几行:

gcc -nostdlib -nostartfiles -r \
-o /home/dww4s/packages/glibc-build/elf/librtld.os \
'-Wl,-(' \
/home/dww4s/packages/glibc-build/elf/dl-allobjs.os \
/home/dww4s/packages/glibc-build/elf/rtld-libc.a \
-lgcc \
'-Wl,-)'

因此,作为librtld.os包含的文件dl-allobjs.os,rtld-libc.a以及libgcc.so。 请注意使用-Wl前缀发送到链接器的参数 - (和 - )。 这些参数告诉链接器迭代存档直到达到稳定状态。 dl-allobjs.os和rtld-libc.a包含共享库的目标文件以及入口点_start。 _start在rtld.c中定义,来自头文件dl-machine.h中包含的宏(RTLD_START)。 宏扩展为内联程序集,用于定义_start符号,并调用函数_dl_start。 由于ld-linux.so.2有一个_start符号,因此可以直接运行。

理解ld-linux.so.2的更多相关文章

  1. 彻底理解Cisco/Linux/Windows的IP路由

    -1.只要理解实质,名称并不重要! 很多使用Linux的网络高手在面对Cisco管理员的诸如管理距离,路由度量等词汇时,还没有PK就自觉败下阵来了.我觉得这实在太可惜了,大家本是一家,为何这么为难对方 ...

  2. 我理解的Linux内存管理

    众所周知,内存管理是Linux内核中最基础,也是相当重要的部分.理解相关原理,不管是对内存的理解,还是对大家写用户态代码都很有帮助.很多书上.很多文章都写了相关内容,但个人总觉得内容太复杂,不是太容易 ...

  3. Linux系统理解以及Linux系统学习心得

    原创作品转载请注明出处  <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 作者:严哲璟 说一下我对Lin ...

  4. 操作系统-多用户如何理解(Linux)

    单用户.多用户.单任务.多任务,这么多种操作系统容易让人迷糊.其实这种初看你会觉得理解了一点,但其实你仔细研究会发现,多用户到底讲的是什么鬼? 多任务比较简单,就是应用程序都要放置到内存上去给CPU调 ...

  5. [翻译]理解分析Linux里的101个ELF文件

    原文:https://linux-audit.com/elf-binaries-on-linux-understanding-and-analysis/

  6. 深入理解LINUX下动态库链接器/加载器ld-linux.so.2

    [ld-linux-x86-64.so.2] 最近在Linux 环境下开发,搞了好几天 Compiler 和 linker,觉得有必要来写一篇关于Linux环境下 ld.so的文章了,google上搜 ...

  7. 理解linux and inode

    inode是一个重要概念,是理解Unix/Linux文件系统和硬盘储存的基础. 我觉得,理解inode,不仅有助于提高系统操作水平,还有助于体会Unix设计哲学,即如何把底层的复杂性抽象成一个简单概念 ...

  8. 理解Linux文件系统之inode

    很少转发别人的文章,但是这篇写的太好了. 理解inode   作者: 阮一峰 inode是一个重要概念,是理解Unix/Linux文件系统和硬盘储存的基础. 我觉得,理解inode,不仅有助于提高系统 ...

  9. 深入理解linux关闭文件和删除文件

    背景介绍 最近看了linux系统编程(linux system programming)一书,结合深入理解linux内核(understanding the linux kernel)一书,深入理解了 ...

  10. [转]理解Linux文件系统之inode

    很少转发别人的文章,但是这篇写的太好了. 理解inode   作者: 阮一峰 inode是一个重要概念,是理解Unix/Linux文件系统和硬盘储存的基础. 我觉得,理解inode,不仅有助于提高系统 ...

随机推荐

  1. matplot中的对象

    figure:图表,可以理解为一个空间,二维情况下是一个平面 axes:坐标系,空间中的坐标系,一个空间可以有多个坐标系 axis:坐标轴,坐标系中的一个坐标轴,一个坐标轴只属于一个坐标系 画点:sc ...

  2. Cas(04)——更改认证方式

    在Cas Server的WEB-INF目录下有一个deployerConfigContext.xml文件,该文件是基于Spring的配置文件,里面存放的内容常常是部署人员需要修改的内容.其中认证方式也 ...

  3. 服务发现框架选型,Consul还是Zookeeper还是etcd

    背景 本文并不介绍服务发现的基本原理.除了一致性算法之外,其他并没有太多高深的算法,网上的资料很容易让大家明白上面是服务发现. 想直接查看结论的同学,请直接跳到文末. 目前,市面上有非常多的服务发现工 ...

  4. servlet中ServletContainerInitializer的简单说明

    根据官方文档到的说明 public interface ServletContainerInitializer Interface which allows a library/runtime to ...

  5. C#、.NET、ASP.NET之间的关系

    一.前言 这是个人的笔记,在博客园已经有不少大佬已经写过了.但我自己就想留点笔记在属于我自己的博客.所以大佬忽略就行,不喜勿碰.谢谢!!! 二.个人笔记 C# 全称(C sharp),它是微软公司发布 ...

  6. 漏洞复现之JBoss 4.x JBossMQ JMS 反序列化漏洞(CVE-2017-7504)

    前言: 序列化就是把对象转换成字节流,便于保存在内存.文件.数据库中:反序列化即逆过程,由字节流还原成对象. Java中的ObjectOutputStream类的writeObject()方法可以实现 ...

  7. linux中硬盘分区、格式化、挂载

    已经接触了小半年的linux,基本命令用的还行,就是涉及到深入操作,就显得不够看了,比如linux中的硬盘操作,于是整理了这篇博客. 1. 主分区,扩展分区,逻辑分区的联系和区别 ​ 一个硬盘可以有1 ...

  8. GridView取不到值的问题总结

    在ASP.NET开发过程中,使用GridView进行数据表现的时候遇到过两次取不到值的问题.分别是初学的时候与 用了一年多以后.出现的问题并不是身边么高深的技术,但是可能会经常遇到,所以这里我做一下总 ...

  9. (3)Spring Boot日志

    文章目录 选择哪一种日志框架 日志的使用 Spring Boot 日志使用 选择哪一种日志框架 市面上日志门面有: JCL(Jakart Commons Logging) .SLF4J(Simple ...

  10. Tomcat部分知识点小结

    * Tomcat:web服务器软件     1. 下载:http://tomcat.apache.org/    2. 安装:解压压缩包即可. * 注意:安装目录建议不要有中文和空格    3. 卸载 ...