核心符號表問題
有兩個模組,mod1和mod2。
在mod1中定義了func()函式,並且經export_symbol()匯出。
在mod2中extern func(),呼叫func()。
編譯模組mod2,成功。
載入mod2時,輸出:
insmod: error inserting 'mod2.ko': -1 invalid parameters
dmesg檢視:
mod2: no symbol version for func
mod2: unknown symbol func (err -22)
kernel symbol table,核心符號表。
linux核心的符號表位於兩個部分:
靜態的符號表,即核心映像vmlinuz的符號表(system.map)
動態的符號表,即核心模組的符號表(/proc/kallsyms)
符號標誌
t external text
t local text
d external initialized data
d local initialized data
b external zeroed data
b local zeroed data
a external absolute
a local absolute
u external undefined
g external small initialized data
g local small initialized data
i init section
s external small zeroed data
s local small zeroed data
r external read only
r local read only
c common
e small common
我們可以看到,大寫標誌都是全域性的、可被外部引用的,而小寫標誌都是區域性的、不能被外部引用的。
可以用nm命令檢視可執行檔案的符號表(nm - list symbols from object files)。
insmod使用公共核心符號表來解析模組中未定義的符號。公共核心符號表中包含了所有的全域性函式和全域性
變數的位址。當模組被裝入核心後,它所匯出的任何核心符號都會變成核心符號表的一部分。
export_symbol(name); // 所有模組可見
export_symbol_gpl(nae); // 含有gpl許可證模組可見
了解了什麼是核心符號表之後,我們回到之前的問題。
我們檢視/proc/kallsyms,發現mod1的func函式的標誌為t,而此標誌表示函式是區域性的。
此問題是核心2.6.26之後版本的bug,並且不會被修復。
解決辦法有幾種:
(1)把mod1的module.symvers放到mod2中,這樣在編譯mod2時符號資訊會自動鏈結進去。
(2)在mod2的makefile中新增符號資訊
echo '0x01873e3f func mod1 export_symbol_gpl' > module.symvers
這樣mod2在編譯時就知道mod1中func符號的位址。
q:這個問題是由什麼引起的呢?
a:生成mod2的時候不知道mod1中func的校驗碼,mod2載入時檢查校驗碼出錯。
在核心主線**樹的乙個提交修改了核心掛載模組時的函式版本校驗機制,使得在掛載模組時候對於編譯
時個別函式沒有確定crc校驗值無法通過check_version函式檢查。
這是核心有意要禁止存在個別無版本校驗資訊的函式的模組掛載。
[1].
核心符號表
linux核心為了實現模組化,需要提供乙個公共的核心符號表,它包含了所有的全域性核心項 函式以及變數 的位址。當模組載入到核心中後,它所匯出的任何符號都將成為核心公共符號表的一部分。核心模組只需要實現自己的功能而無需匯出任何符號,但這樣其他模組將無法使用該模組的功能,乙個新的模組可以使用自己其他模組...
關於核心符號表
在編寫驅動的過程中,常會使用到export symbol巨集來將定義的函式名匯出到核心符號表。以前只是簡單的知道如果乙個模組中定義的函式要提供給其他模組呼叫,就必須進行匯出。這段時間在編譯單個模組的時候,因為沒編譯成功造成了函式沒定義而報警的情況,因此讓我有乙個機會對核心符號表的問題進行了乙個深入的...
linux核心符號表
所謂核心符號表就是在核心內部函式或變數中可供外部引用的函式和變數的符號表。在 2.6 核心下,使用以下命令可以看到核心符號表 引用 beyes linux beyes cat proc kallsyms more c0100000 t text c0100000 t startup 32 c0100...