函式庫檔案中的符號表 nm命令

2021-05-18 08:03:21 字數 2959 閱讀 2886

nm命令可以列出乙個函式庫檔案中的符號表。它對於靜態的函式庫和共享的函式庫都起作用。對於乙個給定的函式庫,nm命令可以列出函式庫中定義的所有符號,包括每個符號的值和型別。還可以給出在原程式中這個函式(符號)是在多少行定義的,不過這必須要求編譯該函式庫的時候加「-l」選項。

關於符號的型別,這裡我們再多討論一下。符號的型別是以乙個字母的形式顯示的,小寫字母表示這個符號是本地(local)的,而大寫字母則表示這個符號是全域性的(global,externel)。一般來說,型別有一下幾種:t、d、b、u、w。各自的含義如下:t表示在**段中定義的一般變數符號;d表示時初始化過的資料段;b表示初始化的資料段;u表示沒有定義的,在這個庫裡面使用了,但是在其他庫中定義的符號;w,weak的縮寫,表示如果其他函式庫中也有對這個符號的定義,則其他符號的定義可以覆蓋這個定義。

如果你知道乙個函式的名字,但是你不知道這個函式在什麼庫中定義的,那麼可以用mn的「-o」選項和grep命令來查詢庫的名字。-o選項使得顯示的每一行都有這個函式庫檔名。例如,你要查詢「cos」這個是在什麼地方定義的,大致可以用下面的命令:

nm  libuserdecorate.so -a -l 2> /dev/null |grep init_cnf

libuserdecorate.so:0002e476 t _zn3zbp18userdecorateserver8init_cnfepkc  /data/home/macky/svn/isd_qqvipserver_rep/decorate_proj/trunk/operate_server/src/main/user_decorate_server.cpp:76

關於nm的更詳細的用法:man nm

轉同事steven的一篇故障定位文章:

上線通知存在兩個問題:

1, 共享記憶體洩漏

2, 共享記憶體attach後沒有dettach。上線通知對共享記憶體的使用比較特殊,會在各個函式中呼叫attach以使用共享記憶體。這樣,在每次使用後沒有dettach的後果是:shm的nattach數量不斷遞增,到一定程度導致程式core。這個問題查了好久也沒有查出原因,之前在析構函式中加printf,發現根本沒有呼叫析構函式。在打算修改共享記憶體的使用方法時(共享記憶體只在啟動時attach,避免在功能函式中attach),still大師幫忙找出問題的關鍵所在。

下面分別談談這兩個問題的分析與定位。

1, 共享記憶體洩漏定位

ø 在出問題的機器上檢視共享記憶體使用情況,用ipcs 

–m檢視結果存在大量如下共享記憶體段:

------ shared memory segments --------

key        shmid      owner      perms      bytes      nattch     status  

0x00000000 1835059    user_00   

600        

204800

0                       

0x00000000 1867828    user_00   

600       200

shm的key為0,大小固定。

ø 在開發機上啟動程式時統計大小為204800的共享記憶體塊的個數。

ipcs -m|grep 204800|wc –l

,發現每啟動一次,個數增加1.

ø 檢視上線通知程序id

ø 檢視各個程序的共享記憶體使用情況:

為便於顯示,省略時間戳資訊。

1) c

ache_main程序:

2) n

otify_worker程序id為11639)

主角出現,該worker使用了大小為204800的shm塊,並且key為0.

3) w

eihu_worker(程序id為11637)

發現只用到了乙個16m的shm,為worker與proxy之間的shm。

ø 結論:

notify_worker程序每次啟動時都會建立一塊shm大小為204800的共享記憶體塊。到初始化函式中檢查,並無對應的建立過程;後來比對與以前版本的區別發現之前版本有對應的建立過程,這個是由於自己注釋掉之後沒有立即重新編譯,後來忘記了這事:(

以後使用共享記憶體要多注意檢查!!!

2, 共享記憶體attach後沒有dettach,導致core。

首先,檢視程序中析構函式的彙編碼。執行gdb cache_main

disassemble main

,出現很多資訊,找到如下關注資訊:

反彙編cshmqueue,如下:

繼續反彙編~cshmqueue,如下:

發現該函式為空函式,按照**邏輯來說該函式應該去析構其成員cshm和csem物件,從而dettach共享記憶體。

進而推測該函式在鏈結成共享記憶體時被替換。

寫乙個簡單的指令碼對所有的靜態庫進行反彙編並利用cshmqueue過濾結果,發現

libcredence2.a

中有如下顯示:

發現該~cshmqueue為t,強型別函式。

再看看我們自身的析構函式,使用

nm -c cnotitysvr.o |grep cshmqueue

檢視如下: 

發現該~cshmqueue為w,弱型別函式,因為我們的析構函式是內聯函式。

也可以檢視更詳細資訊如下,確定這個析構函式是我們自身的:

注意:如果在cshmqueue實現的靜態庫中用nm是查不到內聯析構函式的,只有在使用這個類的目標檔案中可以查到。

最後,確定我們的~cshmqueue是被

libcredence2.a

中同名析構函式覆蓋,之所以編譯時候沒有警告或者錯誤提示,是因為我們的析構函式是內聯函式。

解決方法:

ø 使用命名空間對類的作用域進行限制。

ø 以後類實現時,建構函式和析構函式盡量放在原始檔中,或者用特定的名字空間進行限制。

延伸閱讀(庫文件的開發與使用)http://www.cppblog.com/amazon/archive/2010/01/12/105471.html

C C Lib庫檔案nm除錯之符號表

本文主要介紹了一下在linux下開發c c 時候,不可避免的會開發或者生成.o a so這種中間庫狀態的檔案 可能是自己寫了乙個lib讓別人呼叫,或者提供.c cpp檔案嵌入別人的makefile工程 如何檢視這些庫檔案的一些基本資訊。有時候大家編譯程式時候 確切的說是鏈結器鏈結的時候 很多錯誤例如...

Mac平台下使用nm命令檢視檔案的符號表

在mac平台下,可以使用nm命令來檢視乙個檔案的符號表資訊。nm命令列工具是附帶在xcode中的,因此在使用之前請事先安裝好xcode。nm命令的格式大致如下 nm agnoprumxjlfpa s segname sectname t format arch arch flag file 如果不帶...

檢視 o, obj檔案符號列表,強大的nm命令

nm命令可以檢視,linux以及windows下的.o obj檔案中的符號列表,其中.o檔案可以由gcc,g 編譯得到,obj由vc編譯得到。太爽了。以後遇到undefined reference錯誤的時候就可以這個命令搞定了。舉一例子,在下面的原始碼中呼叫了乙個myprint函式 include ...