【技巧】一種提高 [ 定位Linux核心編譯錯誤 ] 效率的方法
前言:在編譯一些非標準linux核心時,常會出現一些錯誤導致編譯中止。這其中的大部分都能通過根據編譯器報出的錯誤定位來查閱原始碼、找到相關的依賴配置,然後修正配置狀態來解決。但也有時候從依賴邏輯中無法發現問題所在,這就不得不把整個核心配置都倒騰一遍,這將花費大量的時間精力。本文便是在倒騰過程中發現的一些能夠提高效率的小技巧的總結。
關鍵詞:linux,核心編譯,錯誤定位
適用場景:
- 有一份能夠正常編譯不報錯的配置檔案;
- 通過查閱原始碼實在找不到造成問題的核心配置項;
- 能夠確定錯誤是由核心配置引起的,而不是其它諸如環境配置等問題導致的。
(以上條件滿足越多越合適)
1 簡單認識兩個核心原始碼裡的檔案
-
include/generated/autoconf.h:
該檔案由.confg檔案轉換而成。在使用make menuconfig修改配置後.config檔案會被修改,但僅僅這樣是無法影響到核心原始碼的。於是在核心編譯的時候會將.config檔案中的配置項轉換為autoconf.h檔案裡對應的巨集定義,如此便可供核心裡的C原始碼使用。
-
scripts/Kbuild.include:
該檔案被頂層的Makefile引用,在編譯時會被執行。其中有幾條命令控制著編譯的具體命令,但是命令前加了@
符合,導致編譯命令本身被遮蔽,只顯示結果。將@
符合去掉,就可以顯示命令本身的內容。
頂層Makefile對Kbuild.include檔案的引用:
Kbuild.include檔案:
2 基本思路
- 對比正常編譯的autoconf.h和編譯出錯的autoconf.h檔案,找出差異項,將搜尋範圍縮小至差異項;
- 參照差異項使用二分法批量修改autoconf.h檔案,可在較少次數內定位到目標配置項;
- 去掉Kbuild.include檔案中
@set -e
前的@
,顯示編譯命令的具體內容,由此可獲得導致錯誤的命令; - 直接使用導致錯誤的命令來編譯驗證修改後的配置,可縮短驗證過程的時間。
3 示例
-
下圖是一個is deprecated錯誤,在將該錯誤程式碼處相關的幾個檔案來來回回看了幾遍後,依然沒有找出能夠修正錯誤的配置項:
-
修改scripts/Kbuild.include檔案,釋放出命令的具體內容:
-
再次編譯,可以看到編譯的具體命令了:
-
試一下,確實是這條命令報的錯:
-
將autoconf.h檔案備份一份,以防後續修改出錯;然後就可以比較編譯正常的autocof.h檔案與當前導致錯誤的autoconf.h檔案:
-
總共約2000條配置,左邊是可以正常編譯的,右邊是有問題的:(實際上如果用beyond compare來比較可以只顯示差異行,只需要從1000多條差異項中篩選即可,奈何這裡用的diffuse工具無法只顯示差異項)
-
使用二分法篩選,2000條理論上篩選11遍即可找出導致錯誤的配置;實際為了保險起見可能需要把二分法篩選淘汰的那一半也驗證一下,因為要防止導致錯誤的配置項不止一條的情況:
先使用可正常編譯的配置檔案的前1000項替換有問題的配置檔案的對應配置:
雖然報了其它錯誤,但沒有報那個is deprecated的錯誤。 -
可以判斷錯誤配置項在前1000項裡,還是使用剩餘的後1000多項驗證一下:
也報了一堆其它錯誤,但同時也出現了之前的錯誤,說明後面的1000多項並不影響這個錯誤,驗證了之前的判斷。
(後面是繁瑣的除錯過程)
-
這時範圍縮小到前1000項,再分:
前512項:
後半部分:
前512項沒出現,後半部分出現了,可以再把範圍縮小到前512項。 -
前244項:
後半部分:
前244項依然出現,後半部分正常,可以判斷在後半部分。 -
245-384項:出現目標錯誤
後半部分(385-512):沒出現
可以判斷在後半部分。 -
385-455:
456-512:
兩個都出現錯誤?後來反覆驗證了幾遍確實是這樣。 -
在455項和456項之間,有一個配置項左邊能正常編譯的檔案裡沒有,但是右邊的檔案有,所以剛才兩次覆蓋恰好都沒有覆蓋到它,猜測這個可能就是要找的配置項了:
-
去掉該配置項:
編譯正常,沒想到提前解決了。 -
直接在make menuconfig裡關閉CONFIG_ENABLE_WARN_DEPRECATED配置項,然後make編譯:
又報了新的錯誤,但至少那個is deprecated的錯誤是解決了。
最後原因竟然是不能開啟deprecated警告,這就是非標準核心的魅力吧aaaa。
-END-