我们的项目(C++,Linux,gcc,PowerPC)由几个共享库组成。发布新版本的软件包时,只有那些库的源代码实际上受到了影响,才应该更改。 “更改”是指绝对二进制身份(比较文件的校验和。根据策略,不同的校验和->不同的版本)。 (我应该提到,无论每个库的代码是否更改,整个项目总是一次生成的)。

通常,这可以通过隐藏所包含的Header文件的私有(private)部分而不更改公共(public)文件来实现。

但是,在某些情况下,仅向库libTableManager.so的类TableManager(在TableManager.cpp文件中!)的析构函数中添加了delete,而向库libB.so(使用TableManager类的库)添加了二进制/校验和。 ) 已经改变。

TableManager.h:

class TableManager
{
public:
    TableManager();
    ~TableManager();
private:
    int* myPtr;
}

TableManager.cpp:
TableManager::~TableManager()
{
    doSomeCleanup();
    delete myPtr;     // this delete has been added
}

通过使用readelf --all libB.so检查libB.so并查看.dynsym部分,结果发现所有功能的长度(甚至是其他库中动态使用的功能)的长度都存储在libB中!看起来像这样(长度为第三列中的668):
527: 00000000 668 FUNC GLOBAL DEFAULT UND _ZN12TableManagerD1Ev
所以我的问题是:
  • 为什么函数的长度实际上存储在客户端库中?起始地址不够吗?
  • 在编译/链接libB.so(有点“剥离”)时,可以通过某种方式抑制它吗?我们真的想减少这种依赖程度...
  • 最佳答案

    答对了。实际上,这是他们在2008年发现并修复的binutils中的“错误”。大小信息实际上没有用!

    binutils邮件列表中的Simon Baldwin wrote确切描述了问题(我强调):



    我们遇到了旧系统(binutils 2.16)的问题。我将其与台式机系统上的2.20版进行了比较-voilà-共享全局符号的长度为0:

    157: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN12TableManagerD1Ev
    158: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZNSs6assignERKSs@GLIBCXX_3.4 (2)
    159: 00000000     0 FUNC    GLOBAL DEFAULT  UND sleep@GLIBC_2.0 (6)
    160: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN4Gpio11setErrorLEDENS_
    

    因此,我比较了binutils的源代码和-再来一遍-有Alan在邮件列表中建议的修复程序:

    也许我们只是应用补丁并重新编译binutils,因为我们需要使用较旧的平台。谢谢你的耐心。

    关于c++ - 为什么ELF中其他共享库的函数长度信息?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13628298/

    10-11 16:16