У меня очень странная ситуация с привязкой динамических символов в OS X, и я надеюсь получить некоторые подсказки о том, как ее решить.
У меня есть приложение, написанное на C, которое использует dlopen()
для динамической загрузки модулей во время выполнения. Некоторые из этих модулей экспортируют глобальные символы, которые могут использоваться другими модулями, загруженными позже.
У нас есть один модуль (который я назову weird_module.so
), который экспортирует глобальные символы, один из которых weird_module_function
. Если weird_module.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!
Edit:
Я попытался собрать минимальное приложение, чтобы дублировать проблему, и в ходе этого, по крайней мере, выяснил, что мы делали неправильно. Есть два других важных факта, связанных с дублированием проблемы.
Во-первых, 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
для a const
global.
$ nm weird_module.so | grep '_something_global`
00000000000158f0 S _something_global
$ nm libsomething.dylib | grep '_something_global'
0000000000031130 S _something_global
Я согласен с тем, что дубликат символа помещает меня в область поведения undefined, поэтому я оставляю вопрос.