使用 g++ 的符号可见性

Posted

技术标签:

【中文标题】使用 g++ 的符号可见性【英文标题】:Symbol visibility using g++ 【发布时间】:2011-06-27 01:19:47 【问题描述】:

我在 Linux/Mac 下编译了一个隐藏符号的 C++ 库。我已经为我的所有类使用了 _attribute_ ((visibility("hidden"))) 并使用选项 (-c -O2 -fPIC -MMD -MP -MF)。在 Mac 下,使用 MacDependencies (http://code.google.com/p/macdependency/),工作做得很好,因为我只看到了我的导出(我实际上看到了之前和之后的区别)。

但是,我注意到使用 nm 我仍然可以看到所有符号的名称。这在 Mac 和 Linux 下都会发生。

这是为什么呢?有什么办法可以避免吗?

最好的问候和感谢, 乔

【问题讨论】:

在 Linux 上,您是否使用 nm -D 来显示动态符号表?可见性仅适用于动态符号表。 nm -D 确实给了我正确的“列表”,谢谢。 【参考方案1】:

在 OSX 上(不确定其他)我发现了以下内容。

正如 Maxim 所提到的,使用 -fvisibility=hidden__attribute__((visibility("hidden"))) 仍然会将符号放入符号表中,它只是被标记为未导出。最简单的查看方法是使用nm,例如:

$ nm libfoo.dylib 
...
0000000000001fa0 t __Z10a_functionv
0000000000002140 T __Z17a_public_functionv
...

如果地址后面的字母是小写的,则表示它没有被导出。这里a_function() 是隐藏的,a_public_function 具有默认可见性。

要从符号表中去除未导出的符号,您可以使用strip -x,根据手册页:

-x 删除所有局部符号(只保存全局符号)。

$ strip -x libfoo.dylib
$ nm libfoo.dylib 
...
0000000000002140 T __Z17a_public_functionv
...

我相信(但不是 100% 肯定)使用 hidden只是等于更改标志,并且“取消隐藏”符号并非易事。

【讨论】:

strip -x 命令是我要从表中完全删除本地符号的命令,即使用nm 无法看到。【参考方案2】:

您可以strip您的二进制文件来删除任何不需要的符号。

【讨论】:

谢谢!我实际上试图在 Netbeans 中勾选“Strip”,但它没有成功。我现在用 --strip-all 手动尝试,看起来我得到了我期望的结果。感谢所有参与的人!【参考方案3】:

公开或隐藏,符号仍然存在。 nm 显示所有符号。不同之处在于动态链接器无法使用隐藏符号,即无法导出且无法插入。

您可能还喜欢以下man gcc

   -fvisibility=default|internal|hidden|protected
       ...
       A good explanation of the benefits offered by ensuring ELF symbols
       have the correct visibility is given by "How To Write Shared
       Libraries" by Ulrich Drepper (which can be found at
       <http://people.redhat.com/~drepper/>)---however a superior solution
       made possible by this option to marking things hidden when the
       default is public is to make the default hidden and mark things
       public.  This is the norm with DLL's on Windows and with
       -fvisibility=hidden and "__attribute__ ((visibility("default")))"
       instead of "__declspec(dllexport)" you get almost identical
       semantics with identical syntax.  This is a great boon to those
       working with cross-platform projects.

【讨论】:

谢谢Maxim,现在肯定有所不同了。但是又出现了一个问题:在 Windows 下如何查看此类符号表?再次感谢。 可能来自 cygwin 的 depends.exenm 再次感谢,我明天试试。您知道从 nm 的输出中实际删除这些符号的任何方法吗? makr4o 已经给了你答案:nm --dynamicnm --extern-only 取决于你想要什么。 抱歉,我的意思是:有什么方法可以编译/链接/剥离/等我的共享库,这样这些名称就不会以普通的“nm”显示?

以上是关于使用 g++ 的符号可见性的主要内容,如果未能解决你的问题,请参考以下文章

出口制造商,符号可见性,...?

符号可见性、异常、运行时错误

符号可见性和 gcc 警告

如果类没有默认可见性,如何使静态断言失败

GCC:内部可见性“在现实世界的使用中毫无用处”?

如何从活动中更改片段中视图的可见性