dlopen()
不提供任何方法(我所知道的)来告诉它或提示它将加载的内容放在哪里。是否有一种方法可以告诉
dlopen()
应该放置它加载的库的位置?是否有一些替代
dlopen()
的方式,可以提供这个功能?您需要明确实际要解决的问题。
由于各种重要原因,我只能理解这个声明是被请求给您的,而且您无法对此进行任何争议。
关于您的问题:
加载地址已经被指定,所以您不能通过这些库来更改它。实际上,您需要了解关于PIC的知识。
我认为你想做的唯一方法就是“黑客”这些库并修改文本段。
请查看specify-preferred-load-address。
老实说,您应该在这里解释您要解决的问题,这样您就可以得到帮助您以各种方式解决问题的答案。也就是说,您可以获得另一个选项作为解决方案。
你不能这样做,并且在最新的Linux系统上,dlopen
(甚至任何没有MAP_FIXED
的mmap
)都受到ASLR的影响。
因此,即使您成功地在某个固定地址执行等效的dlopen
,除非您在整个系统范围内禁用ASLR,否则您的方法将失败。
特别地,在 Linux 上,同一程序进行相同的dlopen
的两次“相同”运行将进入(即dlopen
的共享库将进入)可能不同的地址。
此外,在 Linux 上,您可以dlopen
大量(至少数十万个)的共享对象。请参见我的 manydl.c 作为一个示例。
正如我评论中所说,你的问题看起来像一个XY 问题。你应该解释一下你想要这样做的原因。真正的动机和总体目标是什么?
你可以通过处理 ELF 共享对象文件并自行进行重定位,重新实现已修改的 dlopen
。你还需要编译和链接你的共享对象。
如果函数简单且小(并且如果您接受与使用gcc -fPIC -O2 -shared -Wall
编译的小型共享库相比性能略有下降),您可以考虑使用一些JIT编译库,例如libjit、GNU lighting、asmjit、LLVM等,在某个固定地址生成机器代码(或者仅生成对真实共享库函数的调用或跳转)
顺便说一下,您可以使用并根据自己的需求适应musl-libc(它包括一个dlopen
函数,您可以将其移植到自己的需求中)
mmap
允许调用者指定所需的地址,并且这并没有引起任何灾难。Windows允许共享库指定自己的首选基址(不保证),而没有“巨大的安全影响”(ASLR的有效性在Windows中有所降低,因为Windows倾向于在每个进程中加载所有DLL时使用相同的地址,但这是为了操作系统可以节省内存,而不是因为DLL可以具有首选映像基址)。 - nobody