2008-08-29 33 views
344

如何列出從.so文件導出的符號。如果可能的話,我也想知道它們的來源(例如,如果它們是從靜態庫中提取的)。如何列出.so文件中的符號

我用gcc 4.0.2,如果有差別

+0

該平臺有差別。 Apple提供了GCC 4.0,但是它的`nm`不響應某些選項,如`-D`和`-g`(IIRC)。 – jww 2015-09-13 08:50:37

+0

這在Mac OS上不打印任何東西。 – 2016-05-10 14:05:14

+3

@jww因爲那是BSD`nm`,而不是GNU`nm`。 – OrangeDog 2016-08-03 17:00:16

回答

419

上市符號的標準工具是nm,你可以簡單地使用它像這樣:

nm -g yourLib.so 

如果你想看到一個C++庫的符號,添加「-C」選項,還原函數符號(它的可讀性更強)。

nm -gC 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 [email protected]_2.2.5 (14) 
    3: 0000000000000000  0 FUNC GLOBAL DEFAULT UND [email protected]_2.2.5 (14) 
    4: 0000000000000000  0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable 
+23

但是,這並不總是適用於.so文件,因此您可能不得不使用另一個答案中提到的「readelf」解決方案。 – 2010-12-13 23:53:22

+0

好的答案 - 但我沒有從nm,objdump或readelf獲取函數簽名。你知道我如何獲得函數簽名(參數)嗎? – 2012-06-20 22:07:59

+7

請注意,nm的OS X版本缺少將符號解映射的'-C'選項。可以用C++ filt代替。示例腳本:http://v8.googlecode.com/svn/branches/bleeding_edge/tools/mac-nm nm -g /usr/lib/libstdc++.6.dylib | C++ filt -p -i – fredbaba 2013-06-12 21:13:34

9

您可以使用從binutils的工具鏈的nm -g工具。但是,它們的來源並不總是可用。而且我實際上並不確定這些信息總是可以被檢索到。也許objcopy顯示進一步的信息。

/編輯:該工具的名稱當然是nm。標誌-g用於僅顯示導出的符號。

11

嘗試添加-l到nm標誌以g et每個符號的來源。如果庫是用調試信息(gcc -g)編譯的,這應該是源文件和行號。正如康拉德所說,目標文件/靜態庫在這一點上可能是未知的。

64

如果您的.so文件爲elf格式,則可以使用readelf程序從二進制文件中提取符號信息。這個命令會給你的符號表:

readelf -Ws /usr/lib/libexample.so 

你應該只提取那些在此.so文件中定義的,而不是由它引用的庫。在這種情況下,第七列應該包含一個數字。您可以通過使用一個簡單的regex提取它:

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

或建議,由Caspin,:

readelf -Ws /usr/lib/libstdc++.so.6 | awk '{print $8}'; 
39
objdump -TC /usr/lib/libexample.so 
28

我一直在想,爲什麼-fvisibility =隱藏的#pragma GCC能見度似乎沒有任何影響,因爲所有的符號總是可見的nm - 直到我發現這篇文章,指出我readelfobjdump的,這讓我認識到,似乎實際上是符號表:

  • 一個你可以用納米
  • 的一個列表,你可以用readelf名單objdump的

我認爲前者包含debuggi ng符號,可用剝離或-s開關,您可以給連接器或安裝命令。即使nm不再列出任何東西,導出的符號仍然會被導出,因爲它們位於ELF的「動態符號表」中,後者是後者。

5

nm -g列出extern變量,這不是必需的導出符號。 任何非靜態文件範圍變量(在C中)都是extern變量。

nm -D將在動態表中列出該符號,您可以通過dlsym找到它的地址。

納米--version

GNU納米2.17.50.0.6-12.el5 20061020

30

對於共享庫以libname.so -D開關必要看到在我的Linux

nm -D libNAME.so 
符號

和靜態庫所報告的其他

nm -g libNAME.a 
7

對於安卓.so文件,NDK工具鏈隨附其他答案中提到的所需工具:readelfobjdumpnm

3

對於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/a/43257338

相關問題