动态库是否在所有程序中都具有相同的虚拟内存地址?
Do dynamic libraries have the same virtual memory address in all programs?
当库动态链接到程序时,它在该程序中的地址是否与在任何其他程序中的地址相同?
我脑子里想象着每个进程都获得了整个地址 space 然后该进程中的所有内容(包括已经在内存中的动态库)都被映射到半 运行由于 ASLR,它的 dom 部分。
但是我做了一个简短的实验,似乎暗示内存中的库地址在不同进程中是固定的,因此可以跨程序重用?对吗?
我写了两个简短的 c 程序,它们使用了 "sleep" 函数。在一个中,我打印出睡眠函数的地址,在第二个中,我为该地址分配了一个函数指针。我 运行 他们都和睡眠功能都工作。
#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 上,许多系统库都是 dyld 共享缓存的一部分。有一个机器范围的映射。因此,这些库在同一体系结构(32 位或 64 位)的所有进程中最终位于同一地址。
dyld 共享缓存的位置在系统启动时随机化。因此,在您重新启动之前,不同进程的库地址将是相同的。
并非所有系统库都是缓存的一部分,只有 Apple 认为经常加载的那些。
您自己的库或来自第三方的库每次加载时都会在随机位置加载,假设它们与位置无关。
尝试查看 vmmap -v <pid>
的输出。查找带有 "machine-wide VM submap" 和后面的行。
当库动态链接到程序时,它在该程序中的地址是否与在任何其他程序中的地址相同?
我脑子里想象着每个进程都获得了整个地址 space 然后该进程中的所有内容(包括已经在内存中的动态库)都被映射到半 运行由于 ASLR,它的 dom 部分。
但是我做了一个简短的实验,似乎暗示内存中的库地址在不同进程中是固定的,因此可以跨程序重用?对吗?
我写了两个简短的 c 程序,它们使用了 "sleep" 函数。在一个中,我打印出睡眠函数的地址,在第二个中,我为该地址分配了一个函数指针。我 运行 他们都和睡眠功能都工作。
#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 上,许多系统库都是 dyld 共享缓存的一部分。有一个机器范围的映射。因此,这些库在同一体系结构(32 位或 64 位)的所有进程中最终位于同一地址。
dyld 共享缓存的位置在系统启动时随机化。因此,在您重新启动之前,不同进程的库地址将是相同的。
并非所有系统库都是缓存的一部分,只有 Apple 认为经常加载的那些。
您自己的库或来自第三方的库每次加载时都会在随机位置加载,假设它们与位置无关。
尝试查看 vmmap -v <pid>
的输出。查找带有 "machine-wide VM submap" 和后面的行。