无论如何,我可以在一个进程中将共享库加载到共享内存中,以便其他一些进程可以简单地映射该共享内存(到同一地址)并简单地调用函数?我知道共享库中的外部需要额外跳转到特定于进程的内存位置以调用适当的函数(如elf plt)。但是,今天的工具是否可行。
答案 0 :(得分:0)
但是,今天的工具是否可行。
不是今天的工具,也不是。
当然,如果您的共享库具有完全独立的功能,那么它将起作用。但是,当您的库引用外部数据或函数时,您将崩溃并刻录。
我知道共享库中的外部需要额外跳转到特定于进程的内存位置以调用适当的函数
我认为你不明白。让我们考虑一个例子:
void *foo() { return malloc(1); }
当它被内置到Linux上的共享库中时,结果是:
0x00000000000006d0 <+0>: mov $0x1,%edi
0x00000000000006d5 <+5>: jmpq 0x5c0 <malloc@plt>
和
Dump of assembler code for function malloc@plt:
0x00000000000005c0 <+0>: jmpq *0x200a5a(%rip) # 0x201020 <malloc@got.plt>
0x00000000000005c6 <+6>: pushq $0x1
0x00000000000005cb <+11>: jmpq 0x5a0
所以问题是:jmpq *0x200a5a(%rip)
将在第二个过程中去哪里。答案:两个地方之一。
如果第一个进程已经调用了malloc
(非常可能),那么jmpq
将转到第一个进程中malloc
的地址,这极不可能是地址在第二个过程中malloc
,更可能是未映射的,或者在某些数据的中间。无论哪种方式,你都会崩溃。
如果第一个进程尚未调用malloc
,则第二个进程中的jmpq
将跳转到Linux上的运行时加载程序地址ld-linux.so.2
或类似地址{{1在Solaris上)解析器功能。同样,该地址也不太可能是第二个过程中解析器的地址,如果不是,则崩溃。
但是从这里变得更糟。如果通过一些不可思议的魔法你最终在第二个进程中调用了ld.so
,那么malloc
本身很可能会崩溃,因为它会尝试使用它先前设置的数据结构,使用获得的内存来自malloc
或sbrk
。这些数据结构存在于第一个进程中,但不存在于第二个进程中,因此您再次崩溃。