Как вывести список символов из .so файла?
Как мне отобразить символы, экспортируемые из файла .so? Если возможно, я также хотел бы узнать, откуда они берутся (например, если они импортируются из статической библиотеки).
Я использую gcc 4.0.2, если это имеет значение.
5 ответ(ов)
Стандартным инструментом для просмотра символов является nm
. Вы можете использовать его следующим образом:
nm -gD yourLib.so
Если необходимо увидеть символы библиотеки на C++, добавьте параметр -C
, который произведет деманглирование символов (в деманглированном виде они гораздо более читабельны):
nm -gDC yourLib.so
Если ваш файл .so
в формате ELF, у вас есть два варианта:
Первый – использовать objdump
(опция -C
также полезна для деманглирования C++):
$ objdump -TC libz.so
libz.so: file format elf64-x86-64
DYNAMIC SYMBOL TABLE:
0000000000002010 l d .init 0000000000000000 .init
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 free
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 __errno_location
0000000000000000 w D *UND* 0000000000000000 _ITM_deregisterTMCloneTable
Или вы можете использовать readelf
:
$ readelf -Ws libz.so
Symbol table '.dynsym' contains 112 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000002010 0 SECTION LOCAL DEFAULT 10
2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND free@GLIBC_2.2.5 (14)
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __errno_location@GLIBC_2.2.5 (14)
4: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
Команда objdump -TC /usr/lib/libexample.so
используется для вывода информации о символах (то есть, функциях и переменных), содержащихся в динамической библиотеке `lib
Для получения информации о символах в разделяемой библиотеке libNAME.so
необходимо использовать ключ -D
:
nm -D libNAME.so
Что касается статической библиотеки, как уже упоминали другие, следует применить ключ -g
:
nm -g libNAME.a
Это позволит просмотреть глобальные символы в статической библиотеке.
Я долго думал, почему флаги -fvisibility=hidden и #pragma GCC visibility не оказывают никакого влияния, поскольку все символы всегда были видны при использовании nm, пока не наткнулся на статью, которая указала мне на readelf и objdump. Это помогло мне осознать, что существует на самом деле две таблицы символов:
- Таблица, которую можно просмотреть с помощью nm
- Таблица, которую можно просмотреть с помощью readelf и objdump
Я полагаю, что первая таблица содержит отладочные символы, которые можно удалить с помощью команды strip или флага -s, который можно передать компоновщику или команде install. И даже если nm больше не показывает ничего, ваши экспортированные символы все равно будут экспортироваться, потому что они находятся в "динамической таблице символов" ELF, что соответствует второй таблице.
Для работы с .so
файлами на C++, в частности для получения информации о символах, вы можете использовать команду nm
с набором опций:
nm --demangle --dynamic --defined-only --extern-only <my.so>
Эта команда позволит вам увидеть только определенные и внешние символы из динамической библиотеки. Например, для библиотеки libqpid-proton-cpp.so
можно выполнить следующую команду:
nm --demangle --dynamic --defined-only --extern-only /usr/lib64/libqpid-proton-cpp.so | grep work | grep add
В результате вы получите что-то подобное:
0000000000049500 T proton::work_queue::add(proton::internal::v03::work)
0000000000049580 T proton::work_queue::add(proton::void_function0&)
000000000002e7b0 W proton::work_queue::impl::add_void(proton::internal::v03::work)
000000000002b1f0 T proton::container::impl::add_work_queue()
000000000002dc50 T proton::container::impl::container_work_queue::add(proton::internal::v03::work)
000000000002db60 T proton::container::impl::connection_work_queue::add(proton::internal::v03::work)
Если вас интересуют версии символов, также добавьте флаг --with-symbol-versions
.
Источник: ссылка на StackOverflow.
Каково влияние extern "C" в C++?
Как изменить цвет вывода echo в Linux
Разница между const int*, const int * const и int * const?
В чём разница между g++ и gcc?
Почему переменные нельзя объявлять в операторе switch?