转载: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