【问题标题】:Stripping symbols from shared library seems not to work从共享库中剥离符号似乎不起作用
【发布时间】:2019-10-24 06:06:15
【问题描述】:

我正在尝试使用 strip 命令从我的共享库中删除非公共符号,但是当我之后应用“nm -C -D”时,我仍然看到所有符号。

我已经查看过这篇文章和其他帖子:Stripping linux shared libraries 以及 gcc Wiki:https://gcc.gnu.org/wiki/Visibility 但是对于我的示例代码,建议的解决方案似乎不起作用。

我声明了两个简单的类,一个用于保持可见,另一个将被删除。对于公众,我在源代码中声明__attribute__ ((visibility ("default")))

当我使用 -fvisibility=hidden 编译和链接并随后在共享库上运行“strip --strip-all --discard-all”时,这两个类在 T(ext) 部分中仍然可见。

这是我的头文件:

#pragma once

#if __GNUC__ >= 4
    #define DLL_PUBLIC __attribute__ ((visibility ("default")))
#else
    #define DLL_PUBLIC
#endif

class DLL_PUBLIC PublicClass
{
public:
  PublicClass() = default;
  ~PublicClass() = default;

  void doSomethingPublic();
};

class PrivateClass
{
public:
  PrivateClass() = default;
  ~PrivateClass() = default;

  void doSomethingPrivate();
};

这是来源:

#include <iostream>
#include "test.hpp"

void PublicClass::doSomethingPublic() { std::cout << "public call" << std::endl; } 
void PrivateClass::doSomethingPrivate() { std::cout << "private call" << std::endl; } 

我在 Ubuntu 18.04 上编译一个目标文件并将共享库与 gcc 7.4.0 链接:

$ /usr/local/bin/c++ -fvisibility=hidden -O3 -DNDEBUG -fPIC -std=gnu++14 -c test.cpp -o test.cpp.o
$ /usr/local/bin/c++ -fvisibility=hidden -fPIC -DNDEBUG -O3 -shared -Wl,-soname,libtest.so -o libtest.so test.cpp.o

应用 strip 命令并显示符号表:

$ strip --strip-all --discard-all --verbose libtest.so
copy from `libtest.so' [elf64-x86-64] to `stSNqAeg' [elf64-x86-64]
$ nm -C -D libtest.so
0000000000201058 B __bss_start
                 U __cxa_atexit
                 w __cxa_finalize
0000000000201058 D _edata
0000000000201060 B _end
0000000000000b84 T _fini
                 w __gmon_start__
00000000000008a8 T _init
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
0000000000000a60 T PublicClass::doSomethingPublic()
0000000000000af0 T PrivateClass::doSomethingPrivate()
                 U std::ctype<char>::_M_widen_init() const
0000000000000b80 W std::ctype<char>::do_widen(char) const
                 U std::ostream::put(char)
                 U std::ostream::flush()
                 U std::ios_base::Init::Init()
                 U std::ios_base::Init::~Init()
                 U std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
                 U std::__throw_bad_cast()
                 U std::cout

strip 命令实际上重写了共享库(日期和大小已更改),但我仍然看到私有符号。我希望 PrivateClass::doSomethingPrivate 方法可以从符号表中删除。

如果有任何提示,我将不胜感激。

【问题讨论】:

  • 这是否使用股票 g++ 而不是 /usr/local/bin/c++ 复制?

标签: c++ shared-libraries visibility hidden strip


【解决方案1】:

你需要用-fvisibility=hidden编译:

$ g++ -fvisibility=hidden -shared -fPIC tmp.cc
$ readelf -D -sW a.out | grep doSomething
    9  16: 000000000000092c    58 FUNC    GLOBAL DEFAULT  10 _ZN11PublicClass17doSomethingPublicEv

【讨论】:

  • 很好,抱歉,我粘贴了错误的命令行。我最初确实指定了 -fvisibility=hidden 并且只是没有检查它是否有任何区别。我会编辑帖子。
  • @joggerwolf 我恐怕无法在 Ubuntu 18.04 上使用 stock g++ 7.4 重现这种行为(nm 的输出中没有 doSomethingPrivate 符号)。 /usr/local/bin/c++ 来自哪里?
  • 感谢您的检查。我假设它直接来自发行版,现在尝试使用它按预期工作的示例来重现它:-(
  • 不幸的是,它仍然无法在我使用 cmake 设置的真实项目中运行,并且由于 IP 原因我无法共享。我检查了详细的 cmake 输出,并且 -fvisibility=hidden 按预期出现在命令行上,但是使用 objdump -t 查看目标文件,在某些符号处有 .hidden 指示,但比我会期待,因为我只标记了一个具有默认可见性的类。
  • @joggerwolf "我假设它直接来自发行版" - 通常发行版不会在 /usr/local 上安装任何东西(例如,我的默认 Ubuntu 18 安装没有 c++ 那里)。你能检查一下这个可执行文件的来源(通过dpkg -S)吗?
猜你喜欢
  • 2023-03-06
  • 2015-01-03
  • 2011-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-06
相关资源
最近更新 更多