У меня действительно странная ситуация с динамической привязкой символов в OS X, и я надеюсь получить некоторые подсказки о том, как ее решить.
У меня есть приложение, написанное на C, которое использует dlopen()
для динамической загрузки модулей во время выполнения. Некоторые из этих модулей экспортируют глобальные символы, которые могут использоваться другими модулями, загруженными позже.
У нас есть один модуль (назовем его weird_module.so
), который экспортирует глобальные символы, одним из которых является weird_module_function
. Если странный_модуль.so связывается с определенной библиотекой (которую я назову libsomething.dylib
), то weird_module_function
не может быть привязан к ней. Но если я удалю -lsomething
при связывании 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()
ed и снова открывается с 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
Я готов считать, что повторяющийся символ поставит меня в область неопределенного поведения, поэтому я опускаю вопрос.