一:分析linux内核移植中vmlinux可执行文件是如何生成的?
1:进入内核源码顶层目录下打开Makefile文件,搜索vmlinux
这里构建vmlinux的命令使用了makefile的内置函数call。这是一个比较特殊的内置函数,make使用它来引用用户自己定义的带有参数的函数。if_changed是kbuild定义的一个函数,这里通过call引用这个函数,传递的实参是link-vmlinux。
2:进入内核源码scripts/Kbuild.include目录下,搜索:if_changed
218 if_changed = $(if $(newer-prereqs)$(cmd-check),
219 $(cmd);
183 cmd = @set -e; $(echo-cmd) $($(quiet)redirect) $(cmd_$(1))
@set -e:在执行的时候有错误就直接退出
$(cmd_$(1)) = cmd_uimage
3:实参:link-vmlinux
4:通过echo打印信息,进入内核源码 /scripts/link-vmlinux.sh文件中:
vmlinux_link()
{
local lds="${objtree}/${KBUILD_LDS}"
local output=${1}
local objects
local strip_debug
info LD ${output}
# skip output file argument
shift
# The kallsyms linking does not need debug symbols included.
if [ "$output" != "${output#.tmp_vmlinux.kallsyms}" ] ; then
strip_debug=-Wl,--strip-debug
fi
if [ "${SRCARCH}" != "um" ]; then
objects="--whole-archive \
${KBUILD_VMLINUX_OBJS} \
--no-whole-archive \
--start-group \
${KBUILD_VMLINUX_LIBS} \
--end-group \
${@}"
${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} \
${strip_debug#-Wl,} \
-o ${output} \
-T ${lds} ${objects}
else
objects="-Wl,--whole-archive \
${KBUILD_VMLINUX_OBJS} \
-Wl,--no-whole-archive \
-Wl,--start-group \
${KBUILD_VMLINUX_LIBS} \
-Wl,--end-group \
${@}"
${CC} ${CFLAGS_vmlinux} \
${strip_debug} \
-o ${output} \
-Wl,-T,${lds} \
${objects} \
-lutil -lrt -lpthread
rm -f linux
fi
}
二:整理内核编译流程:uImage/zImage/Image/vmlinx之间关系
1: 顶层目录下的vmlinux 是编译出来的最原始的内核文件,是未压缩的,vmlinux通过objcopy格式化转换为Image。
60 $(obj)/Image: vmlinux FORCE
61 $(call if_changed,objcopy) ----->调用cmd_objcopy
2:将Image镜像文件经过gzip压缩生成rch/arm/boot/compressed/vmlinx镜像文件
178 $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.o \
179 $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) \
180 $(bswapsdi2) $(efi-obj-y) FORCE
182 $(call if_changed,ld) ---->cmd_ld
arch/arm/boot/vmlinux.lds head.o piggy.o debug.o lib1funcs.o lib1funcs.S ashldi3.S
bswapsdi2.S hyp-stub.S bswapsdi2.o lib.a
arm-linux-gnueabihf-ld vmlinux.lds head.o piggy.o debug.o lib1funcs.o lib1funcs.S
ashldi3.S bswapsdi2.S hyp-stub.S bswapsdi2.o lib.a -o vmlinux
185 $(obj)/piggy_data: $(obj)/../Image FORCE
186 $(call if_changed,$(gzip)) ----->调用cmd_gzip
188 $(obj)/piggy.o: $(obj)/piggy_data
3:vmlinux通过格式化转换为zImage文件
66 $(obj)/zImage: $(obj)/compressed/vmlinux FORCE 67 $(call if_changed,objcopy) ---->cmd_objcopy
267 cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
arm-linux-gnueabihf-objcopy $(obj)/compressed/vmlinux zImage
4:zImage使用mkimage工具得到uImage,uImage在zImage前添加64字节头部信息
89 $(obj)/uImage: $(obj)/zImage FORCE
90 @$(check_for_multiple_loadaddr) ------->检测uImage镜像文件的入口地址
91 $(call if_changed,uimage)------->call:调用if_changed命令,makefile中固定的用法
总结:
vmlinx--->objcopy--->Image--->gzip--->arch/arm/boot/compressed/vmlinx--->objcopy--->zImage--->mkimage--->uImage