进入kernel 源码目录
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
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++) {
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
修改方法就是单独为提示存在未定义符号的文件修改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
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