【发布时间】:2011-11-15 18:53:02
【问题描述】:
我正在使用某些 GNU 工具,即 GNU C++ 编译器 (g++) 和 GNU 链接器 (ld) 来创建共享库 (.so) 文件以及二进制可执行文件。
二进制可执行文件利用dlopen 函数在运行时动态加载共享库文件。除此之外,共享库文件
需要调用在二进制可执行文件中定义的特定类方法(称为ToolboxManager::registerToolbox)。这是通过强制二进制文件来解决的
可执行文件导出类方法,这又是在链接时通过将二进制可执行文件与以下命令行选项链接来完成的;
-Wl,--dynamic-list=${top_srcdir}/dynamic_symbol_table.txt
其中文件${top_srcdir}/dynamic_symbol_table.txt包含以下内容;
{
extern "C++"
{
"ToolboxManager::registerToolbox*";
};
};
注意在文件中使用星号 (*) 来强制链接器导出所有以 ToolboxManager::registerToolbox 开头的符号。
当我在生成的二进制可执行文件上运行 GNU nm 实用程序 (nm -C -g ./a.out) 时,它会显示有关上述类方法的以下信息;
08053da0 T ToolboxManager::registerToolbox
(
std::string&,
std::string&,
std::map
<
std::string,
Factory_DSPB_Base*,
std::less
<
std::string
>,
std::allocator
<
std::pair
<
std::string const,
Factory_DSPB_Base*
>
>
>&
)
或者,如果 nm 实用程序如上所述调用,但这次没有使用 -C 命令行开关;
08053da0 T _ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE
到目前为止,这看起来不错。类方法ToolboxManager::registerToolbox定义前面的“T”表示该方法位于文件的Text/Code部分。
同样,如果我在共享库文件上运行 nm 实用程序 (nm -C -g ./toolbox.so),它会显示有关上述同一个类的以下信息
方法;
U ToolboxManager::registerToolbox
(
std::string&,
std::string&,
std::map
<
std::string,
Factory_DSPB_Base*,
std::less
<
std::string
>,
std::allocator
<
std::pair
<
std::string const,
Factory_DSPB_Base*
>
>
>&
)
这看起来也不错。类方法ToolboxManager::registerToolbox定义前面的“U”,表示该方法在共享库文件中未定义。
但是,当我从命令行运行二进制可执行文件时会出现问题,并且此问题会导致显示以下错误消息;
./toolbox.so: undefined symbol: _ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE
出现在此运行时消息中的损坏的类方法名称如下所示,作为两行中的第一行。出于比较目的,上面的重整类方法名称(使用nm -g 命令生成)如下所示,作为两行中的第二行;
_ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE
_ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE
可以看出,这两个重命名的名称是相同的。因此,我无法理解为什么在运行时无法解析未定义的符号。
然后我重新链接了二进制可执行文件,但是这次我替换了以下链接器命令;
-Wl,--dynamic-list=${top_srcdir}/dynamic_symbol_table.txt
用这个;
-Wl,--export-dynamic
--export-dynamic 链接器选项指示 GNU 链接器将所有符号添加到动态符号表中。
如果然后再次运行二进制可执行文件。这次它执行了 正确,并且对 dlopen 函数的调用不会导致未定义的符号错误。这让我完全困惑,因为它看起来好像正在导出符号 在二进制可执行文件的初始版本中正确。有人能在这里看到问题吗?任何帮助将不胜感激。
提前致谢。
【问题讨论】: