我在OS X上遇到了一个关于动态符号绑定的非常奇怪的情况,希望能得到一些解决方法的线索。
我的应用程序是用C编写的,它使用dlopen()在运行时动态加载模块。其中一些模块导出全局符号,后续加载的其他模块可以使用这些符号。
我们有一个模块(我将其称为weird_module.so),它导出全局符号,其中一个是weird_module_function。如果weird_module.so与特定库链接(我将其称为libsomething.dylib),那么就无法绑定weird_module_function。但是如果我在链接weird_module.so时删除-lsomething,则可以绑定weird_module_function。 libsomething.dylib可能会导致weird_module.so不导出符号,这是怎么回事?是否有办法调试符号的导出方式(类似于我可以使用DYLD_PRINT_BINDINGS来调试符号的绑定方式)?
我的应用程序是用C编写的,它使用dlopen()在运行时动态加载模块。其中一些模块导出全局符号,后续加载的其他模块可以使用这些符号。
我们有一个模块(我将其称为weird_module.so),它导出全局符号,其中一个是weird_module_function。如果weird_module.so与特定库链接(我将其称为libsomething.dylib),那么就无法绑定weird_module_function。但是如果我在链接weird_module.so时删除-lsomething,则可以绑定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
存在一个常量全局符号冲突。
$ nm weird_module.so | grep '_something_global`
00000000000158f0 S _something_global
$ nm libsomething.dylib | grep '_something_global'
0000000000031130 S _something_global
我愿意考虑重复符号会将我置于未定义行为领域,所以我放弃了这个问题。