Как мне перечислить символы в .so файле

422

Как мне перечислить символы, экспортируемые из .so файла? Если возможно, я также хотел бы знать их источник (например, если они извлекаются из статической библиотеки).

Я использую gcc 4.0.2, если это имеет значение.

  • 0
    Платформа имеет значение. Apple предоставляет GCC 4.0, но его nm не реагирует на некоторые параметры, такие как -D и -g (IIRC).
  • 0
    Это ничего не печатает на Mac OS.
Показать ещё 1 комментарий
Теги:
gcc
symbols
name-mangling

10 ответов

446
Лучший ответ

Стандартный инструмент для перечисления символов nm, вы можете использовать его просто так:

nm -g yourLib.so

Если вы хотите увидеть символы библиотеки С++, добавьте опцию "-C", которая разворачивает символы (это гораздо более читаемое разворачивание).

nm -gC yourLib.so

Если ваш .so файл находится в формате elf, у вас есть два варианта:

Либо objdump (-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
  • 29
    Однако это не всегда работает с файлами .so, поэтому вам, возможно, придется использовать решение "readelf", упомянутое в другом ответе.
  • 0
    Отличный ответ - но я не получаю сигнатуры функций от nm, objdump или readelf. Вы знаете, как я могу также получить сигнатуру функции (параметры)?
Показать ещё 8 комментариев
69

Если ваш файл .so находится в формате elf, вы можете использовать программу readelf для извлечения символьной информации из двоичного файла. Эта команда даст вам таблицу символов:

readelf -Ws /usr/lib/libexample.so

Вам нужно извлечь только те, которые определены в этом .so файле, а не в библиотеках, на которые он ссылается. Седьмой столбец должен содержать номер в этом случае. Вы можете извлечь его с помощью простого регулярного выражения:

readelf -Ws /usr/lib/libstdc++.so.6 | grep '^\([[:space:]]\+[^[:space:]]\+\)\{6\}[[:space:]]\+[[:digit:]]\+'

или, как предложено Caspin,:

readelf -Ws /usr/lib/libstdc++.so.6 | awk '{print $8}';
  • 18
    readelf -Ws /usr/lib/libstdc++.so.6 | awk '{print $ 8}'; регулярные выражения являются удивительными, но иногда маленький awk проходит долгий путь.
46
objdump -TC /usr/lib/libexample.so
  • 3
    Неплохо. Дает расколотые имена, которые оказываются полезными
34

Для разделяемых библиотек libNAME.so необходимо было установить ключ -D для отображения символов в моем Linux

nm -D libNAME.so

и для статической библиотеки, о которой сообщают другие.

nm -g libNAME.a
30

Я продолжал задаваться вопросом, почему -fvisibility = hidden и #pragma GCC видимость, похоже, не имеет никакого влияния, поскольку все символы всегда были видны с помощью nm - пока я не нашел это сообщение, которое указывало мне на readelf и objdump, что сделало меня поймите, что на самом деле существуют таблицы two:

  • Тот, который вы можете перечислить с помощью nm
  • Тот, который вы можете перечислить с помощью readelf и objdump

Я думаю, что первая содержит отладочные символы, которые могут быть разделены полосой или ключом -s, который вы можете предоставить компоновщику или команде установки. И даже если nm больше ничего не перечисляет, ваши экспортированные символы все еще экспортируются, потому что они находятся в таблице динамических символов ELF, которая является последней.

  • 3
    Спасибо! Это объясняет, почему иногда «nm» не отображает символы для файлов .so.
  • 8
    nm -D - позволяет вывести список динамических символов
11

Попробуйте добавить -l к флагам nm, чтобы получить источник каждого символа. Если библиотека скомпилирована с информацией об отладке (gcc -g), это должен быть исходный файл и номер строки. Как сказал Конрад, объектный файл/статическая библиотека, вероятно, неизвестна в этот момент.

  • 0
    nm: Unknown command line argument '-l'
9

Для файлов Android .so набор инструментов NDK поставляется с необходимыми инструментами, упомянутыми в других ответах: readelf, objdump и nm.

9

Вы можете использовать инструмент nm -g из инструментальной цепочки binutils. Однако их источник не всегда легко доступен. и я даже не уверен, что эта информация всегда может быть восстановлена. Возможно, objcopy раскрывает дополнительную информацию.

/EDIT: название инструмента, конечно, nm. Флаг -g используется для отображения только экспортированных символов.

8

Для файлов C++ .so конечная команда nm - nm --demangle --dynamic --defined-only --extern-only <my.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)

источник: https://stackoverflow.com/questions/43256459/g-undefined-reference-although-symbol-is-present-in-so-file

5

nm -g введите переменную extern, которая не является необходимым экспортированным символом. Любая переменная области нестатического размера файла (в C) является внешней переменной.

nm -D отобразит символ в динамической таблице, который вы можете найти по адресу dlsym.

nm --version

GNU nm 2.17.50.0.6-12.el5 20061020

Ещё вопросы

Сообщество Overcoder
Наверх
Меню