静态libstdc ++中的全局符号.a在共享libstdc ++中是本地的。所以

时间:2015-07-25 17:16:42

标签: c++ linker g++ libstdc++

在尝试使用__gcclibcxx_demangle_callback作为__cxa_demangle的非分配替代方案时,我遇到了一个给我带来麻烦的问题。当我静态链接libstdc++时,符号位于,但是当我动态链接时,g ++报告:

undefined reference to `__gcclibcxx_demangle_callback'

奇怪的是,nm将其列在一个而不是另一个:

me@compy:/lib$ nm libstdc++.a | grep demangle
0000543d T __cxa_demangle
0000550d T __gcclibcxx_demangle_callback
me@compy:/lib$ nm -D libstdc++.so | grep demangle
0004eabd T __cxa_demangle

readelf的输出提示了为什么 - 它在静态中是全局的,在共享中是本地的:

me@compy:/lib$ readelf -s libstdc++.a | grep demangle
   179: 0000543d   208 FUNC    GLOBAL DEFAULT    1 __cxa_demangle
   180: 0000550d    32 FUNC    GLOBAL DEFAULT    1 __gcclibcxx_demangle_callback
me@compy:/lib$ readelf -s libstdc++.so | grep demangle
  8313: 0004eb8d    32 FUNC    LOCAL  DEFAULT   12 __gcclibcxx_demangle_callback
 10871: 0004eabd   208 FUNC    GLOBAL DEFAULT   12 __cxa_demangle

静态地将我的整个应用程序与libstdc++静态链接不是一种选择。

我的问题有两个:

  1. 为什么两者之间的能见度不同?
  2. 如何获取此符号?有没有办法动态地获取它,或仅静态链接此符号所在的目标文件?

1 个答案:

答案 0 :(得分:0)

首先,可见性是不同的,因为在这两者中,__cxa_demangle标头中只声明了<cxxabi.h>。该标头包含#pragma GCC visibility push(default),可确保在使用-fvisibility=hidden进行编译时,其中的所有声明都可见。

其次,您可以静态链接到libstdc ++或者链接到libiberty。 libiberty导出cplus_demangle_v3_callback,它使用与__gcclibcxx_demangle_callback相同的基础函数。它只是没有任何参数检查,也没有选择所需的demangling选项。你可以这样称呼它:

template <typename F>
struct lambda_caller
{
    F f;
    constexpr lambda_caller(F f) : f(std::move(f)) {}
    static void call(const char* data, size_t length, void* self)
    {
        static_cast<lambda_caller*>(self)->f(data, length);
    }
};

if (!lambda_caller callback{[&](const char* data, size_t length) {
        ::write(STDERR_FILENO, data, length);
    }}; ::cplus_demangle_v3_callback(mangled_name, DMGL_PARAMS | DMGL_TYPES,
                                   &callback::call, &callback))
    throw std::invalid_argument
        "mangled_name is not validly mangled according to C++ ABI rules"};