Gcc 是什么使ELF库中的符号成为对象或普通符号?

Gcc 是什么使ELF库中的符号成为对象或普通符号?,gcc,shared-libraries,ld,elf,Gcc,Shared Libraries,Ld,Elf,我有一个应用程序正在通过dlopen加载一些插件,特别是dlopen(name,RTLD_LAZY | RTLD_DEEPBIND)。有一些插件(以二进制形式提供)可以正常加载,但我尝试构建的插件加载失败,出现错误: /opt/app/plugins/plugin.so: undefined symbol: Log_Modules 所有插件都引用该符号,提供该符号的库将在该过程中加载。但是,objdump-D打印的条目不同。在加载它的插件中说 00000000 DO *UND*

我有一个应用程序正在通过
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
的手册页上说,该标志的意思是

符号是函数(F)、文件(F)、对象(O)或普通符号(空格)的名称

但是我没有看到任何关于物体和普通符号之间区别的提示。所以

  • 有什么区别,
  • 是什么使符号在C或C++语言或链接器级别和中成为一个或另一个符号?
  • 它真的应该使符号无法解析吗
有什么区别

符号表
.st_info
包含
STT_对象
,而不是
STT_FUNC

符号在C或C++语言或链接器级别

中的符号 在
C
级别,编译器将在发出汇编代码时用
@function
标记函数标签,而汇编器将在发出符号表时添加
STT_FUNC
标志

它真的应该使符号无法解析吗

不,你的问题很可能与此无关

一般来说,
objdump
是查看ELF文件的错误工具(它映射到BFD数据模型,该模型在过去20多年中已经过时)。改用
readelf

胡乱猜测:你的
插件。因此
定义了符号,但没有导出符号。使用

nm -D plugin.so | grep ' Log_Modules$'
nm    plugin.so | grep ' Log_Modules$'
如果
Log_Modules
显示在第二个命令输出中,而不是第一个命令输出中,那么我的猜测是正确的

有什么区别

O
标志对应于
STT\u对象
标志,表示一个对象,即一个变量

符号在C或C++语言或链接器级别

中的符号 显然,链接器仅在实际看到定义时,即定义它的库作为依赖项提供时,才使用
STT_对象
标记符号。外部声明本身没有标记

它真的应该使符号无法解析吗

解析符号时,链接器查找显式列出的依赖项,以及加载了
RTLD_GLOBAL
的库,其中包括主可执行文件的依赖项。因此,当主可执行文件已经链接到定义库时,插件将不会显式链接它,但如果它本身加载了
dlopen
(没有
RTLD\u GLOBAL
),则不会


没有标记本身不是问题,但它暗示了缺少库引用的实际问题。

请注意,我问题中的所有三行都有
D
标记,这意味着它们在第一个命令的输出中。对于定义符号的库,第二个命令的输出是空的,因为已经提供了它。函数工作正常。但我需要知道的是何时设置STT_对象标志。这不是你问题的答案,但不管怎样。@EmployedRussian,是的,是的。我没有指出为什么最后一段才是答案,所以我添加了它。