2011-12-19 92 views
28

當編譯一個內核模塊時,我得到了一個WARNING和一個註釋來添加一個編譯選項,CONFIG_DEBUG_SECTION_MISMATCH = y。它給我更詳細的信息有關的問題:什麼是內核部分不匹配?

WARNING: \**\*path to module\***(.text+0x8d2): Section mismatch in reference from the function Pch_Spi_Enable_Bios_Wr() to the variable .devinit.data:ich9_pci_tbl.22939 
The function Pch_Spi_Enable_Bios_Wr() references 
the variable __devinitdata ich9_pci_tbl.22939. 
This is often because Pch_Spi_Enable_Bios_Wr lacks a __devinitdata 
annotation or the annotation of ich9_pci_tbl.22939 is wrong. 

我不能準確地找到內核部分不匹配是什麼,更不用說如何去修復它。

回答

35

這意味着具有給定生命週期的部分中的函數引用了具有不同生命週期的部分中的某個東西。

當內核二進制文件被鏈接時,代碼和數據的不同部分被分成不同的部分。其中一些部分始終保持加載狀態,但其他部分在不再需要時會被刪除(例如啓動過程中只需要啓動的部分可以在啓動完成後釋放 - 這樣可以節省內存)。

如果持久部分中的某個函數引用其中一個可廢棄部分中的數據,則存在一個問題 - 它可能試圖在數據已經釋放時訪問該數據,從而導致各種運行時的問題。

這不是一個警告,你會解決自己,除非你寫了代碼或非常熟悉它。它通過正確註釋函數(或其引用的數據)得到修復,以便它進入正確的部分。正確的修復只能通過詳細瞭解該內核部分來確定。


對於這些部分和註釋的列表,請參閱include/linux/init.h頭在你的內核源代碼樹:

/* These macros are used to mark some functions or 
* initialized data (doesn't apply to uninitialized data) 
* as `initialization' functions. The kernel can take this 
* as hint that the function is used only during the initialization 
* phase and free up used memory resources after 
* 
* Usage: 
* For functions: 
* 
* You should add __init immediately before the function name, like: 
* 
* static void __init initme(int x, int y) 
* { 
* extern int z; z = x * y; 
* } 
* 
* If the function has a prototype somewhere, you can also add 
* __init between closing brace of the prototype and semicolon: 
* 
* extern int initialize_foobar_device(int, int, int) __init; 
* 
* For initialized data: 
* You should insert __initdata between the variable name and equal 
* sign followed by value, e.g.: 
* 
* static int init_variable __initdata = 0; 
* static const char linux_logo[] __initconst = { 0x32, 0x36, ... }; 
* 
* Don't forget to initialize data not at file scope, i.e. within a function, 
* as gcc otherwise puts the data into the bss section and not into the init 
* section. 
* 
* Also note, that this data cannot be "const". 
*/ 

/* These are for everybody (although not all archs will actually 
    discard it in modules) */ 
#define __init  __section(.init.text) __cold notrace 
#define __initdata __section(.init.data) 
#define __initconst __section(.init.rodata) 
#define __exitdata __section(.exit.data) 
#define __exit_call __used __section(.exitcall.exit) 

其他跟隨,與更多的評論和解釋。

又見了CONFIG_DEBUG_SECTION_MISMATCH的Kconfig符號的說明文字:

的部分錯配分析檢查是否有非法從一個部分到另一個部分
引用。
Linux將在鏈接期間或運行期間刪除某些部分
以及以前在這些部分中的任何代碼/數據的使用將最有可能導致oops的

在代碼函數和變量中註釋爲
__init,__devinit等(請參閱include/linux/init.h中的完整列表)
這導致代碼/數據被放置在特定節中。
的部分錯配分析是一個完整的
內核編譯後一直在做,但啓用這個選項將除了
做到以下幾點:

  • -fno內聯函數稱爲一次添加的選項GCC
    當在非初始化函數內嵌入函數註釋__init時,我們將失去區域信息,因此分析不會捕獲非法引用。
    這個選項告訴gcc內聯更少,但也會導致更大的內核產生
  • 運行部分錯配分析爲每個模塊/內置in.o
    當我們在vmlinux.o運行部分錯配分析,我們
    輸在哪裏不匹配是
    介紹valueble信息。
    運行每個模塊/內置.o文件的分析
    會告訴哪裏的不匹配發生得更接近
    源。缺點是我們會報告相同的
    不匹配至少兩次。
  • 啓用來自modpost的詳細報告以幫助解決
    報告的部分不匹配。