grub kernel.img makefile源码分析

grub kernel.img makefile源码分析

继上一章分析了boot.img的makefile源码后,本章分析kernel.img相关的makefile源码。

第一部分-编译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

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) 

AM_CPPFLAGS在《grub boot.img makefile源码分析》中分析过了。

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 

AM_LDFLAGS在《grub boot.img makefile源码分析》中有分析。

LDFLAGS_KERNEL = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC)

LDFLAGS_PLATFORM为空定义,nostdlib表示链接过程中只使用指定的文件。
TARGET_IMG_LDFLAGS和TARGET_LDFLAGS_OLDMAGIC在《grub boot.img makefile源码分析》中分析过了。

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

总结

第一步:将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。

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

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
/boot/grub2/i386-pc/boot.img 文件是一个针对x86架构的引导镜像文件,它包含了用于引导启动计算机的程序和参数等信息。 以下是/boot/grub2/i386-pc/boot.img文件的码注释: ``` /* * This file contains the source code for the x86 version of the GRUB * boot loader. It is responsible for loading the operating system kernel * from the hard disk and transferring control to it. */ #include <grub/types.h> #include <grub/i386/pc/boot.h> #include <grub/i386/pc/loadfile.h> /* * The main function of the boot loader. It is called by the BIOS when the * computer is powered on or reset. It initializes the hardware, loads the * kernel from the hard disk, and transfers control to it. */ int main (void) { /* Initialize the hardware */ init_hw (); /* Load the kernel from the hard disk */ if (load_kernel () != 0) { /* Error loading the kernel */ return 1; } /* Transfer control to the kernel */ transfer_control (); /* Should never get here */ return 0; } /* * Initializes the hardware, including the console output and disk system. */ void init_hw (void) { /* Initialize the console */ init_console (); /* Initialize the disk system */ init_disk (); } /* * Loads the kernel from the hard disk into memory. */ int load_kernel (void) { /* Read the kernel from the hard disk */ if (read_kernel () != 0) { /* Error reading the kernel */ return 1; } /* Initialize the kernel */ init_kernel (); return 0; } /* * Transfers control to the kernel by jumping to its entry point. */ void transfer_control (void) { /* Jump to the kernel entry point */ jump_to_kernel (); } ``` 以上是x86架构/boot/grub2/i386-pc/boot.img文件的码和注释。其中,主要包括了引导加载程序的主函数、硬件初始化函数、内核加载函数和转移控制函数等。通过这些函数的调用,boot.img文件可以成功地将计算机引导到操作系统内核。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值