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

486

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

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

Моу
источник
Платформа имеет значение. Apple предоставляет GCC 4.0, но nmон не отвечает на некоторые параметры, такие как -Dи -g(IIRC).
jww
Это ничего не печатает на Mac OS.
Игорь Ганапольский
3
@jww, потому что это BSD nm, а не GNU nm.
OrangeDog

Ответы:

577

Стандартный инструмент для перечисления символов 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
Стив Гури
источник
35
Однако это не всегда работает с файлами .so, поэтому вам, возможно, придется использовать решение "readelf", упомянутое в другом ответе.
Брукс Моисей
9
Обратите внимание, что в версиях OS X nm отсутствует опция -C для разметки символов. C ++ Filter может быть использован вместо. Пример скрипта здесь: v8.googlecode.com/svn/branches/bleeding_edge/tools/mac-nm nm -g /usr/lib/libstdc++.6.dylib | C ++ Filter -p -i
Фредбаба
5
Обратите внимание, что readelf -Wsбудут показаны все символы и nm -gпоказаны только внешне видимые символы. Это может сбивать с толку, если вы изучаете несколько файлов символов и начинаете обмениваться командами.
Андрей Б,
3
Я бы тоже добавил objectdump -TCв список. В отличие от этого readelf -Ws, он не показывает искаженные имена.
Ян Фото
2
@BrooksMoses Для .soфайлов может потребоваться добавить --dynamicв nmкомандную строку.
user7610
84

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

readelf -Ws /usr/lib/libexample.so

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

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

или, как предложил Каспин ,

readelf -Ws /usr/lib/libstdc++.so.6 | awk '{print $8}';
П Швед
источник
19
readelf -Ws /usr/lib/libstdc++.so.6 | awk '{print $ 8}'; регулярные выражения являются удивительными, но иногда маленький awk проходит долгий путь.
deft_code
42

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

nm -D libNAME.so

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

nm -g libNAME.a
cavila
источник
35

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

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

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

Питер Реммерс
источник
3
Спасибо! Это объясняет, почему иногда «nm» не отображает символы для файлов .so.
Брукс Моисей
10
nm -D - позволяет вам перечислить динамическую таблицу символов
pt123
19

Для .soфайлов C ++ конечная 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/a/43257338

user7610
источник
11

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

Адам Миц
источник
11

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

Ади Шавит
источник
9

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

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

Конрад Рудольф
источник
6

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

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

нм - версия

GNU nm 2.17.50.0.6-12.el5 20061020

zhaorufei
источник
1

Если вы просто хотите знать , если есть символы представляют вы можете использовать

objdump -h /path/to/object

или перечислить отладочную информацию

objdump -g /path/to/object
Крейг Рингер
источник