最近跟编译工具干上了,可能是问题积累集中爆发的结果。

今天对 ld-linux.so.x 有很大兴趣,想对它多些了解,遂百度之。发现了指令 ldd。

关于 ldd

其实 ldd 是一个脚本,并不是一个二进制文件。

它的原理很简单:当环境变量 LD_TRACE_LOADED_OBJECTS 不为空时,只显示依赖关系,不执行程序。我们可以手动试试。

ldd 开启了一个独立的运行空间,设置了环境变量,然后执行程序,把执行的结果返回。

其他的变量(和值)分别对应一些选项:
  -d, --data-relocs -》 LD_WARN=yes
  -r, --function-relocs -》LD_WARN和LD_BIND_NOW=yes
  -u, --unused -》 LD_DEBUG=“unused”
  -v, --verbose -》 LD_VERBOSE=yes
LD_TRACE_LOADED_OBJECTS为必要环境变量,其他视具体情况。

编译 dummy.c

继续使用 dummy.c 对工具链进行实验。

$ echo 'main(){}' > dummy.c
$ gcc dummy.c -o demo
$ ldd demo
linux-gate.so. => (0x00a6c000)
libc.so. => /lib/i386-linux-gnu/libc.so. (0x00ad5000)
/lib/ld-linux.so. (0x00a71000)

所以,最简单没有任何任务的 dummy.c ,需要这 3 个动态库才能执行:

1. linux-gate.so.1 这个库无法在文件下系统中找到。它只是一个虚拟的动态链接库(VDSO, Virtual Dynamically Shared Object),是一个完整的 elf shared object,是内核镜像中的某个特定页;在使用 exec() 执行新的镜像时,linux-gate.so 被页面映射到程序的进程空间中(process's memmory)。想对它进一步了解,可以阅读参考 1 。

2. libc.so.6 标准 C 库。就是我们在制作工具链时编译出来的那一个。

3. ld-linux.so.2 动态连接的实际执行者。

在手上的 armbox 中进行上面实验,并没有 linux-gate.so.1:

$ ldd demo
libc.so. => /lib/arm-linux-gnueabihf/libc.so. (0x76e13000)
/lib/ld-linux-armhf.so. (0x76f27000)

今天的主角是 ld-linux.so.x ,这里就不对 linux-gate.so.1 进行深究了。

ELF 中的 PT_INTERP

如果只是说 ld-linux.so.x 是动态链接库的解释器,那么,未免有些单调了。我先从追踪 gcc 编译出来程序开始。

$ strace ./demo
execve("./demo", ["./demo"], [/* 41 vars */]) =
brk() = 0x9712000
access("/etc/ld.so.nohwcap", F_OK) = - ENOENT (No such file or directory)
mmap2(NULL, , PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -, ) = 0xb7795000
...

这里可以看到,执行文件是交给 execve() 来解释执行的。那么,这里的问题就变成了 execve() 怎么解释这 demo 的问题。没有特殊设置,那么,这里的 demo 肯定是 ELF 格式的文件。。。所以,这里就最后变成了,execve() 怎么解释及执行 ELF 文件的问题。

不想去一点点抠 ELF 的具体结构,所以 man execv() 看了一下。有如下描述:

 If the executable is a dynamically linked ELF executable, the interpreter named the PT_INTERP segment is  used  to load  the  needed  shared  libraries. This interpreter is typically /lib/ld-linux.so.1 for binaries linked with the Linux libc 5, or /lib/ld-linux.so.2 for binaries linked with the glibc 2 

execve() 是 <unistd.h> 中的函数。

使用 readelf 查看我们编译出的二进制文件:

Elf file type is EXEC (Executable file)
Entry point 0x8048300
There are program headers, starting at offset Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4
INTERP 0x000154 0x08048154 0x08048154 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.]
...

这里看到的内容和我们上面了解到的是一致的。

所以,我们在这里得出结论:1) 使用 ld-linux.so.* 作为解释器,是写在二进制文件中的,比如上面编译好的 demo 中。另外的,2) 其它库的查找和加载,则是 ld-linux.so.* 完成的。

ld-linux.so.* 如何加载库?

目前已知的方法是,使用环境变量 LD_LIBRARY_PATH=/lib/ 来定位库的位置。待探索。

参考:

1. http://www.trilithium.com/johan/2005/08/linux-gate/

2. man execve

3. man elf

ldd 以及 ld-linux.so.2的更多相关文章

  1. Linux Programe/Dynamic Shared Library Entry/Exit Point && Glibc Entry Point/Function

    目录 . 引言 . C/C++运行库 . 静态Glibc && 可执行文件 入口/终止函数 . 动态Glibc && 可执行文件 入口/终止函数 . 静态Glibc & ...

  2. linux复习

    linux的特点           - 免费的/开源           - 支持多线程/多用户           - 安全性好           - 对内存和文件管理优越       关机命令 ...

  3. linux笔试

    在对linux基本知识的归纳总结之后,这里是一份linux的测试题.希望能帮助大家复习和熟悉linux知识. 一.选择题 1.cron 后台常驻程序 (daemon) 用于:  A. 负责文件在网络中 ...

  4. linux测试题

    http://www.2cto.com/os/201307/225399.html  2013最新linux运维面试题 在对linux基本知识的归纳总结之后,这里是一份linux的测试题.希望能帮助大 ...

  5. 100 道 Linux 笔试题

    1. cron 后台常驻程序 (daemon) 用于: A. 负责文件在网络中的共享 B. 管理打印子系统C. 跟踪管理系统信息和错误 D. 管理系统日常任务的调度 2. 在大多数Linux发行版本中 ...

  6. <摘录>ldconfig和ldd用法

    ldconfig和ldd用法 关键字: ldconfig ldd /etc/ld.so.conf LD_LIBRARY_PATH一.ldconfig ldconfig --helpUsage: ldc ...

  7. 100 道 Linux 笔试题,能拿 80 分就算大神!

    本套笔试题共100题,每题1分,共100分.(参考答案在文章末尾) 1. cron 后台常驻程序 (daemon) 用于: A. 负责文件在网络中的共享 B. 管理打印子系统C. 跟踪管理系统信息和错 ...

  8. linux笔试题

    1. cron 后台常驻程序 (daemon) 用于: A. 负责文件在网络中的共享 B. 管理打印子系统 C. 跟踪管理系统信息和错误 D. 管理系统日常任务的调度 2. 在大多数Linux发行版本 ...

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

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

  10. 《手把手教你构建自己的 Linux 系统》学习笔记(6)

    目录 /dev 目录是干什么的? /proc 和 /sys 目录是干什么的? udev 这个软件是干什么用的? 目录映射是临时性的,还是永久性的? 命令行里大括号 "{}" 的作用 ...

随机推荐

  1. Unity5中新的Shader体系简析

    一.Unity5中新的Shader体系简析 Unity5和之前的书写模式有了一定的改变.Unity5时代的Shader Reference官方文档也进一步地变得丰满. 主要需要了解到的是,在原来的Un ...

  2. Java Swing 使用非本地字体

    package reyo; import java.awt.Container; import java.awt.Font; import java.awt.FontFormatException; ...

  3. 盾牌第一至七季/全集The Shield迅雷下载

    英文译名The Shield,第1-7季(2002-2008)FX.本季看点:<盾牌>一部极具争议性的连续剧,打破了传统警匪片套路,刻画了性格复杂的警察,他们在与各种罪案做斗争的同时,也面 ...

  4. 实用ExtJS教程100例-011:ExtJS Form 使用JSON数据赋值和取值

    上一节中我们演示了ExtJS Form的异步加载和提交数据,本节中我们将演示如何使用JSON数据为ExtJS Form中的字段赋值和取值. 系列ExtJS教程持续更新中,点击查看>>最新E ...

  5. vi 方向键 ABC

    解决方法:修改/etc/vim/vimrc.tiny ,增加set nocompatible,然后 保存,作用是关闭 vi 兼容模式

  6. ThinkPHP错误信息处理

    index.php入口文件中打开APP_DEBUG// 开启调试模式define('APP_DEBUG', TRUE); // 开启Trace信息 'SHOW_PAGE_TRACE' =>tru ...

  7. 硬盘杀手!Windows版Redis疯狂占用C盘空间!

    关键词:Redis占用C盘,Windows Redis,64位Windows版Redis疯狂占用C盘空间,redis启动后创建RedisQFolk_****.dat文件.redis-server.ex ...

  8. 深度学习Github排名,很不错的介绍

    今天看到这篇文章,把深度学习github排名靠前的项目,介绍了一下,很不错: https://blog.csdn.net/yH0VLDe8VG8ep9VGe/article/details/81611 ...

  9. .NET开发过程中的全文索引使用技巧之Solr(转)

       前言:相信许多人都听说过.net开发过程中基于Lucene.net实现的全文索引,而Solr是一个高性能,基于Lucene的全文搜索服务器.同时对其进行了扩展,提供了比Lucene更为丰富的查询 ...

  10. [leetcode]Palindrome Partitioning @ Python

    原题地址:https://oj.leetcode.com/problems/palindrome-partitioning/ 题意: Given a string s, partition s suc ...