ldd 以及 ld-linux.so.2

摘要:
今天,我们将回顾ld linux。所以X对它很感兴趣,想了解更多,所以百度。上述实验是在手上的扶手箱中进行的。没有linux-gate.so。1: 美元。所以6=˃/lib/arm-linux-gnueabihf/libc。所以6/lib/ld-linuxarmhf。所以3.今天的主角是ld linux。所以x、 所以我们不会进入linux-gate.so。1.ELF_中的PT如果INTERP只是说ld linux。因此X是动态链接库的解释器。它的描述如下:如果可执行文件是动态链接的ELFexecutable,则名为PT_ INTERP段的解释器将访问新的共享库。这解释为/lib/ld linux。所以1与Linuxlibc5或/lib/ld linux链接。所以2forbitarieslinkedwiththelibc2execve()是 。因此,我们得出以下结论:1)使用ld-linux。所以*作为一个解释器,它是用二进制文件编写的,比如上面编译的演示。此外,2)其他库的搜索和加载由ld-linux完成。所以。*。

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

今天对 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.1 =>  (0x00a6c000)
    libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x00ad5000)
    /lib/ld-linux.so.2 (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.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0x76e13000)
    /lib/ld-linux-armhf.so.3 (0x76f27000)

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

ELF 中的 PT_INTERP

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

$ strace ./demo
execve("./demo", ["./demo"], [/*41 vars */]) = 0
brk(0)                                  = 0x9712000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such fileor directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 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 9 program headers, starting at offset 52
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.2]
...

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

所以,我们在这里得出结论: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》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Android客户端实现七牛云存储文件上传WPF DevExpress ChartControl使用之XYDiagram下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

ubuntu下命令行安装jdk --转载

1.ubuntu使用的是openjdk,所以我们需要先找到合适的jdk版本。在命令行中输入命令: $apt-cache search openjdk 返回结果列表(因个人电脑而有所不同): default-jdk-doc - Standard Java or Java compatible Development Kit (documentation) …...

vs2010驱动开发环境配置

1、文件 -> 新建 -> 项目 -> Visual C++ -> 空项目 名称:Driver 2、生成 -> 配置管理器   活动解决方案配置: 新建 名称:Driver Debug 从此处复制设置:Debug 3、视图 -> 属性管理器  展开刚配置的Driver Debug | Win32  ->  右...

linux 下 奇怪的 动态库 依赖问题

 转:http://fanwei51880.blog.163.com/blog/static/3240674020111145285375/   总结如下:1)当你在编译生成静态库的时候, 只需要相应的依赖库库的头文件即可. 只有在你想生成so,或可执行文件 时, 才需要lib库.   对于你没有用到的lib, 但是不包含又编译失败, 那么只包含其头文件即...

1. CMake 系列

目录 1. 文件目录结构 2. 库文件源代码 3. 编译生成库文件 1. 文件目录结构 首先创建如下目录结构: └── lib ├── build # ├── CMakeLists.txt └── src # ├── add.c └── add.h 从上面的结构,可以看出博主想实现...

Linux下安装mysql

Linux下安装mysql1.下载安装包 到mysql官网下载mysql编译好的二进制安装包,在下载页面Select Platform:选项选择linux-generic,然后把页面拉到底部,64位系统下载Linux - Generic (glibc 2.5) (x86, 64-bit),32位系统下载Linux - Generic (glibc 2.5)...

Python安装sqlite3

今天使用PYthon时,发现错误 ImportError: No module named sqlite 这是因为缺少 SQLITE3的缘故。 下面分享一下解决此问题的方法步骤: 1. 查看是Python是否有该库 使用http://django-china.cn/topic/413/ 查看自己Python库的路径, >>> impor...