我有一个应用程序正在通过dlopen
加载一些插件,特别是dlopen(name, RTLD_LAZY|RTLD_DEEPBIND)
。有一些插件(以二进制形式提供)加载正常,但我尝试构建的插件无法加载错误:
/opt/app/plugins/plugin.so: undefined symbol: Log_Modules
所有插件都引用该符号,并在此过程中加载提供它的库。然而,objdump -D
印刷的条目不同。在加载它的插件中说
00000000 DO *UND* 00000000 Log_Modules
它在定义它的图书馆中说
000130dc g DO .data 00000004 Base Log_Modules
而在我建立的模块中说
00000000 D *UND* 00000000 Log_Modules
objdump
的手册页只是说旗帜意味着
符号是函数(F)或文件(f)或对象(O)的名称,或者只是普通符号(空格)的名称。
但我没有看到任何关于对象和普通符号之间差异的提示。所以
有什么不同
符号表.st_info
包含STT_OBJECT
而不是STT_FUNC
。
是什么使符号在C或C ++语言或链接器级别中的一个或另一个
在C
级别,编译器在发出汇编代码时会用@function
标记函数标签,汇编器在发出符号表时会添加STT_FUNC
标志。
它确实应该使符号不能解决?
不,你的问题很可能与此无关。
一般来说,objdump
是查看ELF文件的错误工具(它映射到BFD数据模型,过去20多年来已经过时)。请改用readelf
。
狂野猜测:你的plugin.so
定义,但不导出符号。使用
nm -D plugin.so | grep ' Log_Modules$'
nm plugin.so | grep ' Log_Modules$'
如果Log_Modules
出现在第二个命令输出中,但不是第一个,那么我的猜测是正确的。
有什么不同
O
标志对应于STT_OBJECT
标志,表示一个对象,即一个变量。
是什么使符号在C或C ++语言或链接器级别中的一个或另一个
显然,链接器仅在实际看到定义的情况下用STT_OBJECT
标记标记符号,即当定义它的库作为依赖项提供时。仅外部声明没有标记。
它确实应该使符号不能解决?
解析符号时,链接器会查找显式列出的依赖项,以及使用RTLD_GLOBAL
加载的库,其中包含主可执行文件的依赖项。因此,当主可执行文件已经发生链接定义库时,插件将不会显式链接它,但如果它本身加载了dlopen
(没有RTLD_GLOBAL
),它就不会。
缺少标志本身不是问题,但它暗示了缺少库引用的实际问题。