gcc 从C++动态库中删除一组符号(只保留给定的一组)

n3h0vuf2  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(159)

我正在构建一个动态库(用C编写),它可以导出许多符号。
这些导出的符号(很明显)与我的库的API相匹配。2然而,我的库还导出了过多的附加符号(在我的公共头中根本没有提到)。
为了使我的库的二进制接口保持较小(防止名称冲击;不破坏符号空间;防止库的使用者 * 意外地 * 使用可能在下一个版本中消失的符号),我可以使用版本脚本显式地导出符号,如下所示(实际上版本脚本要复杂得多;在任何情况下,它都涉及到C
-解交错的符号和通配符):

{
        global:
                extern "C++" {
                /* the public API uses the 'MyLib::' namespace */
                 MyLib::*;
                };
                /* g++ version mangling prefixes for 'typeinfo' */
                _ZTI*; _ZTF*; _ZTS*;
                /* g++ version mangling prefixes for 'vtable' */
                 _ZTT*; _ZTV*;
        local:
                *;
};

字符串
然后使用这些附加标志-fvisibility=hidden -Wl,--version-script=mylib.ver调用链接器
酷了
现在,这个库还附带了一个测试套件。为了能够编写简洁的测试,单元测试使用的符号不是公共API的一部分。
从库中去除非公共符号将阻止单元测试(与库链接)找到这些符号。因此,测试套件将变得不可用。
一个明显的解决方法是在单元测试中只使用公共符号,但这会使单元测试更加复杂,测试结果也更难解释。
另一个可能的解决方案是不使用动态库来进行单元测试,而是使用其他库(例如,静态库;或者不使用版本脚本链接的库的变体)。我不喜欢这样,因为我想测试实际的库,而不是一些替代品。
第三种解决方案(我最喜欢)是将非公共符号的剥离推迟到库的部署:测试套件将使用本地库构建(带有所有符号),但在make install(或其他一些显式的构建后步骤)期间,不必要的符号将被剥离。
不幸的是,我不知道如何实现这一点。

  • 版本脚本是链接器的一个功能
  • strip这样的工具做了一些不同的事情(有一个-N标记到(GNU?)strip,它应该删除一个符号,但它似乎不工作,即使是一个普通的C库(没有C++符号混乱)

于是:有没有一种方法可以在编译后的步骤中从库中去掉符号(只保留一个已知的集合)?2如果有,如何通过C++符号的修饰和使用通配符来做到这一点?

xkrw2x1b

xkrw2x1b1#

有没有一种方法可以在构建后的步骤中从库中删除符号(只保留一个已知的集合)?
是的。(动态)符号名称位于.dynstr部分,如果您覆盖那里的名称(例如,用_XMyLib覆盖_ZMyLib...),动态链接器将不会解析这些符号。
迭代.dynsym(动态)符号表中的所有符号不是hard
如何使用C++符号处理和使用通配符?
您必须在每个符号上调用__cxa_demangle,然后进行字符串匹配,并决定是“zap”该符号还是不处理它。

相关问题