1.分析vmlinux可执行文件是如何生成的?
1.在内核源码顶层目录下打开Makefile文件,搜索vmlinux,找到以下代码,可从中得知vmlinux的生成依赖于vmlinux-deps
1178 vmlinux: scripts/link-vmlinux.sh autoksyms_recursive $(vmlinux-deps) FORCE
1179 +$(call if_changed,link-vmlinux)
2.在内核源码顶层目录下打开Makefile文件,搜索vmlinux-deps
1147 vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_OBJS) $(KBUILD_VMLINUX_LIBS)
3.找到vmlinux-deps的三个依赖,其中export KBUILD_LDS是链接文件,KBUILD_VMLINUX_LIBS := $(filter-out %/, $(libs-y)) 跟库有关,所以我们可以重点关注KBUILD_VMLINUX_OBJS
1132 KBUILD_VMLINUX_OBJS := $(head-y) $(patsubst %/,%/built-in.a, $(core-y))
1136 KBUILD_VMLINUX_LIBS := $(filter-out %/, $(libs-y))
1143 export KBUILD_LDS := arch/$(SRCARCH)/kernel/vmlinux.lds
4.通过打印KBUILD_VMLINUX_OBJS信息,会发现KBUILD_VMLINUX_OBJS是由各个子目录下的built-in.a和arch/arm/kernel/head.o组成
arch/arm/kernel/head.o init/built-in.a usr/built-in.a arch/arm/built-in.a arch/arm/mach-aspeed/built-in.a arch/arm/mach-milbeaut/built-in.a arch/arm/mach-stm32/built-in.a kernel/built-in.a certs/built-in.a mm/built-in.a fs/built-in.a ipc/built-in.a security/built-in.a crypto/built-in.a block/built-in.a arch/arm/lib/built-in.a lib/built-in.a arch/arm/lib/lib.a lib/lib.a drivers/built-in.a sound/built-in.a samples/built-in.a net/built-in.a virt/built-in.a
5.打开scripts/Makefile.build,我们可以发现built-in.a的生成
#
# Rule to compile a set of .o files into one .a file (without symbol table)
#
quiet_cmd_ar_builtin = AR $@
cmd_ar_builtin = rm -f $@; $(AR) cDPrST $@ $(real-prereqs)
$(obj)/built-in.a: $(real-obj-y) FORCE
$(call if_changed,ar_builtin)
2.整理内核编译流程:uImage/zImage/Image/vmlinx之间关系
uImage镜像文件的生成
1.在内核源码顶层目录下打开Makefile文件,搜索uImage,发现没有目标,猜测在Makefile中包含其他路径的Makefile文件
596 include arch/$(SRCARCH)/Makefile = arch/arm/Makefile
2.进入arch/arm目录下,打开Makefile文件,搜索uImage,打印每个变量信息
323 $(BOOT_TARGETS): vmlinux
324 $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
打印信息内容:
@
-f ./scripts/Makefile.build obj
arch/arm/boot
uImage
make -f ./scripts/Makefile.build obj=arch/arm/boot MACHINE=arch/arm/boot/uImage
3.进入内核源码/scripts/Makefile.build文件,搜索uImage
6 src := $(obj)=arch/arm/boot
42 kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) kbuild-dir :=$(src)
43 kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
kbuild-file := $(kbuild-dir)/Kbuild和$(kbuild-dir)/Makefile
44 include $(kbuild-file) :将 arch/arm/boot/Makefile和当前的Makfile.build文件合并
4.进入内核源码arch/arm/boot/,打开Makefile文件,搜索uImage
89 $(obj)/uImage: $(obj)/zImage FORCE
90 @$(check_for_multiple_loadaddr) ------->检测uImage镜像文件的入口地址
91 $(call if_changed,uimage)------->call:调用if_changed命令,makefile中固定的用法
5. 入内核源码arch/arm/boot/,打开Makefile文件,指定LOADADDR这个变量的信息,将加载的地址赋值
70 LOADADDR = 0xc2000000 -------> 需要添加内容
71 ifneq ($(LOADADDR),)
72 UIMAGE_LOADADDR=$(LOADADDR)
6.进入内核源码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
7. 进入内核源码scripts/Makefile.lib目录下,搜索cmd_uimage
398 cmd_uimage = $(BASH) $(MKIMAGE) -A $(UIMAGE_ARCH) -O linux \
399 -C $(UIMAGE_COMPRESSION) $(UIMAGE_OPTS-y) \
400 -T $(UIMAGE_TYPE) \
401 -a $(UIMAGE_LOADADDR) -e $(UIMAGE_ENTRYADDR) \
402 -n $(UIMAGE_NAME) -d $< $@
解析:
385 MKIMAGE := ./scripts/mkuboot.sh
cmd_uimage = /usr/bin/mkimage -A arm -O linux -C gzip -T kernel -n uImage -d zImage
7.uImage和zImage之间关系?
1)uImage使用在zImage使用mkimage工具得到的,uImage在zImage前添加64字节头部信息
2)每次编译打印信息的内容就是编译到uImage中内容
Image Name: Linux-5.10.61
Created: Wed Mar 8 16:15:39 2023
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 7172080 Bytes = 7003.98 KiB = 6.84 MiB
Load Address: c2000000
Entry Point: c2000000
zImage镜像文件
1.进入内核源码arch/arm/boot/,打开Makefile文件,搜索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
2.zImage和arch/arm/boot/compressed/vmlinux关系?
zImage是通过vmlinux格式化转换为的文件
compressed/vmlinux文件
1.进入内核源码arch/arm/boot/,打开Makefile文件,搜索vmlinux
63 $(obj)/compressed/vmlinux: $(obj)/Image FORCE
64 $(Q) $(MAKE) $(build)=$(obj)/compressed $@
执行命令:make -f ./scripts/Makefile.build obj=arch/arm/boot/compressed arch/arm/boot/compressed/vmlinux
2.进入内核源码arch/arm/boot/compressed,打开Makefile文件,搜索vmlinux
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.进入内核源码scripts/Makefile.lib目录下,搜索cmd_gzip
cmd_gzip = $(KGZIP) -n -f -9 > $@ = gzip Image > vmlinx
4.rch/arm/boot/compressedvmlinux文件和Image之间关系
将Image镜像文件经过gzip压缩生成rch/arm/boot/compressed/vmlinx镜像文件
Image镜像文件
1.进入内核源码arch/arm/boot/compressed,打开Makefile文件,搜索Image
60 $(obj)/Image: vmlinux FORCE
61 $(call if_changed,objcopy) ----->调用cmd_objcopy
2.Image和内核顶层目录下vmlinx关系
vmlinux通过objcopy格式化转换为Image