可以使用如下命令观看 elf 文件的信息
readelf -a build/ramdisk.img | vim -
 
在编写 elf loader 的时候,实际上只有下图这一部分 “Program Headers” 是有用的
 
 凡是类型为 “LOAD” 的就是需要加载进内存的部分
所以,只要把这些部分加载进内存里,再跳转到 entrypoint 就完事了,是不是很容易啊?
如下,使用 PA3 中的 elf loader 代码:
static uintptr_t loader(PCB *pcb, const char *filename) {
//	1. read program from ramdisk to mem -- invoke ramdisk_read()
//	2. execute the program -- return the entry
	extern size_t ramdisk_read(void *buf, size_t offset, size_t len);
	Elf_Ehdr elfheader;
	
	// 从磁盘/elf文件中读取 elf 头,这部分元数据放在 elf 文件的头部
	ramdisk_read(&elfheader, 0, sizeof(Elf_Ehdr));
	// 检查这个 elf 文件针对的机器架构是否是我们这种架构
	assert(elfheader.e_machine == EXPECT_TYPE);
	// 检查 elf 魔数
	assert(*(uint64_t *)(elfheader.e_ident) == 0x00010102464c457f);
	// Elf_Phdr 的格式和大小刚好是 ELF Program Headers 中的一节 
	Elf_Phdr program_header;
	// 从磁盘/elf文件中 读取第一个 program_header
	ramdisk_read(&program_header, elfheader.e_phoff, sizeof(Elf_Phdr));
	// 进入循环,这个循环会遍历所有的 program_header
	for(int i = 1; i < elfheader.e_phnum; i++) {
		// 如果当前这节 program_header 的类型是 LOAD,那么把它装载进内存
		// 然后再把 program_header.memsize - program_header.filesize 这部分清零
    	if(program_header.p_type == PT_LOAD) {
			ramdisk_read((void *)(program_header.p_vaddr), program_header.p_offset, program_header.p_filesz);
			memset((uint8_t *)(program_header.p_vaddr) +  program_header.p_filesz, 0, program_header.p_memsz - program_header.p_filesz);
		}
		
		// 从磁盘/elf文件中 读取下一个 program_header
		ramdisk_read(&program_header, elfheader.e_phoff + i * elfheader.e_phentsize, sizeof(Elf_Phdr));
	}
	// 返回程序入点
	return elfheader.e_entry; 
}
                

















