首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >让GNU链接器(%ld)导出符号时出现问题

让GNU链接器(%ld)导出符号时出现问题
EN

Stack Overflow用户
提问于 2011-09-13 09:25:45
回答 1查看 3.5K关注 0票数 7

我正在使用某些GNU工具,即GNU C++编译器(g++)和GNU Linker (ld)来创建共享库(.so)文件和二进制可执行文件。

二进制可执行文件利用dlopen函数在运行时动态加载共享库文件。除此之外,共享库文件还需要调用二进制可执行文件中定义的特定类方法(称为ToolboxManager::registerToolbox)。这是通过强制二进制可执行文件导出类方法来实现的,而这又是在链接时通过将二进制可执行文件与以下命令行选项链接来完成的;

代码语言:javascript
复制
-Wl,--dynamic-list=${top_srcdir}/dynamic_symbol_table.txt

其中,文件${top_srcdir}/dynamic_symbol_table.txt包含以下内容;

代码语言:javascript
复制
{
  extern "C++"
  {
    "ToolboxManager::registerToolbox*";
  };
};

请注意,在文件中使用星号(*)强制链接器导出所有以ToolboxManager::registerToolbox开头的符号。

当我在生成的二进制可执行文件上运行GNU nm实用程序(nm -C -g ./a.out)时,它显示了关于上述类方法的以下信息;

代码语言:javascript
复制
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命令行开关;

代码语言:javascript
复制
08053da0 T _ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE

到目前为止,这看起来还不错。类方法ToolboxManager::registerToolbox定义前面的"T“表示该方法驻留在文件的文本/代码部分。

类似地,如果我在共享库文件上运行nm实用程序(nm -C -g ./toolbox.so),它将显示关于前面提到的同一类方法的以下信息;

代码语言:javascript
复制
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“表示该方法在共享库文件中未定义。

但是,当我从命令行运行二进制可执行文件时,出现了一个问题,该问题导致显示以下错误消息;

代码语言:javascript
复制
./toolbox.so: undefined symbol: _ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE

出现在此运行时消息中的损坏的类方法名显示如下,作为两行中的第一行。为了便于比较,上面损坏的类方法名(并且是使用nm -g命令生成的)显示在下面两行中的第二行;

代码语言:javascript
复制
_ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE

_ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE

可以看出,这两个损坏的名字是相同的。因此,我不明白为什么未定义的符号不能在运行时解析。

然后我重新链接了二进制可执行文件,但是这次我替换了下面的链接器命令;

代码语言:javascript
复制
-Wl,--dynamic-list=${top_srcdir}/dynamic_symbol_table.txt

就是这一个;

代码语言:javascript
复制
-Wl,--export-dynamic

GNU链接器选项指示--export-dynamic链接器向动态符号表添加所有符号。

然后再次运行二进制可执行文件。这一次,它正确地执行了,并且对dlopen函数的调用没有导致未定义的符号错误。这让我非常困惑,因为它看起来像是在二进制可执行文件的初始版本中正确地导出了符号。有没有人能看到这里的问题?任何帮助都将不胜感激。

提前谢谢。

EN

回答 1

Stack Overflow用户

发布于 2011-09-14 07:09:42

我已经设法解决了这个问题。我发现如果我去掉下面一行中的引号;

代码语言:javascript
复制
"ToolboxManager::registerToolbox*"

在文件${top_srcdir}/dynamic_symbol_table.txt中,然后重新链接二进制可执行文件,然后它就可以工作了。也就是说,dlopen函数将不再失败。

我不禁想知道,在GNU binutils邮件列表上问这个问题是否比在这个网站上问这个问题更合适。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7395838

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档