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

问题描述 投票:1回答:1

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

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

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

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

#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
macos dynamic-linking virtual-address-space
1个回答
2
投票

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

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

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

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

试着看看vmmap -v <pid>的输出。查找“机器范围的VM子图”及其后续行。

© www.soinside.com 2019 - 2024. All rights reserved.