Linux 使用 g++ 的符号可见性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4994741/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Symbol visibility using g++
提问by JoeSlav
I compiled a C++ library under Linux/Mac with its symbols hidden. I've used _attribute_ ((visibility("hidden")))for all my classes and compiled with options (-c -O2 -fPIC -MMD -MP -MF). Under Mac, using MacDependencies (http://code.google.com/p/macdependency/), the job is done just fine as I see only my exports (I actually saw the difference before and after).
我在 Linux/Mac 下编译了一个隐藏符号的 C++ 库。我已经将_属性_ ((visibility("hidden")))用于我的所有类,并使用选项(-c -O2 -fPIC -MMD -MP -MF)进行编译。在 Mac 下,使用 MacDependencies (http://code.google.com/p/macdependency/),工作做得很好,因为我只看到了我的导出(我实际上看到了前后的差异)。
However, I noticed that using nmI still see all the names of the symbols. This happens under both Mac and Linux.
但是,我注意到使用nm我仍然可以看到所有符号的名称。这在 Mac 和 Linux 下都会发生。
Why is that? Is there any way to avoid this?
这是为什么?有什么办法可以避免这种情况吗?
Best Regards and thanks, Joe
最好的问候和感谢,乔
采纳答案by Maxim Egorushkin
Public or hidden, symbols are still there. nm
shows all symbols. The difference is that hidden symbols are not available to the dynamic linker, i.e. not exported and can not be interposed.
公共或隐藏,符号仍然存在。nm
显示所有符号。不同之处在于动态链接器无法使用隐藏符号,即无法导出且无法插入。
You might also like the following man gcc
:
您可能还喜欢以下内容 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.
回答by Timmmm
On OSX (not sure about others) I found the following.
在 OSX 上(不确定其他人)我发现了以下内容。
As mentioned by Maxim, using -fvisibility=hidden
or __attribute__((visibility("hidden")))
still puts the symbol in the symbol table, it just gets marked as unexported. The easiest way to see this is with nm
, e.g:
正如 Maxim 所提到的,使用-fvisibility=hidden
或__attribute__((visibility("hidden")))
仍然将符号放入符号表中,它只是被标记为未导出。看到这一点的最简单方法是使用nm
,例如:
$ nm libfoo.dylib
...
0000000000001fa0 t __Z10a_functionv
0000000000002140 T __Z17a_public_functionv
...
If the letter after the address is lowercase it means it isn't exported. Here a_function()
is hidden, and a_public_function
has default visibility.
如果地址后面的字母是小写,则表示它没有导出。这里a_function()
是隐藏的,并且a_public_function
具有默认可见性。
To strip the non-exported symbols from the symbol table you can use strip -x
, which according to the man page:
要从符号表中去除未导出的符号,您可以使用strip -x
,根据手册页:
-x Remove all local symbols (saving only the global symbols).
-x 删除所有局部符号(仅保存全局符号)。
$ strip -x libfoo.dylib
$ nm libfoo.dylib
...
0000000000002140 T __Z17a_public_functionv
...
I believe (but am not 100% sure) that using hidden
doesn't justamount to changing a flag, and 'unhiding' the symbols wouldn't be trivial.
我相信,(但我不是100%确定),使用hidden
并不仅仅等同于不断变化的一个标志,而“取消隐藏”符号不会是微不足道的。