grub源码分析之kernel.img-Makefile

转载于 “https://blog.csdn.net/conansonic/article/details/78735401”

《grub源码分析之boot.img-Makefile》https://blog.csdn.net/baidu_31504167/article/details/89136605

kernel.img生成过程总结如下:

【config配置如下】

../configure --target=x86_64 --with-platform=pc --prefix=xxxx/grub2.02-pc

第一步:将symlist.c编译成kernel_exec-symlist.o,将kern/i386/pc/startup.S、kern/i386/pc/init.c、kern/i386/pc/mmap.c、term/i386/pc/console.c、kern/i386/dl.c、kern/i386/tsc.c、kern/i386/tsc_pit.c、kern/compiler-rt.c、kern/mm.c、kern/time.c、kern/generic/millisleep.c、kern/command.c、kern/corecmd.c、kern/device.c、kern/disk.c、kern/dl.c、kern/env.c、kern/err.c、kern/file.c、kern/fs.c、kern/list.c、kern/main.c、kern/misc.c、kern/parser.c、kern/partition.c、kern/rescue_parser.c、kern/rescue_reader.c、kern/term.c最终编译成kern/i386/pc/kernel_exec-startup.o。
【编译log如下】

gcc -DHAVE_CONFIG_H -I. -I../../grub-core -I..  -Wall -W  -DGRUB_MACHINE_PCBIOS=1 -DGRUB_MACHINE=I386_PC -m32 -nostdinc -isystem /usr/lib/gcc/x86_64-linux-gnu/4.8/include -I../../include -I../include -DGRUB_FILE=\"kern/i386/pc/startup.S\" -I. -I../../grub-core -I.. -I../.. -I../../include -I../include -I../../grub-core/lib/libgcrypt-grub/src/   -DGRUB_KERNEL=1  -D_FILE_OFFSET_BITS=64 -g  -m32 -msoft-float -DGRUB_FILE=\"kern/i386/pc/startup.S\" -I. -I../../grub-core -I.. -I../.. -I../../include -I../include -I../../grub-core/lib/libgcrypt-grub/src/ -DASM_FILE=1     -MT kern/i386/pc/kernel_exec-startup.o -MD -MP -MF kern/i386/pc/.deps-core/kernel_exec-startup.Tpo -c -o kern/i386/pc/kernel_exec-startup.o \`test -f 'kern/i386/pc/startup.S' || echo '../../grub-core/'`kern/i386/pc/startup.S

第二步:将第一步中编译完成的kernel_exec-symlist.o和kernel_exec-startup.o链接成kernel.exec,其中将代码段的地址设置为0x9000。
【编译log如下】

gcc -Os -Wall -W -Wshadow -Wpointer-arith -Wundef -Wchar-subscripts -Wcomment -Wdeprecated-declarations -Wdisabled-optimization -Wdiv-by-zero -Wfloat-equal -Wformat-extra-args -Wformat-security -Wformat-y2k -Wimplicit -Wimplicit-function-declaration -Wimplicit-int -Wmain -Wmissing-braces -Wmissing-format-attribute -Wmultichar -Wparentheses -Wreturn-type -Wsequence-point -Wshadow -Wsign-compare -Wswitch -Wtrigraphs -Wunknown-pragmas -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-value  -Wunused-variable -Wwrite-strings -Wnested-externs -Wstrict-prototypes -g -Wredundant-decls -Wmissing-prototypes -Wmissing-declarations  -Wextra -Wattributes -Wendif-labels -Winit-self -Wint-to-pointer-cast -Winvalid-pch -Wmissing-field-initializers -Wnonnull -Woverflow -Wvla -Wpointer-to-int-cast -Wstrict-aliasing -Wvariadic-macros -Wvolatile-register-var -Wpointer-sign -Wmissing-include-dirs -Wmissing-prototypes -Wmissing-declarations -Wformat=2 -march=i386 -m32 -mrtd -mregparm=3 -falign-jumps=1 -falign-loops=1 -falign-functions=1 -freg-struct-return -mno-mmx -mno-sse -mno-sse2 -mno-sse3 -mno-3dnow -msoft-float -fno-dwarf2-cfi-asm -mno-stack-arg-probe -fno-asynchronous-unwind-tables -fno-unwind-tables -Qn -fno-stack-protector -Wtrampolines -Werror   -ffreestanding   -m32 -Wl,-melf_i386 -Wl,--build-id=none  -nostdlib -Wl,-N -Wl,-N -Wl,**-Ttext,0x9000**   -o **kernel.exec** kern/i386/pc/kernel_exec-startup.o kern/i386/pc/kernel_exec-init.o kern/i386/pc/kernel_exec-mmap.o term/i386/pc/kernel_exec-console.o kern/i386/kernel_exec-dl.o kern/i386/kernel_exec-tsc.o kern/i386/kernel_exec-tsc_pit.o kern/kernel_exec-compiler-rt.o kern/kernel_exec-mm.o kern/kernel_exec-time.o kern/generic/kernel_exec-millisleep.o kern/kernel_exec-command.o kern/kernel_exec-corecmd.o kern/kernel_exec-device.o kern/kernel_exec-disk.o kern/kernel_exec-dl.o kern/kernel_exec-env.o kern/kernel_exec-err.o kern/kernel_exec-file.o kern/kernel_exec-fs.o kern/kernel_exec-list.o kern/kernel_exec-main.o kern/kernel_exec-misc.o kern/kernel_exec-parser.o kern/kernel_exec-partition.o kern/kernel_exec-rescue_parser.o kern/kernel_exec-rescue_reader.o kern/kernel_exec-term.o kernel_exec-symlist.o 

第三步:通过strip命令将链接成的kernel.exec瘦身,删除一些不必要的段,最终生成kernel.img文件。
【编译log如下】

if test x0 = x1; then   strip -S -x  -o kernel.img.bin kernel.exec;    -felf32 -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -ed2022 -ed2016 -wd1106 -nu -nd kernel.img.bin kernel.img;   rm -f kernel.img.bin;    elif test ! -z ''; then      strip  -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags -R .ARM.exidx  -o kernel.img.bin kernel.exec &&       kernel.img.bin kernel.img || (rm -f kernel.img; rm -f kernel.img.bin; exit 1);      rm -f kernel.img.bin; else strip  -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags -R .ARM.exidx  -o kernel.img kernel.exec; fi

=================================================

第一部分-编译kernel_exec_OBJECTS
kernel_exec_OBJECTS目标的主要作用是将各个c文件编译成kernel_exec-startup.o,下面来看。
boot_image_OBJECTS
grub-core/Makefile

kernel_exec_OBJECTS = $(am_kernel_exec_OBJECTS) \
    $(nodist_kernel_exec_OBJECTS)

首先看nodist_kernel_exec_OBJECTS的定义,

nodist_kernel_exec_OBJECTS = kernel_exec-symlist.$(OBJEXT)

OBJEXT定义为o,因此下面看目标kernel_exec-symlist.o。

kernel_exec-symlist.o
grub-core/Makefile

kernel_exec-symlist.o: symlist.c
    $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(kernel_exec_CPPFLAGS) $(CPPFLAGS) $(kernel_exec_CFLAGS) $(CFLAGS) -MT kernel_exec-symlist.o -MD -MP -MF $(DEPDIR)/kernel_exec-symlist.Tpo -c -o kernel_exec-symlist.o `test -f 'symlist.c' || echo '$(srcdir)/'`symlist.c
    $(AM_V_at)$(am__mv) $(DEPDIR)/kernel_exec-symlist.Tpo $(DEPDIR)/kernel_exec-symlist.Po

kernel_exec-symlist.o由symlist.c编译而成,大部分变量的定义在《grub源码分析之boot.img-Makefile》中都有提及。下面只看一些新的变量。

kernel_exec_CPPFLAGS = $(AM_CPPFLAGS) $(CPPFLAGS_KERNEL) 
CPPFLAGS_KERNEL = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) -DGRUB_KERNEL=1

CPPFLAGS_CPU和CPPFLAGS_PLATFORM都为空定义。因此CPPFLAGS_KERNEL变量最终只是定义宏GRUB_KERNEL为1 。

回到目标kernel_exec-symlist.o中。

kernel_exec_CFLAGS = $(AM_CFLAGS) $(CFLAGS_KERNEL) 

AM_CFLAGS变量的最终定义为TARGET_CFLAGS,如下所示,

TARGET_CFLAGS =  -Os -Wall -W -Wshadow -Wpointer-arith -Wundef -Wchar-subscripts -Wcomment -Wdeprecated-declarations -Wdisabled-optimization -Wdiv-by-zero -Wfloat-equal -Wformat-extra-args -Wformat-security -Wformat-y2k -Wimplicit -Wimplicit-function-declaration -Wimplicit-int -Wmain -Wmissing-braces -Wmissing-format-attribute -Wmultichar -Wparentheses -Wreturn-type -Wsequence-point -Wshadow -Wsign-compare -Wswitch -Wtrigraphs -Wunknown-pragmas -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-value  -Wunused-variable -Wwrite-strings -Wnested-externs -Wstrict-prototypes -g -Wredundant-decls -Wmissing-prototypes -Wmissing-declarations  -Wextra -Wattributes -Wendif-labels -Winit-self -Wint-to-pointer-cast -Winvalid-pch -Wmissing-field-initializers -Wnonnull -Woverflow -Wvla -Wpointer-to-int-cast -Wstrict-aliasing -Wvariadic-macros -Wvolatile-register-var -Wpointer-sign -Wmissing-include-dirs -Wmissing-prototypes -Wmissing-declarations -Wformat=2 -march=i386 -m32 -mrtd -mregparm=3 -falign-jumps=1 -falign-loops=1 -falign-functions=1 -freg-struct-return -mno-mmx -mno-sse -mno-sse2 -mno-sse3 -mno-3dnow -msoft-float -fno-dwarf2-cfi-asm -mno-stack-arg-probe -fno-asynchronous-unwind-tables -fno-unwind-tables -Qn -fno-stack-protector -Wtrampolines -Werror

CFLAGS_KERNEL的定义如下,

CFLAGS_KERNEL = $(CFLAGS_PLATFORM) -ffreestanding

CFLAGS_PLATFORM为空定义,ffreestanding表示只是单纯编译C语言语句,没有引入任何标准库。

再回到目标kernel_exec-symlist.o中,接下来就是寻找源文件symlist.c,编译成目标kernel_exec-symlist.o,并将依赖关系通过mv指令最终写进/grub-core/.deps-core/kernel_exec-symlist.Po文件中。

am_kernel_exec_OBJECTS
kernel_exec_OBJECTS的另一个依赖am_kernel_exec_OBJECTS包含了大部分最终被编译链接进kernel.img的源文件,下面来看。

am_kernel_exec_OBJECTS
grub-core/Makefile

am_kernel_exec_OBJECTS = kern/i386/pc/kernel_exec-startup.$(OBJEXT) \
    kern/i386/pc/kernel_exec-init.$(OBJEXT) \
    kern/i386/pc/kernel_exec-mmap.$(OBJEXT) \
    term/i386/pc/kernel_exec-console.$(OBJEXT) \
    kern/i386/kernel_exec-dl.$(OBJEXT) \
    kern/i386/kernel_exec-tsc.$(OBJEXT) \
    kern/i386/kernel_exec-tsc_pit.$(OBJEXT) \
    kern/kernel_exec-compiler-rt.$(OBJEXT) \
    kern/kernel_exec-mm.$(OBJEXT) \
    kern/kernel_exec-time.$(OBJEXT) \
    kern/generic/kernel_exec-millisleep.$(OBJEXT) \
    kern/kernel_exec-command.$(OBJEXT) \
    kern/kernel_exec-corecmd.$(OBJEXT) \
    kern/kernel_exec-device.$(OBJEXT) \
    kern/kernel_exec-disk.$(OBJEXT) \
    kern/kernel_exec-dl.$(OBJEXT) \
    kern/kernel_exec-env.$(OBJEXT) \
    kern/kernel_exec-err.$(OBJEXT) \
    kern/kernel_exec-file.$(OBJEXT) \
    kern/kernel_exec-fs.$(OBJEXT) \
    kern/kernel_exec-list.$(OBJEXT) \
    kern/kernel_exec-main.$(OBJEXT) \
    kern/kernel_exec-misc.$(OBJEXT) \
    kern/kernel_exec-parser.$(OBJEXT) \
    kern/kernel_exec-partition.$(OBJEXT) \
    kern/kernel_exec-rescue_parser.$(OBJEXT) \
    kern/kernel_exec-rescue_reader.$(OBJEXT) \
    kern/kernel_exec-term.$(OBJEXT)

其中,每个源文件被编译的命令和前面分析的kernel_exec-symlist.o一致,因此下面就不详细说明了,简单说:

kern/i386/pc/kernel_exec-startup.o由kern/i386/pc/startup.S编译而成,其依赖关系记录在kern/i386/pc/.deps-core/kernel_exec-startup.Po

kern/i386/pc/kernel_exec-init.o由kern/i386/pc/init.c编译而成,其依赖关系记录在kern/i386/pc/.deps-core/kernel_exec-init.Po

kern/i386/pc/kernel_exec-mmap.obj由kern/i386/pc/mmap.c编译而成,其依赖关系记录在kern/i386/pc/.deps-core/kernel_exec-mmap.Po中

term/i386/pc/kernel_exec-console.o由term/i386/pc/console.c编译而成,其依赖关系记录在term/i386/pc/.deps-core/kernel_exec-console.Po中

kern/i386/kernel_exec-dl.o由kern/i386/dl.c编译而成,其依赖关系记录在kern/i386/.deps-core/kernel_exec-dl.Po中

kern/i386/kernel_exec-tsc.o由kern/i386/tsc.c编译而成,其依赖关系记录在kern/i386/.deps-core/kernel_exec-tsc.Po中

kern/i386/kernel_exec-tsc_pit.o由kern/i386/tsc_pit.c编译而成,其依赖关系记录在kern/i386/$(DEPDIR)/kernel_exec-tsc_pit.Po

kern/kernel_exec-compiler-rt.o由kern/compiler-rt.c编译而成,其依赖关系记录在kern/$(DEPDIR)/kernel_exec-compiler-rt.Po

kern/kernel_exec-mm.o由kern/mm.c编译而成,其依赖关系记录在kern/$(DEPDIR)/kernel_exec-mm.Po

kern/kernel_exec-time.o由kern/time.c编译而成,其依赖关系记录在kern/$(DEPDIR)/kernel_exec-time.Po

kern/generic/kernel_exec-millisleep.o由kern/generic/millisleep.c编译而成,其依赖关系记录在kern/generic/$(DEPDIR)/kernel_exec-millisleep.Po

kern/kernel_exec-command.o由kern/command.c编译而成,其依赖关系记录在kern/$(DEPDIR)/kernel_exec-command.Po

kern/kernel_exec-corecmd.o由kern/corecmd.c编译而成,其依赖关系记录在kern/$(DEPDIR)/kernel_exec-corecmd.Po

kern/kernel_exec-device.o由kern/device.c编译而成,其依赖关系记录在kern/$(DEPDIR)/kernel_exec-device.Po

kern/kernel_exec-disk.o由kern/disk.c编译而成,其依赖关系记录在kern/$(DEPDIR)/kernel_exec-disk.Po

kern/kernel_exec-dl.o由kern/dl.c编译而成,其依赖关系记录在kern/$(DEPDIR)/kernel_exec-dl.Po

kern/kernel_exec-env.o由kern/env.c编译而成,其依赖关系记录在kern/$(DEPDIR)/kernel_exec-env.Po

kern/kernel_exec-err.o由kern/err.c编译而成,其依赖关系记录在kern/$(DEPDIR)/kernel_exec-err.Po

kern/kernel_exec-file.o由kern/file.c编译而成,其依赖关系记录在kern/$(DEPDIR)/kernel_exec-file.Po

kern/kernel_exec-fs.obj由kern/fs.c编译而成,其依赖关系记录在kern/$(DEPDIR)/kernel_exec-fs.Po

kern/kernel_exec-list.o由kern/list.c编译而成,其依赖关系记录在kern/$(DEPDIR)/kernel_exec-list.Po

kern/kernel_exec-main.o由kern/main.c编译而成,其依赖关系记录在kern/$(DEPDIR)/kernel_exec-main.Po

kern/kernel_exec-misc.o由kern/misc.c编译而成,其依赖关系记录在kern/$(DEPDIR)/kernel_exec-misc.Po

kern/kernel_exec-parser.o由kern/parser.c编译而成,其依赖关系记录在kern/$(DEPDIR)/kernel_exec-parser.Po

kern/kernel_exec-partition.o由kern/partition.c编译而成,其依赖关系记录在kern/$(DEPDIR)/kernel_exec-partition.Po

kern/kernel_exec-rescue_parser.o由kern/rescue_parser.c编译而成,其依赖关系记录在kern/$(DEPDIR)/kernel_exec-rescue_parser.Po

kern/kernel_exec-rescue_reader.o由kern/rescue_reader.c编译而成,其依赖关系记录在kern/$(DEPDIR)/kernel_exec-rescue_reader.Po

kern/kernel_exec-term.o由kern/term.c编译而成,其依赖关系记录在kern/$(DEPDIR)/kernel_exec-term.Po

第二部分-链接kernel.exec
编译完kernel_exec_OBJECTS后,接下来就要对其进行链接,下面来看。
kernel.exec
grub-core/Makefile

kernel.exec$(EXEEXT): $(kernel_exec_OBJECTS) $(kernel_exec_DEPENDENCIES) $(EXTRA_kernel_exec_DEPENDENCIES)
    @rm -f kernel.exec$(EXEEXT)
    $(AM_V_CCLD)$(kernel_exec_LINK) $(kernel_exec_OBJECTS) $(kernel_exec_LDADD) $(LIBS)

kernel_exec_DEPENDENCIES和EXTRA_kernel_exec_DEPENDENCIES都为空定义。
首先通过rm指令删除可能已经存在的kernel.exec。
接下来的AM_V_CCLD为空定义。

kernel_exec_LINK = $(CCLD) $(kernel_exec_CFLAGS) $(CFLAGS) \
    $(kernel_exec_LDFLAGS) $(LDFLAGS) -o $@

CCLD定义为gcc,kernel_exec_CFLAGS本章前面分析过了。接下来的CFLAGS空定义和LDFLAGS都为空定义,因此下面来看kernel_exec_LDFLAGS。

kernel_exec_LDFLAGS
kernel.exec
grub-core/Makefile

kernel_exec_LDFLAGS = $(AM_LDFLAGS) $(LDFLAGS_KERNEL) $(TARGET_IMG_LDFLAGS) $(TARGET_IMG_BASE_LDOPT),0x9000 
LDFLAGS_KERNEL = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC)

LDFLAGS_PLATFORM为空定义,nostdlib表示链接过程中只使用指定的文件。

TARGET_IMG_BASE_LDOPT = -Wl,-Ttext

Ttext表示链接器需要将代码段设置在地址0x9000处。
回到目标kernel.exec中,最后的kernel_exec_LDADD和LIBS都为空定义。

第三部分-kernel.img
在链接完kernel.exec后,接下来就要删除链接文件的一些不必要的信息,最终生成kernel.img,下面来看。

kernel.img
grub-core/Makefile

kernel.img: kernel.exec$(EXEEXT)
    if test x$(TARGET_APPLE_LINKER) = x1; then   $(TARGET_STRIP) -S -x $(kernel_exec) -o $@.bin $<;   $(TARGET_OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -ed2022 -ed2016 -wd1106 -nu -nd $@.bin $@;   rm -f $@.bin;    elif test ! -z '$(TARGET_OBJ2ELF)'; then      $(TARGET_STRIP) $(kernel_exec_STRIPFLAGS) -o $@.bin $< &&      $(TARGET_OBJ2ELF) $@.bin $@ || (rm -f $@; rm -f $@.bin; exit 1);      rm -f $@.bin; else $(TARGET_STRIP) $(kernel_exec_STRIPFLAGS) -o $@ $<; fi

TARGET_APPLE_LINKER定义为0,因此只看else部分。TARGET_STRIP定义为strip命令,参考《grub源码分析之boot.img-Makefile》中使用objcopy指令,strip指令相当于objcopy –strip-debug,表示不从源文件拷贝调试符号信息和相关的段,这些符号信息由gcc的-g选项生成。

kernel_exec_STRIPFLAGS = $(AM_STRIPFLAGS) $(STRIPFLAGS_KERNEL) 

AM_STRIPFLAGS为空定义,STRIPFLAGS_KERNEL的定义如下,

STRIPFLAGS_KERNEL = -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags -R .ARM.exidx
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值