Як перерахувати символи у файлі .so


485

Як перерахувати символи, що експортуються з файлу .so? Якщо можливо, я також хотів би дізнатися їх джерело (наприклад, якщо вони витягнуті зі статичної бібліотеки).

Я використовую gcc 4.0.2, якщо це має значення.


Платформа має значне значення. Apple пропонує GCC 4.0, але nmвін не відповідає деяким параметрам, як-от -Dі -g(IIRC).
jww

Це нічого не друкує на Mac OS.
ІгорГанапольський

3
@jww, тому що це BSD nm, а не GNU nm.
OrangeDog

Відповіді:


575

Стандартний інструмент для переліку символів 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 ++ filt може бути використаний замість цього. Приклад скрипту тут: v8.googlecode.com/svn/branches/bleeding_edge/tools/mac-nm nm -g /usr/lib/libstdc++.6.dylib | c ++ filt -p -i
fredbaba

5
Зверніть увагу, що readelf -Wsбудуть показані всі символи, а також nm -gлише видимі зовні символи. Це може бути заплутаним, якщо ви вивчаєте кілька файлів символів і починаєте обмінюватися своїми командами.
Андрій Б

3
Я також додав objectdump -TCби до списку. На противагу цьому readelf -Ws, в ньому не відображаються зловмисні імена.
Ян Фото

2
@BrooksMoses Для .soфайлів, можливо, вам потрібно буде додати --dynamicдо nmкомандного рядка.
користувач7610

84

Якщо ваш .soфайл у форматі ельфів, ви можете скористатися програмою 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}';

19
readelf -Ws /usr/lib/libstdc++.so.6 | awk '{print $ 8}'; регексети є приголомшливими, але іноді невеликий буд проходить довгий шлях.
deft_code


42

Для спільних бібліотек libNAME.so перемикач -D був необхідний, щоб побачити символи в моєму Linux

nm -D libNAME.so

і для статичної бібліотеки, як повідомляють інші

nm -g libNAME.a

35

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

  • Той, який ви можете перелічити за допомогою nm
  • Той, який ви можете перелічити за допомогою readelf та objdump

Я думаю, що перший містить символи налагодження, які можна позбавити смужкою або перемикачем -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


11

Спробуйте додати -l до nm-прапорів, щоб отримати джерело кожного символу. Якщо бібліотека зібрана з інформацією про налагодження (gcc -g), це повинен бути вихідний файл та номер рядка. Як сказав Конрад, на даний момент об'єктний файл / статична бібліотека, ймовірно, невідомий.


11

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


9

Ви можете використовувати nm -gінструмент із ланцюжка інструментів binutils. Однак їх джерело не завжди легко доступне. і я фактично навіть не впевнений, що цю інформацію завжди можна отримати. Можливо, objcopyрозкриває подальшу інформацію.

/ EDIT: Звичайно, ім'я інструменту nm. Прапор -gвикористовується для відображення лише експортованих символів.


6

nm -g список зовнішньої змінної, яка не обов'язково експортується символом. Будь-яка нестатична змінна область файлу (у С) - це зовнішня змінна.

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

нм --версія

GNU nm 2.17.50.0.6-12.el5 20061020


1

Якщо ви просто хочете знати , якщо є символи представляють ви можете використовувати

objdump -h /path/to/object

або перелічити інформацію про налагодження

objdump -g /path/to/object
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.