Видимость символов с помощью g ++ - PullRequest
7 голосов
/ 14 февраля 2011

Я скомпилировал библиотеку C ++ под Linux / Mac с ее скрытыми символами. Я использовал _ атрибут _ ((видимость ("скрытый"))) для всех моих классов и скомпилирован с параметрами (-c -O2 -fPIC -MMD -MP -MF ). В Mac с использованием MacDependencies (http://code.google.com/p/macdependency/), работа выполнена просто отлично, так как я вижу только свои экспорты (на самом деле я видел разницу до и после).

Однако я заметил, что используя нм я все еще вижу все названия символов. Это происходит как под Mac, так и под Linux.

Почему это? Есть ли способ избежать этого?

С уважением и благодарностью, Джо

Ответы [ 3 ]

13 голосов
/ 14 февраля 2011

Публичный или скрытый, символы все еще там. 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.
6 голосов
/ 14 февраля 2011

Вы можете strip свой двоичный файл, чтобы удалить все ненужные символы.

1 голос
/ 17 января 2017

На OSX (не уверен насчет других) я обнаружил следующее.

Как упомянул Максим, использование -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, что в соответствии с man-страницей:

-x Удалить все локальные символы (сохраняя только глобальные символы).

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

Я считаю (но не уверен на 100%), что использование hidden не просто означает изменение флага, и «скрытие» символов не будет тривиальным.

...