我有一个应用程序(A)调用第三方共享库(C)。我想编写一个我自己的库(B)拦截从A到C的调用,在某些情况下用我自己的代码替换调用,在某些情况下做一些额外的处理,然后在C中调用匹配函数,然后在有些情况下直接将呼叫转发给C.
应用程序是开源的,所以我可以只更改每个调用站点以在B中调用类似命名的函数,然后在需要时调用C中的相应函数,但这将是一个很多工作并且会使应用程序中的上游变更难以合并。我没有第三方库的来源。如果它只是标题,那么我可以使用命名空间来实现这一点,但是当我的库和第三方库看起来需要完全相同的符号定义时,我不知道如何去做。
有没有办法让这项工作?我主要针对的是OS X,但希望它可以在Linux上运行,最后也可以在Windows上运行。
答案 0 :(得分:4)
您可以使用LD_PRELOAD指向您自己的共享库。使用LD_PRELOAD将调用共享库中的所有函数,而不是其他库中具有相同名称的函数。
如果您希望注入代码然后调用原始函数,则需要调用dlsym以从第三方库获取原始函数。
答案 1 :(得分:2)
一种解决方案如下。
在头文件中,#define
所有要拦截到包装函数的函数。
#define foo wrap_foo
#define bar wrap_bar
将其添加到包含在任何位置的某个头文件中,以便所有代码都包含此标头。此标头应包含在之前您要拦截的库的标头。 gcc
还有一个-include
选项,可以将头文件包含在所有来源中。
这里的目标是通过调用包装函数来替换对实际函数的所有调用。
现在在某处定义您的包装函数,并根据需要拦截调用。此文件应不包含您之前创建的包装器标头。
int wrap_foo() {
return foo();
}
int wrap_bar() {
return bar();
}
将它们连接在一起。
请注意,这样您就可以拦截对包含封面头的编译代码中foo()
和bar()
等的调用。任何预编译的代码(在库或对象中)都将直接链接到foo()
和bar()
等。