我在 OS X 上遇到了一个非常奇怪的动态符号绑定情况,我希望能得到一些关于如何解决的线索。
我有一个用 C 编写的应用程序,用于dlopen()
在运行时动态加载模块。其中一些模块导出全局符号,稍后加载的其他模块可能会使用这些符号。
我们有一个模块(我称之为weird_module.so
),它导出全局符号,其中之一是weird_module_function
. 如果奇怪的模块.so 与特定的库(我将调用它libsomething.dylib
)链接,则weird_module_function
无法绑定。但是如果我删除-lsomething
when 链接weird_module.so
,那么我可以绑定到weird_module_function
.
什么可能libsomething.dylib
会导致weird_module.so
不导出符号?我可以做些什么来调试符号的导出方式(类似于我可以DYLD_PRINT_BINDINGS
用来调试它们的绑定方式)?
$ LDFLAGS="-bundle -mmacosx-version-min=10.6 -Xlinker -undefined -Xlinker dynamic_lookup /usr/lib/bundle1.o"
$ gcc -o weird_module.so ${LDFLAGS} weird_module.o -lsomething
$ nm weird_module.so | grep '_weird_module_function$'
00000000000026d0 T _weird_module_function
$ gcc -o other_module.so ${LDFLAGS} other_module.o -lsomething
$ nm other_module.so | grep '_weird_module_function$'
U _weird_module_function
$ run-app
Loading weird_module.so
Loading other_module.so
dyld: lazy symbol binding failed: Symbol not found: _weird_module_function
Referenced from: other_module.so
Expected in: flat namespace
dyld: Symbol not found: _weird_module_function
Referenced from: other_module.so
Expected in: flat namespace
# Now relink without -lsomething
$ gcc -o weird_module.so ${LDFLAGS} weird_module.o
$ nm weird_module.so | grep '_weird_module_function$'
00000000000026d0 T _weird_module_function
$ run-app
Loading weird_module.so
Loading other_module.so
# No error!
编辑:
我尝试构建一个最小的应用程序来复制问题,并且在这样做的过程中至少发现了我们做错的一件事。还有两个与重复问题相关的相关事实。
首先是run-app
预加载模块RTLD_LAZY | RTLD_LOCAL
以检查其元数据。然后根据元数据使用或dlclose()
编辑并重新打开该模块。(对于有问题的两个模块,它会以 重新打开)。RTLD_LAZY | RTLD_GLOBAL
RTLD_NOW | RTLD_LOCAL
RTLD_LAZY | RTLD_GLOBAL
其次,事实证明在全局中存在符号冲突weird_module.so
。libsomething.dylib
const
$ nm weird_module.so | grep '_something_global`
00000000000158f0 S _something_global
$ nm libsomething.dylib | grep '_something_global'
0000000000031130 S _something_global
我愿意考虑重复符号会将我置于未定义行为的领域,所以我放弃了这个问题。