babyos2(2)—— load elf format kernel
来源:互联网 发布:网络报警主机 编辑:程序博客网 时间:2024/06/05 20:23
为了能用qemu进行C代码级别的调试,babyos2不同于babyos,babyos采用的是纯二进制格式,babyos2的kernel是elf格式。
#define ELF_MAGIC 0x464c457FU // "\x7FELF"// File headertypedef struct elf_hdr_s { uint32 magic; // must equal ELF_MAGIC uint8 elf[12]; uint16 type; uint16 machine; uint32 version; uint32 entry; uint32 phoff; uint32 shoff; uint32 flags; uint16 ehsize; uint16 phentsize; uint16 phnum; uint16 shentsize; uint16 shnum; uint16 shstrndx;} elf_hdr_t;// Program section headertypedef struct prog_hdr_s { uint32 type; uint32 off; uint32 vaddr; uint32 paddr; uint32 filesz; uint32 memsz; uint32 flags; uint32 align;} prog_hdr_t;
主要参考了xv6相关的代码,但不同于xv6,xv6是根据elf格式一步一步地通过读扇区加载elf格式内核,babyos2是boot中将内核所有数据加载到一个临时位置,然后从内核加载elf格式到elf中各个section指定的加载位置。
extern "C" void loadmain(void){ elf_hdr_t *elf = (elf_hdr_t *) (ELF_BASE_ADDR); uint8 *base = (uint8 *) elf; // check if it's a valid elf file if (elf->magic != ELF_MAGIC) { return; } // load program segments prog_hdr_t *ph = (prog_hdr_t *)(base + elf->phoff); prog_hdr_t *end_ph = ph + elf->phnum; for (; ph < end_ph; ph++) { uint8 *pa = (uint8 *)ph->paddr; //memcpy(pa, base + ph->off, ph->filesz); movsb(pa, base + ph->off, ph->filesz); if (ph->memsz > ph->filesz) { stosb(pa + ph->filesz, 0, ph->memsz - ph->filesz); } } // find entry from elf, and call void (*entry)(void) = (void(*)(void))(elf->entry); entry();}
首先检测magic,是不是一个正确的elf格式文件,
然后依次读取各个program segment,并拷贝到prog_hdr指定的加载位置,因为这时未开启分页,所以加载地址是根据内核代码段的基地址+偏移,babyos2采用flat内存模式,各个段基地址都是0,所以这里逻辑地址=物理地址。
加载完成后,跳转到elf->entry去执行。
Makefile:
boot: boot.S ${CPP} ${CFLAGS} -c boot.S ${LD} ${LDFLAGS} --oformat binary -N -Ttext 0x7c00 -o boot boot.oloader: load.S loadmain.cc ${CPP} ${CFLAGS} -c load.S ${CPP} ${CFLAGS} -O -c loadmain.cc ${LD} --oformat binary -N -Ttext 0x0000 -o loader load.o loadmain.o
到此为止,boot loader的使命完成,elf格式的内核被解析并加载到指定的位置,然后跳转过去开始执行内核代码。
内核代码的加载位置及功能,后续再描述。
阅读全文
0 0
- babyos2(2)—— load elf format kernel
- babyos2(14)—— 用户态栈的扩展,加载elf
- babyos2(0)——从零开始
- babyos2(1)——boot
- babyos2(3)—— console, kprintf
- babyos2(4)——memory ranges
- babyos2(5)——分页
- babyos2(9)——系统调用
- babyos2(16)—— sleep, wakeup
- babyos2(6)——IDT,中断,异常
- babyos2(8)——读IDE硬盘
- babyos2(11)——物理内存管理,伙伴系统
- babyos2(12)——pagefault, vm_area, mmap
- babyos2(15)—— bug fix 1
- ELF format
- babyos2(7)——键盘中断、时钟中断、实时钟
- babyos2(10)——进程,调度,fork,exec,用户空间
- babyos2(13)——进程页表,fork, COW(copy on write)
- Python实现机器学习--实现多元线性回归
- 如何写出漂亮的React组件
- 条款04:确定对象被使用前已经先被初始化
- 1701 H2 11.10王建瑜 连续第六天
- Linux系统基础(十二)
- babyos2(2)—— load elf format kernel
- VUE实现一个分页组件
- Windows下文件无法删除解决方法
- mysql随机生成字符串
- 二分 Asteroids
- vue.js 组件之间传递数据
- 深度优先搜索 hdu 1997 汉诺塔问题
- javascript 高级系列之变量提升与函数提升
- C#---接口