linux - linux进程中的多个全局偏移表
问题描述
我正在检查正在运行的进程的内存布局并进行了有趣的观察。似乎有多个 GOT(全局偏移表)。这是我在研究 malloc 函数时在调试器中看到的内容:
(gdb) p (void *) 0x7ff5806ae020
$5 = (void *) 0x7ff5806ae020 <malloc@got.plt>
(gdb) p (void *) 0x7ff5806471d0
$6 = (void *) 0x7ff5806471d0 <malloc@got.plt>
(gdb) p (void *) 0x5634ef446030
$7 = (void *) 0x5634ef446030 <malloc@got.plt>
我检查了malloc
蹦床的 3 个不同地址。当我查看进程的内存映射时,这些地址对应于以下条目:
7ff580647000-7ff580648000 rw-p 0001c000 fd:01 547076 /lib/x86_64-linux-gnu/libpthread-2.31.so
5634ef446000-5634ef447000 rw-p 00003000 fd:02 12248955 /home/user/binary
7ff5806ae000-7ff5806af000 rw-p 0002a000 fd:01 523810 /lib/x86_64-linux-gnu/ld-2.31.so
我看到不同的条目对应于不同的“可链接对象”:二进制和两个动态库。
此外,三分之二的蹦床指向实际功能。并且两个指针都是一样的。第三个蹦床指向存根。
(gdb) p *(void **) 0x5634ef446030
$8 = (void *) 0x7ff5804ef1b0 <__GI___libc_malloc>
(gdb) p *(void **) 0x7ff5806471d0
$9 = (void *) 0x7ff580631396 <malloc@plt+6>
(gdb) p *(void **) 0x7ff5806ae020
$10 = (void *) 0x7ff5804ef1b0 <__GI___libc_malloc>
真的需要三个蹦床吗?如果是,那为什么?
解决方案
我意识到这样的系统是实现蹦床的唯一明智方法。
在汇编中,对动态链接函数的每条调用指令基本上是指该函数在 GOT 中的索引。索引直接编码在指令中。因此,静态链接时必须知道索引是最新的。否则,程序代码必须在程序每次启动时由动态链接器更新。显然,非常繁琐的任务。
此外,每个库都是单独编译的,因此不能依赖其他库,包括它们的确切 GOT 布局。如果只有一个 GOT,那么一起加载的所有库必须以某种方式就 GOT 中每个条目的含义达成一致。拥有一个由所有库一起填充的共享数据结构(GOT)几乎肯定会产生这种依赖关系。
例如,readelf 说 .so-files 也有表:
$ readelf -S /lib/ld-linux.so.2
[18] .got PROGBITS 00029ff4 028ff4 000008 04 WA 0 0 4
[19] .got.plt PROGBITS 0002a000 029000 000028 04 WA 0 0 4
$ readelf -S /usr/lib/libpurple.so.0.13.0
[21] .got PROGBITS 0000000000137318 00136318
0000000000003cd8 0000000000000008 WA 0 0 8
虽然, libpurple 没有.got.plt
,我不完全理解。
我的困惑来自一个事实,即该表被称为“全球”。与编译模块(.o 文件)相比,“全局”一词实际上意味着该表在可链接对象级别是全局的。
其次,我有一种错觉,认为 GOT 指的是可执行应用程序,而不是任何可动态链接的对象。
推荐阅读
- opencart - 如何在 Opencart 的购物车中硬编码一件商品?
- linux - 用户空间线程实现中的 sleep()
- c++ - “不能增加结束列表迭代器”运行时错误 (Visual C++)
- azure-data-lake - dataFactory V2 - 通配符
- google-apps-script - 尝试复制可变长度列表
- cloudflare - 为什么我必须在 GTmetrix 上测试我的站点两次才能看到 cloudflare 的速度优势?
- c# - 在 SpeechSynthesizer 中改变声音
- python - AttributeError:“应用程序”对象没有属性“标签”
- python - Python中的线程与普通
- bash - Bash脚本无法识别文件