本文介绍了从其他库(OS X/POSIX)重新导出共享库符号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时删除!!

我的问题是特定于x86-64的OS X,但更受人们欢迎的是可在其他POSIX OS上使用的通用解决方案.

给出一些共享库(在下文中称为原始库)的符号名称列表,我希望我的共享库重新导出这些符号.重新导出,就像有人尝试根据我的库解析该符号一样,我可以提供该符号的版本,或者(如果我的库中没有此符号)则转发到原始库的符号.

我不知道符号的类型,我只知道它们是函数(在 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 禁止直接与伞形框架的某些部分链接.

因为我有些含糊地解释了它:我无法更改实际程序的链接方式.目标是产生一个共享库,以替代原始库.(显然称为过滤器库.)

解决方案

立即发现(特定于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 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) 

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 T in nm output) or other symbols (type S in nm output).

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 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.

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 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.

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 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.

I'm aware of the -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.

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): 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.

If 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 do

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

To see if the actual reexporting worked use:

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

The output should look like

  cmd LC_REEXPORT_DYLIB
  cmdsize XX
     name empty.dylib (offset YY)

After launching the 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)

这篇关于从其他库(OS X/POSIX)重新导出共享库符号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

1403页,肝出来的..

09-06 09:54