我正在使用某些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函数不会导致未定义的符号错误。这让我完全感到困惑,因为它看起来好像是出口的符号 正确地在二进制可执行文件的初始版本中。有人能在这里看到问题吗?任何帮助都会受到极大的赞赏。
提前致谢。
答案 0 :(得分:3)
我设法解决了这个问题。我发现如果我删除以下行中的引号;
"ToolboxManager::registerToolbox*"
在文件${top_srcdir}/dynamic_symbol_table.txt
中,然后重新链接二进制可执行文件,然后它可以工作。也就是说,dlopen函数不会再失败了。
我不禁想知道在GNU binutils邮件列表上提问这个问题是否比在这个网站上提问更合适。