Видимость символов с помощью g++

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

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

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

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


person JoeSlav    schedule 14.02.2011    source источник
comment
В Linux вы используете nm -D для отображения динамической таблицы символов? Видимость применяется только к динамической таблице символов.   -  person mark4o    schedule 14.02.2011
comment
nm -D дает мне действительно правильный список, спасибо.   -  person JoeSlav    schedule 14.02.2011


Ответы (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.
person Maxim Egorushkin    schedule 14.02.2011
comment
Спасибо, Максим, теперь точно получил разницу. Однако возникает еще один вопрос: как я могу увидеть такую ​​таблицу символов под Windows? Спасибо еще раз. - person JoeSlav; 14.02.2011
comment
Вероятно, depends.exe или nm из cygwin. - person Maxim Egorushkin; 14.02.2011
comment
Еще раз спасибо, завтра попробую. Знаете ли вы какой-либо способ удалить эти символы из вывода nm? - person JoeSlav; 14.02.2011
comment
makr4o уже дал вам ответ: nm --dynamic и nm --extern-only в зависимости от того, что вы хотите. - person Maxim Egorushkin; 14.02.2011
comment
Извините, я хотел сказать: есть ли способ скомпилировать/связать/разрезать/и т. д. мою общую библиотеку, чтобы эти имена не отображались с простым «nm»? - person JoeSlav; 14.02.2011

Вы можете strip удалить все ненужные символы.

person Hasturkun    schedule 14.02.2011
comment
Спасибо! На самом деле я пытался поставить галочку Strip из Netbeans, но это не помогло. Я попробовал вручную с --strip-all и, похоже, получил ожидаемый результат. Спасибо всем, кто принял участие! - person JoeSlav; 14.02.2011

В 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, который согласно справочной странице:

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

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

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

person Timmmm    schedule 17.01.2017
comment
Команда strip -x - это то, что я искал, чтобы полностью удалить локальные символы из таблицы, т.е. их нельзя увидеть с помощью nm. - person Avi Tevet; 17.04.2019