动态库在所有程序中是否具有相同的虚拟内存地址?

愚蠢的问题

当库动态链接到程序时,它在该程序中的地址与其他任何程序中的地址相同吗?

我想到,每个进程都会获得整个地址空间,然后由于ASLR,该进程中的所有内容(包括已经在内存中的动态库)都将映射到其中的半随机部分。

但是我做了一个简短的实验,似乎暗示着内存中库的地址在不同进程之间是固定的,因此可以在程序之间重用?那是对的吗?

我编写了两个简短的C程序,它们使用了“睡眠”功能。在第一个中,我打印出了睡眠函数的地址,在第二个中,我分配了指向该地址的函数指针。我同时运行它们和睡眠功能。

#include <stdio.h>
#include <unistd.h>

int main()
{
    while(1)
    {
        printf("%s\n", &"hi");
        sleep(2);
        printf("pointer to sleep: %p\n", sleep);
    }
}
#include <stdio.h>
#include <unistd.h>

#define sleepagain ((void (*)(int))0x7fff7652e669) //addr of sleep from first program

int main()
{
    while(1)
    {
        printf("%s\n", &"test");
        sleepagain(2);
    }
}

我不确定这将显示什么,但实际上显示的是:a)每次我运行第一个程序时地址都相同,并且b)当我运行第二个程序时睡眠仍然起作用。

我想我了解这是如何工作的,但我很好奇它是否必须按其工作方式工作,其背后的原因是什么?

只是参考一下我看到的答案otool -IvV

a.out:
Indirect symbols for (__TEXT,__stubs) 2 entries
address            index name
0x0000000100000f62     2 _printf
0x0000000100000f68     3 _sleep
Indirect symbols for (__DATA,__nl_symbol_ptr) 2 entries
address            index name
0x0000000100001000     4 dyld_stub_binder
0x0000000100001008 ABSOLUTE
Indirect symbols for (__DATA,__got) 1 entries
address            index name
0x0000000100001010     3 _sleep
Indirect symbols for (__DATA,__la_symbol_ptr) 2 entries
address            index name
0x0000000100001018     2 _printf
0x0000000100001020     3 _sleep

这也是lldb中的间接地址。该地址就是睡眠本身的地址:

Process 11209 launched: 'stuff/a.out' (x86_64)
hi
Process 11209 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x00007fff7652e669 libsystem_c.dylib`sleep
libsystem_c.dylib`sleep:
->  0x7fff7652e669 <+0>: push   rbp
    0x7fff7652e66a <+1>: mov    rbp, rsp
    0x7fff7652e66d <+4>: push   rbx
    0x7fff7652e66e <+5>: sub    rsp, 0x28
Target 0: (a.out) stopped.

有关其他信息:

$ otool -hv a.out
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
MH_MAGIC_64  X86_64        ALL LIB64     EXECUTE    15       1296   NOUNDEFS DYLDLINK TWOLEVEL PIE
肯·托马斯(Ken Thomases)

在macOS上,许多系统库是dyld共享缓存的一部分。有一个机器范围的映射。因此,这些库在相同体系结构(32位或64位)的所有进程中最终都位于相同的地址。

dyld共享缓存的位置在系统引导时是随机的。因此,在重新启动之前,库地址在每个进程之间都是相同的。

并非所有系统库都是缓存的一部分,只有Apple认为通常会加载的那些库才是缓存的一部分。

假设您自己或第三方的库在每次加载时都将在随机位置加载,前提是它们与位置无关。

尝试查看的输出vmmap -v <pid>查找带有“计算机范围内的VM子图”的行以及随后的内容。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

链接器是否生成带有 no-pie 标志的最终虚拟内存地址?

线性,物理,逻辑和虚拟内存地址有什么区别?

从虚拟内存地址中查找物理内存地址

数组中的相同字符串具有相同的内存地址

具有相同内存地址但值不同的指针

解耦具有相同内存地址的字典

为什么相同的整数值在Java中具有不同的内存地址?

使两个函数在C ++中具有相同的内存地址

链接器如何生成最终的虚拟内存地址?

用户空间中的虚拟内存地址范围

如果链接脚本中未定义节,则虚拟内存地址错误

x[0], y[0], z[0] 在 cpython 中具有相同的内存地址,但为什么 a 不是?

所有进程的虚拟地址空间在其“内核”部分中具有相同的内容吗?

TLS数据在所有线程中的地址相同

malloc函数将所有数据分配到相同的内存地址

为什么这些调用具有相同的内存地址?

虚拟内存中的地址转换

不同进程的虚拟内存地址空间之间的隔离是否不适用于特权进程和交换?

局部变量拥有相同的内存地址

shmat()为不同的程序返回不同的地址,所有这些程序都具有相同的共享内存

具有16GB虚拟内存并不断增长的Java程序:这有问题吗?

两次调用 iterator.cycle 函数返回相同的迭代器(具有相同的内存地址)

在所有版本的Windows中,%PROGRAMDATA%是否相同?

Linux 中的虚拟内存和虚拟地址

如何获得一个新的虚拟内存地址到已经分配的页面?

进程用来执行的高级虚拟内存地址(内核映射)是什么?

检查列是否在所有行上都具有相同的值

虚拟内存和交换空间是否相同?

每次在C#中运行程序时如何使用相同的虚拟内存块