Binary_ds类定义简化表:
namespace Boot {
class Binary_ds { public: Binary_ds(char const *name) : _ds(L4Re::chkcap(L4Re::Util::Env_ns().query<L4Re::Dataspace>(name), "Kernel binary not found", -l4_EIO)); bool is_elf_binary(); bool is_elf64(); l4_addr_t load_as_elf(Vmm::Ram_ds *ram); l4_addr_t load_as_raw(Vmm::Ram_ds *ram, l4_addr_t ram_offset); void const *get_header() const; l4virtio::Ptr<void> get_upper_bound(); ~Binary_ds();
private: Ldr::Elf_ehdr const *as_elf_header() const; L4Re::Util::Auto_cap<L4Re::Dataspace>::Cap _ds; L4Re::Rm::Auto_region<char *> _header; l4virtio::Ptr<void> _end; struct Region; Region _loaded_range_vmm; };
} // namespace
|
构造函数——Binary_ds
Binary_ds(char const *name) //name为内核镜像名字 : _ds(L4Re::chkcap(L4Re::Util::Env_ns().query<L4Re::Dataspace>(name), "Kernel binary not found", -l4_EIO)) //通过内核镜像名获取相应能力权限,并赋值给类的私有变量“_ds” { /*初始化vmm的start和end为0*/ _loaded_range_vmm.start = 0; _loaded_range_vmm.end = 0; // Map the first page which should contain all headers necessary // to interpret the binary. auto *e = L4Re::Env::env(); //在pkg\L4Re-core\L4Re\include\env中定义,原型:static Env const *env(),获取当前task的运行时环境信息 L4Re::chksys(e->rm()->attach(&_header, l4_PAGESIZE, L4Re::Rm::Search_addr, l4::Ipc::make_cap_rw(_ds.get()))); //attach函数在pkg\L4Re-core\L4Re\include\rm中定义,Attach a data space to a region,映射包含镜像头信息的第一页,映射好的虚拟地址存在“_header”变量中。 } |
Elf的load函数
l4_addr_t load_as_elf(Vmm::Ram_ds *ram) { auto const *eh = as_elf_header();
l4_addr_t img_start = (l4_addr_t)(-1L); l4_addr_t img_end = 0;
//迭代器,逐个条目(程序段信息)传递给lambda函数处理 eh->iterate_phdr([this,ram,&img_start,&img_end](Ldr::Elf_phdr ph) { if (ph.type() == PT_LOAD) { l4_addr_t dest = ram->boot2ram(ph.paddr()); //记录程序段需要加载的物理地址 if (dest > ram->size() || dest + ph.memsz() > ram->size()) L4Re::chksys(-l4_ERANGE, "Binary outside VM RAM region");
l4_addr_t gupper = ph.paddr() + ph.memsz(); if (gupper > img_end) img_end = gupper;
if (ph.paddr() < img_start) img_start = ph.paddr();
Dbg(Dbg::Mmio, Dbg::Info, "bin") .printf("Copy in ELF binary section @0x%lx from 0x%lx/0x%lx\n", dest, ph.offset(), ph.filesz()); // 在这之前主要是更新img的start和end地址;下面这句是拷贝程序段到内存 L4Re::chksys(ram->ram()->copy_in(dest, _ds.get(), ph.offset(), ph.filesz())); } });
//设置_loaded_range_vmm的起始和结束地址 _loaded_range_vmm.start = (l4_addr_t)ram->access(ram->boot2guest_phys<void>(img_start)); _end = ram->boot2guest_phys<void>(img_end); _loaded_range_vmm.end = (l4_addr_t)ram->access(_end); return eh->entry(); //返回elf的入口地址 } |
不带elf头image的load函数
l4_addr_t load_as_raw(Vmm::Ram_ds *ram, l4_addr_t ram_offset) { l4virtio::Ptr<void> start(ram->vm_start() + ram_offset); _end = ram->load_file(_ds.get(), start, nullptr); //直接拷贝全部数据 _loaded_range_vmm.start = (l4_addr_t)ram->access(start); _loaded_range_vmm.end = (l4_addr_t)ram->access(_end); return start.get(); } |
析构函数
~Binary_ds() { if (_loaded_range_vmm.start !=0 && _loaded_range_vmm.end != 0) l4_cache_coherent(_loaded_range_vmm.start, _loaded_range_vmm.end); //通过系统调用对内存进行释放 } |