Linux System.map檔案
當執行GNU連結器gld(ld)時若使用了"-M"選項,或者使用nm命令,則會在標準輸出裝置(通常是螢幕)上打印出連結映像(link map)資訊,即是指由連結程式產生的目標程式記憶體地址映像資訊。其中列出了程式段裝入到記憶體中的位置資訊。具體來講有如下資訊:
目標檔案及符號資訊對映到記憶體中的位置。
公共符號如何放置。
連結中包含的所有檔案成員及其引用的符號。
通常我們會把傳送到標準輸出裝置的連結映像資訊重定向到一個檔案中(例如System.map)。在編譯核心時,linux/Makefile檔案產生的System.map檔案就用於存放核心符號表資訊。符號表是所有核心符號及其對應地址的一個列表,當然也包括上面說明的_etext、_edata和_end等符號的地址資訊。隨著每次核心的編譯,就會產生一個新的對應System.map檔案。當核心執行出錯時,通過System.map檔案中的符號表解析,就可以查到一個地址值對應的變數名,或反之。
利用System.map符號表檔案,在核心或相關程式出錯時,就可以獲得我們比較容易識別的資訊。符號表的樣例如下所示:
c03441a0 B dmi_broken c03441a4 B is_sony_vaio_laptop c03441c0 b dmi_ident c0344200 b pci_bios_present c0344204 b pirq_table |
其中每行說明一個符號,第1欄指明符號值(地址);第2欄是符號型別,指明符號位於目標檔案的哪個區(sections)或其屬性;第3欄是對應的符號名稱。
第2欄中的符號型別指示符通常有表3-5所示的幾種,另外還有一些與採用的目標檔案格式相關。如果符號型別是小寫字元,則說明符號是區域性的;如果是大寫字元,則說明符號是全域性的(外部的)。參見檔案include/a.out.h中nlist{}結構n_type欄位的定義(第110~185行)。
表3-5 目標檔案符號列表檔案中的符號型別
符號型別 |
名稱 |
說明 |
A |
Absolute |
符號的值是絕對值,並且在進一步連結過程中不會被改變 |
B |
BSS |
符號在未初始化資料區或區(section)中,即在BSS段中 |
C |
Common |
符號是公共的。公共符號是未初始化的資料。在連結時,多個公共符號可能具有同一名稱。如果該符號定義在其他地方,則公共符號被看作是未定義的引用 |
D |
Data |
符號在已初始化資料區中 |
G |
Global |
符號是在小物件已初始化資料區中的符號。某些目標檔案的格式允許對小資料物件(例如一個全域性整型變數)可進行更有效的訪問 |
I |
Inderect |
符號是對另一個符號的間接引用 |
N |
Debugging |
符號是一個除錯符號 |
R |
Read only |
符號在一個只讀資料區中 |
S |
Small |
符號是小物件未初始化資料區中的符號 |
T |
Text |
符號是程式碼區中的符號 |
U |
Undefined |
符號是外部的,並且其值為0(未定義) |
- |
Stabs |
符號是a.out目標檔案中的一個stab符號,用於儲存除錯資訊 |
? |
Unknown |
符號的型別未知,或者與具體檔案格式有關 |
可以看出名稱為dmi_broken的變數位於核心地址0xc03441a0處。
System.map位於使用它的軟體(例如核心日誌記錄後臺程式klogd)能夠尋找到的地方。在系統啟動時,如果沒有以一個引數的形式為klogd給出System.map的位置,則klogd將會在三個地方搜尋System.map。依次為:
/boot/System.map /System.map /usr/src/linux/System.map |
儘管核心本身實際上不使用System.map,但其他程式,像klogd、lsof、ps以及dosemu等許多軟體都需要有一個正確的System.map檔案。利用該檔案,這些程式就可以根據已知的記憶體地址查找出對應的核心變數名稱,便於對核心的除錯工作。