Linux內核符號表

一,什麼是符號(Symbols)?
    什麼是Symbol?  其實就是kernel中的變量(Variable Name)或函數名稱(Function Name)
    這樣可以方便程序員在寫程序時可以直接參照這一份Symbol的索引文件,找到所需要的kernel信息,這一份Symbol的索引文件又稱爲kernel symbol table。
    
二,內核符號表(Kernel Symbol Table)?

2.1)定義
內核符號表,就是在內核的內部函數或變量中,可供外部引用的函數和變量的符號表。
其實說白了就是一個索引文件,它存在的目的就是讓外部軟件可以知道kernel文件內部實際分配的位置。

2.2)所在文件
編譯內核時,System.map文件用於存放內核符號表信息。
(System.map文件位於/或者/boot、/usr/src/linux/下)

2.3)文件的生成
符號表是所有內核符號及其對應地址的一個列表,隨着每次內核的編譯,就會產生一個新的對應System.map文件,當內核運行出錯時,通過System.map中的符號表解析,就可以查到一個地址值對應的變量名。System.map文件記錄了所有代碼的運行地址(所有函數和變量)。
【內核並不使用符號名。它是通過變量或函數的地址(指針)來使用變量或函數的。其實內核連System.map文件都不使用,只是生成用於調試用的。】

2.4)system.map文件的格式

   線性地址           類型        符號
ffffffff81002590       t        create_dev
ffffffff81009c00       T       show_regs

其中,類型 若是小寫字母則表示局部引用, 若是大寫字母則表示全局引用(外部). 

2.5)內核符號表的存在意義
1)把內核的符號地址,轉化爲程序猿可以看懂的符號名稱
內核符號表就是爲程序員通過符號來訪問程序體的對應地址(指針),建立了一個動態的,可變更的映射表格。
例如:
內核不會使用符號名create_dev,而會使用ffffffff81002590來引用這個變量。但程序猿們更喜歡符號名create_dev這樣直觀的名字。
所以就需要這麼一個對應關係表。這個類似於網絡裏的DNS,沒有誰願意去記那沒規律的IP地址,而記個網址就好記多了。

2)轉換之後,就可以更方便的調試內核代碼
對於系統的oop消息、或者通過gdb的調試消息,都需要根據該對照表,將內核熟悉的函數地址轉化爲用戶熟悉的函數名稱,便於用戶進行故障定位、運行監控。
而內核本身並不真正使用System.map,而只是用於做調試用。


2.6)內核符號表存儲位置

2.6.1) System.map

磁盤中真實存在的文件,存儲內核中靜態編譯的函數和變量地址,每個新編譯內核對應一個System.map文件,當klogd輸出內核消息時,會通過/boot/System.map來將函數、變量地址轉換爲名稱,方便用戶理解。該文件對應不同的編譯內核有對應的實現文件。

2.6.2 )/proc/kallsyms
內核啓動時候創建,供oops時定位錯誤,文件大小總爲0,包含當前內核導出的、可供使用的變量或者函數;它只是內核數據的簡單表示形式。

2.7)System.map 和 /proc/kallsyms 區別

二者相似點:

都是內核函數、變量的符號表,結構一致;對於可導出的內核變量、函數,其運行時在物理內存中的位置是一樣的。


二者區別
兩者側重點不同,
(1)System.map文件面向內核,對於內核中的沒有導出的變量或者函數名,比如kthread_create_list鏈表頭指針,也有其相應的內核地址,該文件一般是隻讀的、固定大小的,沒有動態添加模塊中的變量、函數名
(2)而kallsyms在內核啓動過程中創建,並實時更新,反映的是系統的當前最新情況,其內部也包含內核或者是已加載模塊導出的函數、變量名稱。
所以和System.map文件有差別,kallsyms文件動態變化,大小不固定。

總結就是:
System.map文件較單純,是在用戶一開始編譯就產生的固定文件,不會因爲任何原因更改,除非被換掉。
/proc/kallsyms是一個在啓動時由Linux kernel實時產生的文件當系統有任何變更時,它就會馬上做出修正
因爲這是動態的信息,當用戶新增或刪除一個module,都會自動做實時的修正(/proc下的都是這一類型的文件)
       
2.8)分類
Linux內核的符號表位於兩個部分。
2.8.1)首先是內核的靜態部分,也就是內核文件映像vmlinuz部分的符號表,對應於/proc/kallsyms和System.map這兩個文件。
2.8.2)還有一部分則是Linux可配置模塊部分的符號表。

2.9)形成過程

  Linux內核符號表/proc/kallsyms的形成過程

  (1)./scripts/kallsyms.c負責生成System.map
  (2)./kernel/kallsyms.c負責生成/proc/kallsyms
  (3)./scripts/kallsyms.c解析vmlinux(.tmp_vmlinux)生成kallsyms.S(.tmp_kallsyms.S),然後內核編譯過程中將kallsyms.S(內核符號表)編入內核鏡像uImage
內核啓動後./kernel/kallsyms.c解析uImage形成/proc/kallsyms

要在一個內核中啓用 kallsyms 功能,必須用進行內核配置,make menuconfig設置 CONFIG_KALLSYMS 選項爲y;如果你要在 kallsyms 中包含全部符號信息,必須設置 CONFIG_KALLSYMS_ALL 爲y。


三,導出符號表
驅動程序中,如果該驅動程序中有被其他內核代碼調用的部分,可以用EXPORT_SYMBOL導出到內核符號表中。

附:
內核符號表類型

符號類型

名稱

說明

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

符號的類型未知,或者與具體文件格式有關


   
     

參考網址:
http://www.blogbus.com/wanderer-zjhit-logs/172382425.html
http://www.360doc.com/content/14/0218/09/2613145_353425431.shtml
http://blog.chinaunix.net/uid-24148050-id-95497.html
http://book.51cto.com/art/200903/117056.htm
發佈了29 篇原創文章 · 獲贊 22 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章