问题描述
我的问题是特定于x86-64的OS X,但更受人们欢迎的是可在其他POSIX OS上使用的通用解决方案. 给出一些共享库(在下文中称为原始库)的符号名称列表,我希望我的共享库重新导出这些符号.重新导出,就像有人尝试根据我的库解析该符号一样,我可以提供该符号的版本,或者(如果我的库中没有此符号)则转发到原始库的符号. 我不知道符号的类型,我只知道它们是函数(在 对于函数,我已经有一个解决方案:对于要重新导出的每个函数,我都会生成一个程序集存根,该存根可以动态解析符号(使用 对于非功能符号,问题似乎更加棘手,因为我无法生成此通用代理功能,因为解决方永远不会调用函数. 使用构造函数 换句话说,我想编写我的库的符号表,以指向另一个共享库的各个符号.可以在编译时或运行时进行重写(最好是运行时).或换一种说法, 我知道 因为我有些含糊地解释了它:我无法更改实际程序的链接方式.目标是产生一个共享库,以替代原始库.(显然称为过滤器库.) 立即发现(特定于OS X): 如果 查看实际的重新导出是否有效: 输出应类似于 启动 My question is fairly OS X on x86-64 specific but a universal solution that works on other POSIX OSes is even more appreciated. Given a list of symbol names of some shared library (called original library in the following) and I want my shared library to re-export these symbols. Re-export as in if someone tries to resolve the symbol against my library I either provide my version of this symbol or (if my library doesn't have this symbol) forward to the original library's symbol. I don't know the types of the symbols, I only know whether they are functions (type For functions, I already have a solution: For every function I want to re-export I generate an assembly stub that does dynamically resolve the symbol (using For non-function symbols the problem seems to be harder because I cannot generate this universal proxy function, because the resolving party does never call a function. Using a constructor function In other words, I'd like to write the symbol table of my library to point to the respective symbols of another shared library. Doing the rewriting at compile or run time is okay (run time preferred). Or put yet another way, the behaviour of I'm aware of the EDIT: Because I explained it somewhat ambiguously: I can't change the way the actual program is linked. The goal is to produce a shared library that is a replacement for the original library. (Apparently called filter library.) Found it out now (OS X specific): If To see if the actual reexporting worked use: The output should look like After launching the 这篇关于从其他库(OS X/POSIX)重新导出共享库符号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! nm
输出中键入 T
)还是其他符号(键入S
在 nm
输出中). dlsym()
),然后跳转到具有相同环境的已解析函数(注册 rdi
, rsi
, rdx
, rcx
, r8
, r9
,堆栈指针等).我基本上是在生成通用代理功能.使用一些可以很容易生成的宏技巧,而无需为每个符号编写代码. static void init(void)__attribute __((constructor));
每当有人加载我的库时,我都可以执行代码,这将是解决并重新导出所有库的好方法非功能性符号(如果可能). DYLD_INSERT_LIBRARIES
( LD_PRELOAD
)的行为正是我所需要的,但我不想插入新的库,我想替换一个库(在文件系统中).编辑:我不想/不能使用 DYLD_INSERT_LIBRARIES
或 DYLD _ *
系列的任何其他环境变量的原因是对于已签名,受限,...二进制的代码,将忽略. -reexport-l
, -reexport_library
和 -reexported_symbols_list
链接器标志,但是我无法使它们工作,尤其是当我的库是伞式框架(例如:/System/Library/Frameworks/Coreworkss.framework/Frameworks/SearchKit.framework/SearchKit
)的一部分的框架的替换"时,因为> ld 禁止直接与伞形框架的某些部分链接. 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 empty.dylib
),第二步则是
install_name_tool -change/usr/local/lib/empty.dylib PATH_TO_ORIGINAL_LIB替换lib.dylib
otool -l replacement-lib.dylib |grep -A2 LC_REEXPORT_DYLIB
cmd LC_REEXPORT_DYLIBcmdsize XX名称empty.dylib(偏移YY)
install_name_tool
后可能是
cmd LC_REEXPORT_DYLIBcmdsize XX名称/System/Library/Frameworks/CoreServices.framework/Frameworks/SearchKit.framework/Versions/Current/SearchKit(偏移YY)
T
in nm
output) or other symbols (type S
in nm
output).dlsym()
) and then jumps into the resolved function with the very same environment (registers rdi
, rsi
, rdx
, rcx
, r8
, r9
, stack pointer, ...). I'm basically generating universal proxy functions. Using some macro trickery that can be generated fairly easy without writing code for each and every symbol.static void init(void) __attribute__((constructor));
I can execute code whenever someone loads my library, that would be a good point to resolve and re-export all non-function symbols if that's possible.DYLD_INSERT_LIBRARIES
(LD_PRELOAD
) is exactly what I need but I don't want to insert a new library, I want to replace one (in the file system). EDIT: The reason I don't want/can't use DYLD_INSERT_LIBRARIES
or any other environment variable of the DYLD_*
family is that they are ignored for code signed, restricted, ... binaries. -reexport-l
, -reexport_library
and -reexported_symbols_list
linker flags but I could not get them to work, especially when my library is a "replacement" for frameworks that are part of umbrella frameworks (example: /System/Library/Frameworks/CoreServices.framework/Frameworks/SearchKit.framework/SearchKit
) because ld
forbids to link directly against parts of umbrella frameworks.clang -o replacement-lib.dylib ... -Xlinker -reexport_library PATH_TO_ORIGINAL_LIB
does the trick. PATH_TO_ORIGINAL_LIB
could for example be /System/Library/Frameworks/CoreServices.framework/Frameworks/SearchKit.framework/Versions/Current/SearchKit
.PATH_TO_ORIGINAL_LIB
is a library that is part of an umbrella framework (as in the example above), then replace PATH_TO_ORIGINAL_LIB
by the path of some other lib (I created a lib empty.dylib
for that) and as a second step doinstall_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
it could be cmd LC_REEXPORT_DYLIB
cmdsize XX
name /System/Library/Frameworks/CoreServices.framework/Frameworks/SearchKit.framework/Versions/Current/SearchKit (offset YY)