diff options
author | Alexis211 <alexis211@gmail.com> | 2009-10-18 12:35:07 +0200 |
---|---|---|
committer | Alexis211 <alexis211@gmail.com> | 2009-10-18 12:35:07 +0200 |
commit | bc2eccdd11c27029096fb3e891073503eb269e27 (patch) | |
tree | 555c2a56c810af5a292dbe270ad9c12dc0f17993 /Source/Kernel/Linker | |
parent | 22c06556ccbd07f4ef7da39a62d10e03fbee3fe0 (diff) | |
download | Melon-bc2eccdd11c27029096fb3e891073503eb269e27.tar.gz Melon-bc2eccdd11c27029096fb3e891073503eb269e27.zip |
We can now load ELF binaries !!!
Diffstat (limited to 'Source/Kernel/Linker')
-rw-r--r-- | Source/Kernel/Linker/Binary.proto.cpp | 4 | ||||
-rw-r--r-- | Source/Kernel/Linker/ElfBinary.class.cpp | 55 | ||||
-rw-r--r-- | Source/Kernel/Linker/ElfBinary.class.h | 68 |
3 files changed, 126 insertions, 1 deletions
diff --git a/Source/Kernel/Linker/Binary.proto.cpp b/Source/Kernel/Linker/Binary.proto.cpp index 6053f22..c0345da 100644 --- a/Source/Kernel/Linker/Binary.proto.cpp +++ b/Source/Kernel/Linker/Binary.proto.cpp @@ -1,16 +1,18 @@ #include "Binary.proto.h" #include <Linker/MelonBinary.class.h> +#include <Linker/ElfBinary.class.h> Binary* (*loaders[])(File& file) = { &MelonBinary::load, - + &ElfBinary::load, 0 }; Binary* Binary::load(File& file) { Binary* r = 0; u32int i = 0; while (loaders[i] != 0) { + file.seek(0, SM_BEGINNING); r = loaders[i](file); //Call loader if (r != 0) break; i++; diff --git a/Source/Kernel/Linker/ElfBinary.class.cpp b/Source/Kernel/Linker/ElfBinary.class.cpp new file mode 100644 index 0000000..450053f --- /dev/null +++ b/Source/Kernel/Linker/ElfBinary.class.cpp @@ -0,0 +1,55 @@ +#include "ElfBinary.class.h" +#include <TaskManager/Task.ns.h> + +ElfBinary::~ElfBinary() { + for (SimpleList<phdr_t> *iter = m_phdr; iter != 0; iter = iter->next()) { + delete iter->v().data; + } +} + +Binary* ElfBinary::load(File& file) { + elf_ehdr_t hdr; + file.read<elf_ehdr_t> (&hdr); + //Verify we have an elf file + if (hdr.e_ident[0] != 0x7F or hdr.e_ident[1] != 'E' or hdr.e_ident[2] != 'L' or hdr.e_ident[3] != 'F') return 0; + + //Store elf header into a new ElfBinary + ElfBinary* b = new ElfBinary(); + memcpy((u8int*)&b->m_ehdr, (const u8int*) &hdr, sizeof(elf_ehdr_t)); + b->m_phdr = 0; + + //Load program headers + file.seek(hdr.e_phoff, SM_BEGINNING); + for (u32int i = 0; i < hdr.e_phnum; i++) { + b->m_phdr = b->m_phdr->cons(phdr_t()); + file.read<elf_phdr_t>(&b->m_phdr->v().h); //Load current entry from file + } + //Load data + for (SimpleList<phdr_t> *iter = b->m_phdr; iter != 0; iter = iter->next()) { + iter->v().data = (u8int*)Mem::kalloc(iter->v().h.p_filesz); + file.seek(iter->v().h.p_offset, SM_BEGINNING); + file.read(iter->v().h.p_filesz, iter->v().data); + } + + return b; +} + +thread_entry_t ElfBinary::toProcess(Process* p) { + for (SimpleList<phdr_t> *iter = m_phdr; iter != 0; iter = iter->next()) { + phdr_t &e = iter->v(); + if (e.h.p_type == PT_LOAD) { + for (u32int i = e.h.p_vaddr; i < e.h.p_vaddr + e.h.p_memsz; i += 0x1000) { + p->getPagedir()->allocFrame(i, true, true); + } + p->getPagedir()->switchTo(); + memcpy((u8int*)e.h.p_vaddr, (const u8int*)e.data, e.h.p_filesz); + if (e.h.p_memsz > e.h.p_filesz) { //set to zero all the remaining space + u8int* x = (u8int*)e.h.p_vaddr; + for (u32int i = e.h.p_vaddr + e.h.p_filesz; i < e.h.p_filesz; i++) { + x[i] = 0; + } + } + } + } + return (thread_entry_t)m_ehdr.e_entry; +} diff --git a/Source/Kernel/Linker/ElfBinary.class.h b/Source/Kernel/Linker/ElfBinary.class.h new file mode 100644 index 0000000..311e2e6 --- /dev/null +++ b/Source/Kernel/Linker/ElfBinary.class.h @@ -0,0 +1,68 @@ +#ifndef DEF_ELFBINARY_CLASS_H +#define DEF_ELFBINARY_CLASS_H + +#include <Linker/Binary.proto.h> +#include <Library/SimpleList.class.h> + +/* p_type */ +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff + +struct elf_ehdr_t { + u8int e_ident[16]; /* ELF identification */ + u16int e_type; /* 2 (exec file) */ + u16int e_machine; /* 3 (intel architecture) */ + u32int e_version; /* 1 */ + u32int e_entry; /* starting point */ + u32int e_phoff; /* program header table offset */ + u32int e_shoff; /* section header table offset */ + u32int e_flags; /* various flags */ + u16int e_ehsize; /* ELF header (this) size */ + + u16int e_phentsize; /* program header table entry size */ + u16int e_phnum; /* number of entries */ + + u16int e_shentsize; /* section header table entry size */ + u16int e_shnum; /* number of entries */ + + u16int e_shstrndx; /* index of the section name string table */ +}; + +struct elf_phdr_t { + u32int p_type; /* type of segment */ + u32int p_offset; + u32int p_vaddr; + u32int p_paddr; + u32int p_filesz; + u32int p_memsz; + u32int p_flags; + u32int p_align; +}; + +struct phdr_t { + elf_phdr_t h; + u8int* data; +}; + +class ElfBinary : public Binary { + private: + elf_ehdr_t m_ehdr; + SimpleList<phdr_t> *m_phdr; + + ElfBinary() {} + + public: + virtual ~ElfBinary(); + static Binary* load(File& file); + + thread_entry_t toProcess(Process* p); +}; + +#endif |