在Windows上,创建 "代理DLL "是很常见的,它可以代替原来的DLL,并转发对它的调用(在进行任何必要的附加操作后)。你可以阅读一下 此处 和 此处 比如说。
然而,Linux下的shlib munging文化却完全不同。首先,LD_PRELOAD是Linux下ld.so的内置功能,它只是简单地将单独的shlib注入到进程中,并使用它定义的任何符号作为覆盖。而这种 "注入 "技术似乎定义了整个思路的方向--这里是 典型的ELF黑客工具 或 这个问题这位先生似乎和我有相同的使用情况,但他一开始就问如何能给现有的二进制文件打补丁。
不,谢谢。我不想注入或修改一些不属于我的东西,我只想做一个独立的代理shlib。我想做的只是做一个独立的代理shlib,它可以调用原始的。理想的情况是,有一个工具可以与原版的.so一起使用,并创建一个C源码,它可以重定向到原版的函数,同时让我轻松地覆盖任何我想要的东西。那么,这样的工具在哪里呢? ;-) 谢谢。
使用 "代理DLL "的方法 LD_PRELOAD
并不真正涉及到修改一些不属于你的东西,而且注入的东西和普通的动态库加载并没有什么不同。ERESI项目中的 "典型的ELF黑客工具 "与以下内容无关 LD_PRELOAD
. 你不应该害怕它。一个好的写作入门 LD_PRELOAD
-可 "代理 "是 此处.
这就是说,如果你想为某个库创建一个全系统的代理,你可能会认为,全局设置 LD_PRELOAD
(从而将您的代理加载到系统上运行的每个二进制文件中)是不可取的。它通常用于覆盖glibc中的函数,如 libeatmydata 或 袜业但如果你要覆盖一个比glibc更大或更不广泛的库中的函数,那么尝试找到另一种方法是有意义的,真正为那个库创建一个代理。
其中一种方法是使用 patchelf --replace-needed
或 --add-needed
来硬编码原始库的完整路径名,然后通过设置 LD_LIBRARY_PATH
¹. 所以,完整的程序是
LD_PRELOAD
-可覆盖原有库的一些功能的库(测试它是否只用了 LD_PRELOAD
在继续进行之前!)ldd libwrapper-foo.so
包括这样的内容。libfoo.so.0 => /usr/lib/x86_64-linux-gnu/libfoo.so.0 (0x0000deadbeef0000)
patchelf
: patchelf --replace-needed libfoo.so.0 /usr/lib/x86_64-linux-gnu/libfoo.so.0 libwrapper-foo.so
libwrapper-foo.so
到 libfoo.so.0
LD_LIBRARY_PATH=. ldd $(which program-that-uses-libfoo)
应包括这些行。libfoo.so.0 => ./libfoo.so.0 (0x0000dead56780000)
/usr/lib/x86_64-linux-gnu/libfoo.so.0 (0x0000dead1234000000)
LD_LIBRARY_PATH
的完整路径。.bashrc
或其他地方这种代理库的一个实际例子是 我的libpango包装器 可以实现所有应用的子像素定位。
¹)也可以将这个代理库放入到 /usr/local/lib
但 ldconfig
(更新共享库缓存的工具)拒绝使用硬编码绝对路径的库。
拒绝使用带有硬编码绝对路径的库。 是一个工具,它涵盖了一些平台的图形类库(OpenGL、DirectX)调用的详细跟踪。它可能过于详细和复杂,不适合通用解决方案,但至少提供了一些参考和亲和力。