MIT6.828 LAB1 PART2.2 The Boot loader

加载内核

ELF文件由三大部分组成:一个带有加载信息的文件头,程序段表和程序段。每一个程序段是一块连续的代码或数据。bootloader的工作是把程序段加载到内存中。程序段表中列出了要加载到内存中的所有段。

通过命令 objdump -h obj/kern/kernel 考察JOS内核中所有段的名字大小和地址,如下所示。VMA字段是链接地址,指的是这个段希望被存放到的逻辑地址。LMA字段是加载地址,表示的是这个段被加载到内存后的物理地址。

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00005459  f0100000  00100000  00001000  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .rodata       0000166c  f0105460  00105460  00006460  2**5
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .stab         000088c9  f0106acc  00106acc  00007acc  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .stabstr      00002ada  f010f395  0010f395  00010395  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .data         0007a114  f0112000  00112000  00013000  2**12
                  CONTENTS, ALLOC, LOAD, DATA
  5 .got          0000000c  f018c114  0018c114  0008d114  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  6 .got.plt      0000000c  f018c120  0018c120  0008d120  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  7 .data.rel.local 0000100e  f018d000  0018d000  0008e000  2**12
                  CONTENTS, ALLOC, LOAD, DATA
  8 .data.rel.ro.local 000000e0  f018e020  0018e020  0008f020  2**5
                  CONTENTS, ALLOC, LOAD, DATA
  9 .bss          00000f10  f018e100  0018e100  0008f100  2**5
                  ALLOC
 10 .comment      00000029  00000000  00000000  0008f100  2**0
                  CONTENTS, READONLY

每一个ELF文件中都有一个Program Headers Table(PHT),用于指明ELF文件中哪些部分被加载到内存中以及加载到内存中的地址。PHT表中的每一个表项分别对应操作系统的一个段。并且每个表项的内容包括这个段的大小,段起始地址偏移等等信息。可用objdump -x obj/kern/kernel 命令获取PHT。(没看懂PHT,.bss段是否需要加载到内存中)

off字段指的是这段的开头相对于这个elf文件的开头的偏移量。filesz指的是这段在elf文件中的大小。memsz指的是这段装入内存中的实际大小。memsz一定大于或等于filesz,因为段在elf文件中时,许多未定义的变量没有分配内存给他们。

Program Header:
    LOAD off    0x00001000 vaddr 0xf0100000 paddr 0x00100000 align 2**12
         filesz 0x00011e6f memsz 0x00011e6f flags r-x
    LOAD off    0x00013000 vaddr 0xf0112000 paddr 0x00112000 align 2**12
         filesz 0x0007c100 memsz 0x0007d010 flags rw-
   STACK off    0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**4
         filesz 0x00000000 memsz 0x00000000 flags rwx

BIOS把bootsector加载到内存地址0x7c00处后,执行bootloader程序,在bootmain子程序中执行最后一条语句,把操作系统内核的各个段从外存读入内存中。

((void (*)(void)) (ELFHDR->e_entry))();

 BootLoader和内核有关于地址的区别:在boot loader运行时还没有任何的分段处理机制,或分页处理机制,所以boot loader可执行程序中的链接地址就应该等于加载地址。BIOS默认把boot loader加载到0x7C00内存地址处,所以就要求boot loader的链接地址也要在0x7C00处。

内核的加载地址和链接地址是不同的。

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

Exercise 6

 在这个练习中,我们将尝试使用GDB的x命令(查看内存命令)。 x/Nx ADDR。这个指令将打印出从ADDR地址开始之后的N个字的内容。重启一下Qemu。在Bios进入boot loader之前,内存地址0x00100000处8个字的内容,然后进入boot loader运行到内核开始处停止,再看下这个地址处的值。为什么二者不同?第二次这个内存处所存放的值的含义是什么?

实验过程如图示:

0x7d6b是call entry的地址,是进入内核前执行的最后一条指令,因此将断点设置在这里。0x00100000之后的8个字前后不一样应该是由于bootmain将内核的某个section放在了这个地址。

因为内核的入口地址是0x0010000c,在这个地址范围内,所以在这个内存存放的内容可能是.text段,因为内核最先加载.text段的内容。

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

到此,LAB1的part2部分就完成了。

参考博客:https://www.cnblogs.com/fatsheep9146/p/5216681.html

https://blog.csdn.net/a747979985/article/details/94334901

猜你喜欢

转载自blog.csdn.net/qq_43012789/article/details/107301594