从其他库重新导出共享库符号(OS X / POSIX)

时间:2013-11-16 16:19:24

标签: c macos linker shared-libraries x86-64

我的问题是x86-64特定的OS X,但是对其他POSIX操作系统起作用的通用解决方案更受欢迎。

给出一些共享库的符号名称列表(以下称为原始库),我希望我的共享库重新导出这些符号。重新导出,如果有人试图解决我的图书馆的符号我要么提供我的这个符号的版本,或者(如果我的图书馆没有这个符号)转发到原始图书馆的符号。

我不知道符号的类型,我只知道它们是函数(T输出中的nm类型)还是其他符号(S中的类型{ {1}}输出)。

对于函数,我已经有了一个解决方案:对于我想要重新导出的每个函数,我生成一个动态解析符号的汇编存根(使用nm),然后跳转到已解析的函数相同的环境(注册dlsym()rdirsirdxrcxr8,堆栈指针,...)。我基本上生成通用代理功能。使用一些非常容易生成的宏技巧,无需为每个符号编写代码。

对于非功能符号,问题似乎更难,因为我无法生成此通用代理功能,因为解析方从不调用函数。

使用构造函数r9我可以在有人加载我的库时执行代码,如果可能的话,这将是解决和重新导出所有非函数符号的好点。

换句话说,我想编写我的库的符号表以指向另一个共享库的相应符号。在编译或运行时进行重写是可以的(首选运行时)。或者换句话说,static void init(void) __attribute__((constructor));DYLD_INSERT_LIBRARIES)的行为正是我所需要的,但我不想插入新库,我想替换一个(在文件系统中) )。 编辑:我不希望/无法使用LD_PRELOADDYLD_INSERT_LIBRARIES系列的任何其他环境变量的原因是它们会被忽略代码签名,限制,...二进制文件。

我知道DYLD_*-reexport-l-reexport_library链接器标记,但我无法让它们工作,尤其是当我的图书馆是"替代品时#34;对于作为伞形框架一部分的框架(例如:-reexported_symbols_list),因为/System/Library/Frameworks/CoreServices.framework/Frameworks/SearchKit.framework/SearchKit禁止直接链接到伞形框架的各个部分。

编辑:因为我有点含糊地解释了:我无法改变实际程序的链接方式。目标是生成一个共享库,它是原始库的替代品。 (显然称为过滤器库。)

2 个答案:

答案 0 :(得分:4)

现在发现它(特定于OS X):clang -o replacement-lib.dylib ... -Xlinker -reexport_library PATH_TO_ORIGINAL_LIB可以解决问题。 PATH_TO_ORIGINAL_LIB可以是/System/Library/Frameworks/CoreServices.framework/Frameworks/SearchKit.framework/Versions/Current/SearchKit

如果PATH_TO_ORIGINAL_LIB是一个伞形框架的库(如上例所示),则将PATH_TO_ORIGINAL_LIB替换为其他lib的路径(我创建了一个lib {{1}对于那个)并作为第二步做

empty.dylib

查看实际再出口是否有效:

install_name_tool -change /usr/local/lib/empty.dylib PATH_TO_ORIGINAL_LIB replacement-lib.dylib

输出应该看起来像

otool -l replacement-lib.dylib | grep -A2 LC_REEXPORT_DYLIB

启动 cmd LC_REEXPORT_DYLIB cmdsize XX name empty.dylib (offset YY) 之后,它可能是

install_name_tool

答案 1 :(得分:1)

您可以链接两个库并使用链接顺序确保链接到正确的符号。这适用于OS X和Linux:

cc -o executable -lmylib -loriglib

origlib是原始库,mylib包含应该覆盖origlib中符号的符号。然后,可执行文件将首先与mylib的符号相关联,所有未解析的符号将与origlib相关联。

在与OS X框架链接时,它的工作方式相同。只需链接您的库,首先替换符号,然后替换为框架。

cc -o executable -lmylib -framework SomeFramework

编辑:如果您只想在运行时替换符号,则可以使用LD_PRELOAD同样的方式:

cc -o executable -framework SomeFramework
LD_PRELOAD=libmylib.dylib ./executable
相关问题