轉載:https://blog.csdn.net/wuu1010/article/details/103285396
1. 編譯內核
進入kernel 源碼目錄
1.1. 修改gcc優化等級
diff --git a/Makefile b/Makefile index d4d36c619..1047c83c6 100644 --- a/Makefile +++ b/Makefile @@ -701,11 +701,11 @@ KBUILD_CFLAGS += $(call cc-disable-warning, format-overflow) KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member) ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE -KBUILD_CFLAGS += -O2 +KBUILD_CFLAGS += -O0 else ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3 -KBUILD_CFLAGS += -O3 +KBUILD_CFLAGS += -O0 else ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE -KBUILD_CFLAGS += -Os +KBUILD_CFLAGS += -O0 endif ifdef CONFIG_CC_DISABLE_WARN_MAYBE_UNINITIALIZED
1.2. 防止modpost: Section mismatches detected.錯誤
如果此時直接執行make進行編譯,會出現modpost: Section mismatches detected.錯誤。
解決方法是修改scripts/mod/modpost.c。
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index d2a30a7b3..58e2237c2 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -2670,7 +2670,7 @@ int main(int argc, char **argv) if (dump_write) write_dump(dump_write); - if (sec_mismatch_count && sec_mismatch_fatal) + if (0 && sec_mismatch_count && sec_mismatch_fatal) fatal("modpost: Section mismatches detected.\n" "Set CONFIG_SECTION_MISMATCH_WARN_ONLY=y to allow them.\n"); for (n = 0; n < SYMBOL_HASH_SIZE; n++) {
1.3. 根據需要編譯內核
make tinyconfig ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- 2>&1 | tee -a build.log make vmlinux -j4 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- 2>&1 | tee -a build_error.log
此時編譯失敗,原因是部分函數未定義,具體原因可以參考宋寶華: 關於Linux編譯優化幾個必須掌握的姿勢
MODINFO modules.builtin.modinfo LD vmlinux mm/page-writeback.o: In function `page_index': page-writeback.c:(.text+0x21a4): undefined reference to `__page_file_index' page-writeback.c:(.text+0x21a4): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `__page_file_index' mm/truncate.o: In function `truncate_exceptional_pvec_entries': truncate.c:(.text+0x199c): undefined reference to `dax_delete_mapping_entry' truncate.c:(.text+0x199c): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `dax_delete_mapping_entry' ...... mm/rmap.o: In function `linear_page_index': rmap.c:(.text+0x3110): undefined reference to `linear_hugepage_index' Makefile:1077: recipe for target 'vmlinux' failed make: *** [vmlinux] Error 1
1.4. 修改子目錄Makefile
修改方法就是單獨為提示存在未定義符號的文件修改gcc優化等級。方法是在Makefile中添加CFLAGS_file.o += -O。
拷貝如下內容新建腳本enbale_O0.sh,使用enabel_O0.sh和上述編譯失敗的build_error.log文件,執行./enable_O0.sh build_error.log。
#!/bin/bash # make clean -j16 # make all -j4 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- 2>&1 |tee -a build_error.log MAKE_LOG="" BUILD_PATH="$(pwd -P)" if [ $# -ge 1 ]; then MAKE_LOG=$1 else echo "Usage: $(basename $0) build_error.log [build_path]" exit -1 fi if [ $# -ge 2 ]; then if [ -d $2 ]; then BUILD_PATH=$2 BUILD_PATH=${BUILD_PATH%*/} else echo "$2 No such directory" exit -1 fi fi if [ ! -f ${MAKE_LOG} ]; then echo "${MAKE_LOG}: No such file" exit -1 fi add_cflag() { make_file=$1 obj_file=$2 if [ -e ${make_file} ]; then line_no=$(grep -snv '^#' ${make_file} \ | cut -d : -f 1 | head -1) str_cflags="CFLAGS_${obj_file}" if [[ "" == "$(grep ${str_cflags}.*O ${make_file})" ]]; then cmd="${line_no}i\\${str_cflags} += -O" sed -i "${cmd}" ${make_file} echo "${make_file}: add ${str_cflags}" fi fi } vmlinux_add_cflag() { log_file=$1 filelist=$(grep -shw -B1 'undefined reference' ${log_file} \ | grep 'In function' | cut -d : -f 1 | sort -u) for f in ${filelist} do path=$(dirname ${f}) obj_file=$(basename ${f}) make_file=${path}/Makefile add_cflag ${make_file} ${obj_file} done } process_one() { # ERROR: "alloc_test_extent_buffer" [fs/btrfs/btrfs.ko] undefined! str=$1 symbol=$(echo ${str} | awk '{print $2}') symbol=${symbol:1:0-1} # 刪除 "" ko=$(echo ${str} | awk '{print $3}') ko=${ko:1:0-1} # 刪除 [] path=$(dirname ${ko}) filelist=$(grep -rl ${symbol} ${BUILD_PATH}/${path}/*.o) echo $filelist make_file=${path}/Makefile for f in ${filelist} do f=${f#${BUILD_PATH}/} # 從左邊刪除 "${BUILD_PATH}/" obj=$(basename ${f}) add_cflag ${make_file} ${obj} done } module_add_cflag() { log_file=$1 IFS=$'\n' # 按行遍歷 str_list=$(grep -sh "^ERROR:.*undefined!" ${log_file} | sort -u) for str in ${str_list} do process_one ${str} done } vmlinux_add_cflag ${MAKE_LOG} module_add_cflag ${MAKE_LOG}
執行結束后,子目錄Makefile改動如下:
diff --git a/mm/Makefile b/mm/Makefile index d99684669..52a1962ea 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -2,6 +2,14 @@ # # Makefile for the linux memory manager. # +CFLAGS_truncate.o += -O +CFLAGS_rmap.o += -O +CFLAGS_page-writeback.o += -O +CFLAGS_mremap.o += -O +CFLAGS_mprotect.o += -O +CFLAGS_mincore.o += -O +CFLAGS_memory.o += -O +CFLAGS_gup.o += -O KASAN_SANITIZE_slab_common.o := n KASAN_SANITIZE_slab.o := n
1.5. 重新執行編譯
make clean make vmlinux -j4 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- 2>&1 | tee -a build_ok.log
此時可正常編譯通過。
MODINFO modules.builtin.modinfo
LD vmlinux
SORTEX vmlinux
SYSMAP System.map
2. 參考資料
宋寶華: 關於Linux編譯優化幾個必須掌握的姿勢
runninglinuxkernel_4
————————————————
版權聲明:本文為CSDN博主「wuu1010」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/wuu1010/java/article/details/103285396
