diff --git a/Execute/Parse.cpp b/Execute/Parse.cpp index 3544ef5..9a74d9a 100644 --- a/Execute/Parse.cpp +++ b/Execute/Parse.cpp @@ -1,5 +1,7 @@ #include +#include + #include "../kernel.h" #include "../Fex.hpp" @@ -15,14 +17,47 @@ namespace Execute if (ExFile->Node->Flags == FileSystem::NodeFlags::FS_FILE) { Fex *FexHdr = (Fex *)ExFile->Node->Address; + Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ExFile->Node->Address; + IMAGE_DOS_HEADER *MZHeader = (IMAGE_DOS_HEADER *)ExFile->Node->Address; if (FexHdr->Magic[0] == 'F' && FexHdr->Magic[1] == 'E' && FexHdr->Magic[2] == 'X' && FexHdr->Magic[3] == '\0') { if (FexHdr->Type == FexFormatType::FexFormatType_Executable) { + trace("%s - Fex", Path); Type = BinaryType::BinTypeFex; goto Exit; } } + else if (ELFHeader->e_ident[EI_MAG0] == ELFMAG0 && + ELFHeader->e_ident[EI_MAG1] == ELFMAG1 && + ELFHeader->e_ident[EI_MAG2] == ELFMAG2 && + ELFHeader->e_ident[EI_MAG3] == ELFMAG3) + { + trace("%s - ELF", Path); + Type = BinaryType::BinTypeELF; + goto Exit; + } + else if (MZHeader->e_magic == IMAGE_DOS_SIGNATURE) + { + IMAGE_NT_HEADERS *PEHeader = (IMAGE_NT_HEADERS *)(((char *)ExFile->Node->Address) + MZHeader->e_lfanew); + IMAGE_OS2_HEADER *NEHeader = (IMAGE_OS2_HEADER *)(((char *)ExFile->Node->Address) + MZHeader->e_lfanew); + if (NEHeader->ne_magic == IMAGE_OS2_SIGNATURE) + { + trace("%s - NE", Path); + Type = BinaryType::BinTypeNE; + } + else if (PEHeader->Signature == IMAGE_NT_SIGNATURE) + { + trace("%s - PE", Path); + Type = BinaryType::BinTypePE; + } + else + { + trace("%s - MZ", Path); + Type = BinaryType::BinTypeMZ; + } + goto Exit; + } /* ... */ @@ -33,4 +68,166 @@ namespace Execute vfs->Close(ExFile); return Type; } + + /* Originally from https://wiki.osdev.org/ELF_Tutorial */ + + static inline Elf64_Shdr *GetElfSheader(Elf64_Ehdr *Header) { return (Elf64_Shdr *)((uint64_t)Header + Header->e_shoff); } + static inline Elf64_Shdr *GetElfSection(Elf64_Ehdr *Header, uint64_t Index) { return &GetElfSheader(Header)[Index]; } + + static inline char *GetElfStringTable(Elf64_Ehdr *Header) + { + if (Header->e_shstrndx == SHN_UNDEF) + return nullptr; + return (char *)Header + GetElfSection(Header, Header->e_shstrndx)->sh_offset; + } + + static inline char *elf_lookup_string(Elf64_Ehdr *Header, uint64_t Offset) + { + char *StringTable = GetElfStringTable(Header); + if (StringTable == nullptr) + return nullptr; + return StringTable + Offset; + } + + static void *ElfLookupSymbol(Elf64_Ehdr *Header, const char *Name) + { + Elf64_Shdr *SymbolTable = nullptr; + Elf64_Shdr *StringTable = nullptr; + Elf64_Sym *Symbol = nullptr; + char *String = nullptr; + + for (Elf64_Half i = 0; i < Header->e_shnum; i++) + { + Elf64_Shdr *shdr = GetElfSection(Header, i); + switch (shdr->sh_type) + { + case SHT_SYMTAB: + SymbolTable = shdr; + StringTable = GetElfSection(Header, shdr->sh_link); + break; + } + } + + if (SymbolTable == nullptr || StringTable == nullptr) + return nullptr; + + for (uint64_t i = 0; i < (SymbolTable->sh_size / sizeof(Elf64_Sym)); i++) + { + Symbol = (Elf64_Sym *)((uint64_t)Header + SymbolTable->sh_offset + (i * sizeof(Elf64_Sym))); + String = (char *)((uint64_t)Header + StringTable->sh_offset + Symbol->st_name); + if (strcmp(String, Name) == 0) + return (void *)Symbol->st_value; + } + return nullptr; + } + + static uint64_t ELFGetSymbolValue(Elf64_Ehdr *Header, uint64_t Table, uint32_t Index) + { + if (Table == SHN_UNDEF || Index == SHN_UNDEF) + return 0; + Elf64_Shdr *SymbolTable = GetElfSection(Header, Table); + + uint32_t STEntries = SymbolTable->sh_size / SymbolTable->sh_entsize; + if (Index >= STEntries) + { + error("Symbol index out of range %d-%u.", Table, Index); + return 0xdead; + } + + uint64_t SymbolAddress = (uint64_t)Header + SymbolTable->sh_offset; + Elf32_Sym *Symbol = &((Elf32_Sym *)SymbolAddress)[Index]; + + if (Symbol->st_shndx == SHN_UNDEF) + { + Elf64_Shdr *StringTable = GetElfSection(Header, SymbolTable->sh_link); + const char *Name = (const char *)Header + StringTable->sh_offset + Symbol->st_name; + + void *Target = ElfLookupSymbol(Header, Name); + if (Target == nullptr) + { + if (ELF32_ST_BIND(Symbol->st_info) & STB_WEAK) + return 0; + else + { + error("Undefined external symbol \"%s\".", Name); + return 0xdead; + } + } + else + return (uint64_t)Target; + } + else if (Symbol->st_shndx == SHN_ABS) + return Symbol->st_value; + else + { + Elf64_Shdr *Target = GetElfSection(Header, Symbol->st_shndx); + return (uint64_t)Header + Symbol->st_value + Target->sh_offset; + } + } + + void *ELFLoadRel(Elf64_Ehdr *Header) + { + Elf64_Shdr *shdr = GetElfSheader(Header); + for (uint64_t i = 0; i < Header->e_shnum; i++) + { + Elf64_Shdr *Section = &shdr[i]; + if (Section->sh_type == SHT_NOBITS) + { + if (!Section->sh_size) + continue; + if (Section->sh_flags & SHF_ALLOC) + { + void *Buffer = KernelAllocator.RequestPages(TO_PAGES(Section->sh_size)); + memset(Buffer, 0, Section->sh_size); + + Memory::Virtual pva = Memory::Virtual(/* TODO TODO TODO TODO TODO TODO */); + for (uint64_t i = 0; i < TO_PAGES(Section->sh_size); i++) + pva.Map((void *)((uint64_t)Buffer + (i * PAGE_SIZE)), (void *)((uint64_t)Buffer + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US); + + Section->sh_offset = (uint64_t)Buffer - (uint64_t)Header; + debug("Section %ld", Section->sh_size); + } + } + } + + for (uint64_t i = 0; i < Header->e_shnum; i++) + { + Elf64_Shdr *Section = &shdr[i]; + if (Section->sh_type == SHT_REL) + { + for (uint64_t Index = 0; Index < Section->sh_size / Section->sh_entsize; Index++) + { + Elf64_Rel *RelTable = &((Elf64_Rel *)((uint64_t)Header + Section->sh_offset))[Index]; + Elf64_Shdr *Target = GetElfSection(Header, Section->sh_info); + + uint64_t *RelAddress = (uint64_t *)(((uint64_t)Header + Target->sh_offset) + RelTable->r_offset); + uint64_t SymbolValue = 0; + + if (ELF64_R_SYM(RelTable->r_info) != SHN_UNDEF) + { + SymbolValue = ELFGetSymbolValue(Header, Section->sh_link, ELF64_R_SYM(RelTable->r_info)); + if (SymbolValue == 0xdead) + return (void *)0xdeadbeef; + } + + switch (ELF64_R_TYPE(RelTable->r_info)) + { + case R_386_NONE: + break; + case R_386_32: + *RelAddress = DO_64_64(SymbolValue, *RelAddress); + break; + case R_386_PC32: + *RelAddress = DO_64_PC32(SymbolValue, *RelAddress, (uint64_t)RelAddress); + break; + default: + error("Unsupported relocation type: %d", ELF64_R_TYPE(RelTable->r_info)); + return (void *)0xdeadbeef; + } + debug("Symbol value: %#lx", SymbolValue); + } + } + } + return (void *)Header->e_entry; + } } diff --git a/Execute/Spawn.cpp b/Execute/Spawn.cpp index b59b22d..3d30e82 100644 --- a/Execute/Spawn.cpp +++ b/Execute/Spawn.cpp @@ -2,7 +2,9 @@ #include #include +#include #include +#include #include "../kernel.h" #include "../Fex.hpp" @@ -27,40 +29,151 @@ namespace Execute case BinaryType::BinTypeFex: { Fex *FexHdr = (Fex *)ExFile->Node->Address; - if (FexHdr->Magic[0] == 'F' && FexHdr->Magic[1] == 'E' && FexHdr->Magic[2] == 'X' && FexHdr->Magic[3] == '\0') + if (FexHdr->Type == FexFormatType::FexFormatType_Executable) { - if (FexHdr->Type == FexFormatType::FexFormatType_Executable) + const char *BaseName; + cwk_path_get_basename(Path, &BaseName, nullptr); + PCB *Process = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), BaseName, TaskTrustLevel::User); + + void *BaseImage = KernelAllocator.RequestPages(TO_PAGES(ExFile->Node->Length)); + memcpy(BaseImage, (void *)ExFile->Node->Address, ExFile->Node->Length); + + Memory::Virtual pva = Memory::Virtual(Process->PageTable); + for (uint64_t i = 0; i < TO_PAGES(ExFile->Node->Length); i++) + pva.Map((void *)((uint64_t)BaseImage + (i * PAGE_SIZE)), (void *)((uint64_t)BaseImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US); + + TCB *Thread = TaskManager->CreateThread(Process, + (IP)FexHdr->Pointer, + Arg0, Arg1, + (IPOffset)BaseImage, + TaskArchitecture::x64, + TaskCompatibility::Native); + ret.Process = Process; + ret.Thread = Thread; + ret.Status = ExStatus::OK; + goto Exit; + } + ret.Status = ExStatus::InvalidFileHeader; + goto Exit; + } + case BinaryType::BinTypeELF: + { + const char *BaseName; + cwk_path_get_basename(Path, &BaseName, nullptr); + PCB *Process = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), BaseName, TaskTrustLevel::User); + + void *BaseImage = KernelAllocator.RequestPages(TO_PAGES(ExFile->Node->Length)); + memcpy(BaseImage, (void *)ExFile->Node->Address, ExFile->Node->Length); + + Memory::Virtual pva = Memory::Virtual(Process->PageTable); + for (uint64_t i = 0; i < TO_PAGES(ExFile->Node->Length); i++) + pva.Map((void *)((uint64_t)BaseImage + (i * PAGE_SIZE)), (void *)((uint64_t)BaseImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US); + + Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)BaseImage; + + TaskArchitecture Arch = TaskArchitecture::x64; + TaskCompatibility Comp = TaskCompatibility::Native; + if (ELFHeader->e_machine == EM_386) + Arch = TaskArchitecture::x32; + else if (ELFHeader->e_machine == EM_AMD64) + Arch = TaskArchitecture::x64; + else if (ELFHeader->e_machine == EM_AARCH64) + Arch = TaskArchitecture::ARM64; + else + Arch = TaskArchitecture::UnknownArchitecture; + + // TODO: Should I care about this? + if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS32) + { + if (ELFHeader->e_ident[EI_DATA] == ELFDATA2LSB) + fixme("ELF32 LSB"); + else if (ELFHeader->e_ident[EI_DATA] == ELFDATA2MSB) + fixme("ELF32 MSB"); + else + fixme("ELF32 Unknown"); + } + else if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS64) + { + if (ELFHeader->e_ident[EI_DATA] == ELFDATA2LSB) + fixme("ELF64 LSB"); + else if (ELFHeader->e_ident[EI_DATA] == ELFDATA2MSB) + fixme("ELF64 MSB"); + else + fixme("ELF64 Unknown"); + } + else + fixme("Unknown ELF"); + + if (ELFHeader->e_type == ET_EXEC) + { + trace("Executable"); + Elf64_Phdr *pheader = (Elf64_Phdr *)(((char *)BaseImage) + ELFHeader->e_phoff); + void *Address = nullptr; + for (int i = 0; i < ELFHeader->e_phnum; i++, pheader++) { - const char *BaseName; - cwk_path_get_basename(Path, &BaseName, nullptr); - PCB *Process = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), BaseName, TaskTrustLevel::User); + if (pheader->p_type != PT_LOAD) + continue; + Address = (void *)((uint64_t)pheader->p_vaddr + pheader->p_memsz); + } + void *Offset = KernelAllocator.RequestPages(TO_PAGES((uint64_t)Address)); - void *BaseImage = KernelAllocator.RequestPages(TO_PAGES(ExFile->Node->Length)); - memcpy(BaseImage, (void *)ExFile->Node->Address, ExFile->Node->Length); + for (uint64_t i = 0; i < TO_PAGES((uint64_t)Address); i++) + pva.Map((void *)((uint64_t)Offset + (i * PAGE_SIZE)), (void *)((uint64_t)Offset + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US); - /* - For some reason I can't map BaseImage. - Neither can I in the Tasking->CreateThread function. - Very strange. - */ + pheader = (Elf64_Phdr *)(((char *)BaseImage) + ELFHeader->e_phoff); + for (int i = 0; i < ELFHeader->e_phnum; i++, pheader++) + { + if (pheader->p_type != PT_LOAD) + continue; + void *dst = (void *)((uint64_t)pheader->p_vaddr + (uint64_t)Offset); + memset(dst, 0, pheader->p_memsz); + memcpy(dst, ((char *)BaseImage) + pheader->p_offset, pheader->p_filesz); + } - Memory::Virtual pva = Memory::Virtual(Process->PageTable); - - for (uint64_t i = 0; i < TO_PAGES(ExFile->Node->Length); i++) - pva.Map((void *)((uint64_t)BaseImage + (i * PAGE_SIZE)), (void *)((uint64_t)BaseImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US); - - TCB *Thread = TaskManager->CreateThread(Process, - (IP)FexHdr->Pointer, - Arg0, Arg1, - (IPOffset)BaseImage, - TaskArchitecture::x64, - TaskCompatibility::Native); - ret.Process = Process; - ret.Thread = Thread; - ret.Status = ExStatus::OK; + TCB *Thread = TaskManager->CreateThread(Process, + (IP)ELFHeader->e_entry, + Arg0, Arg1, + (IPOffset)Offset, + Arch, + Comp); + ret.Process = Process; + ret.Thread = Thread; + ret.Status = ExStatus::OK; + goto Exit; + } + else if (ELFHeader->e_type == ET_DYN) + { + fixme("Shared Object"); + } + else if (ELFHeader->e_type == ET_REL) + { + trace("Relocatable"); + void *EP = ELFLoadRel(ELFHeader); + if (EP == (void *)0xdeadbeef || EP == 0x0) + { + ret.Status = ExStatus::InvalidFileEntryPoint; goto Exit; } + TCB *Thread = TaskManager->CreateThread(Process, + (IP)EP, + Arg0, Arg1, + (IPOffset)BaseImage, + Arch, + Comp); + ret.Process = Process; + ret.Thread = Thread; + ret.Status = ExStatus::OK; + goto Exit; } + else if (ELFHeader->e_type == ET_CORE) + { + fixme("Core"); + } + else + { + fixme("Unknown"); + } + ret.Status = ExStatus::InvalidFileHeader; goto Exit; } @@ -83,6 +196,9 @@ namespace Execute } Exit: + if (ret.Status != ExStatus::OK) + if (ret.Process) + ret.Process->Status = TaskStatus::Terminated; vfs->Close(ExFile); return ret; } diff --git a/Tasking/Task.cpp b/Tasking/Task.cpp index f0f8d0e..ff96fb1 100644 --- a/Tasking/Task.cpp +++ b/Tasking/Task.cpp @@ -807,6 +807,7 @@ namespace Tasking sprintf_(IdleName, "Idle Thread %d", i); IdleThread->Rename(IdleName); IdleThread->SetPriority(1); + break; } debug("Tasking Started"); ((APIC::Timer *)Interrupts::apicTimer[0])->OneShot(CPU::x64::IRQ16, 100); diff --git a/include/elf.h b/include/elf.h new file mode 100644 index 0000000..68d85be --- /dev/null +++ b/include/elf.h @@ -0,0 +1,339 @@ +#ifndef __FENNIX_KERNEL_ELF_H__ +#define __FENNIX_KERNEL_ELF_H__ + +#include + +// https://wiki.osdev.org/ELF_Tutorial +// https://github.com/torvalds/linux/blob/master/include/uapi/linux/elf.h + +/* 32-bit ELF base types. */ +typedef uint32_t Elf32_Addr; +typedef uint64_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; + +/* 64-bit ELF base types. */ +typedef uint64_t Elf64_Addr; +typedef uint16_t Elf64_Half; +typedef int16_t Elf64_SHalf; +typedef uint64_t Elf64_Off; +typedef int32_t Elf64_Sword; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +#define EI_NIDENT 16 + +typedef struct elf32_hdr +{ + unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; /* Entry point virtual address */ + Elf32_Off e_phoff; /* Program header table file offset */ + Elf32_Off e_shoff; /* Section header table file offset */ + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +typedef struct elf64_hdr +{ + unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; /* Entry point virtual address */ + Elf64_Off e_phoff; /* Program header table file offset */ + Elf64_Off e_shoff; /* Section header table file offset */ + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; +} Elf64_Ehdr; + +typedef struct elf32_shdr +{ + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +typedef struct elf64_shdr +{ + Elf64_Word sh_name; /* Section name, index in string tbl */ + Elf64_Word sh_type; /* Type of section */ + Elf64_Xword sh_flags; /* Miscellaneous section attributes */ + Elf64_Addr sh_addr; /* Section virtual addr at execution */ + Elf64_Off sh_offset; /* Section file offset */ + Elf64_Xword sh_size; /* Size of section in bytes */ + Elf64_Word sh_link; /* Index of another section */ + Elf64_Word sh_info; /* Additional section information */ + Elf64_Xword sh_addralign; /* Section alignment */ + Elf64_Xword sh_entsize; /* Entry size if section holds table */ +} Elf64_Shdr; + +typedef struct +{ + Elf64_Word p_type; + Elf64_Word p_flags; + Elf64_Off p_offset; + Elf64_Addr p_vaddr; + Elf64_Addr p_paddr; + Elf64_Xword p_filesz; + Elf64_Xword p_memsz; + Elf64_Xword p_align; +} Elf64_Phdr; + +typedef struct elf32_rel +{ + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct elf64_rel +{ + Elf64_Addr r_offset; /* Location at which to apply the action */ + Elf64_Xword r_info; /* index and type of relocation */ +} Elf64_Rel; + +typedef struct elf32_sym +{ + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} Elf32_Sym; + +typedef struct elf64_sym +{ + Elf64_Word st_name; /* Symbol name, index in string tbl */ + unsigned char st_info; /* Type and binding attributes */ + unsigned char st_other; /* No defined meaning, 0 */ + Elf64_Half st_shndx; /* Associated section index */ + Elf64_Addr st_value; /* Value of the symbol */ + Elf64_Xword st_size; /* Associated symbol size */ +} Elf64_Sym; + +enum Elf_Ident +{ + EI_MAG0 = 0, // 0x7F + EI_MAG1 = 1, // 'E' + EI_MAG2 = 2, // 'L' + EI_MAG3 = 3, // 'F' + EI_CLASS = 4, // Architecture (32/64) + EI_DATA = 5, // Byte Order + EI_VERSION = 6, // ELF Version + EI_OSABI = 7, // OS Specific + EI_ABIVERSION = 8, // OS Specific + EI_PAD = 9 // Padding +}; + +enum Elf_OSABI +{ + ELFOSABI_NONE = 0, + ELFOSABI_HPUX = 1, + ELFOSABI_NETBSD = 2, + ELFOSABI_LINUX = 3, + ELFOSABI_HURD = 4, + ELFOSABI_SOLARIS = 6, + ELFOSABI_AIX = 7, + ELFOSABI_IRIX = 8, + ELFOSABI_FREEBSD = 9, + ELFOSABI_TRU64 = 10, + ELFOSABI_MODESTO = 11, + ELFOSABI_OPENBSD = 12, + ELFOSABI_OPENVMS = 13, + ELFOSABI_NSK = 14, + ELFOSABI_AROS = 15, + ELFOSABI_FENIXOS = 16, /* Wait... what? */ + ELFOSABI_CLOUDABI = 17, + ELFOSABI_OPENVOS = 18, + ELFOSABI_C6000_ELFABI = 64, + ELFOSABI_C6000_LINUX = 65, + ELFOSABI_ARM = 97, + ELFOSABI_STANDALONE = 255 +}; + +enum Elf_Type +{ + ET_NONE = 0, // Unknown Type + ET_REL = 1, // Relocatable File + ET_EXEC = 2, // Executable File + ET_DYN = 3, // Shared Object File + ET_CORE = 4, // Core File + ET_LOPROC = 0xff00, // Processor Specific + ET_HIPROC = 0xffff // Processor Specific +}; + +enum RtT_Types +{ + R_386_NONE = 0, // No relocation + R_386_32 = 1, // Symbol + Offset + R_386_PC32 = 2 // Symbol + Offset - Section Offset +}; + +enum StT_Bindings +{ + /** + * @brief Local symbol. Symbol is not visible outside the object file. + */ + STB_LOCAL = 0, + /** + * @brief Global symbol. These symbols are visible to all object files being combined. + */ + STB_GLOBAL = 1, + /** + * @brief Weak symbols. These symbols are like global symbols, but their definitions are not required. Weak symbols are not visible outside the object file containing their definition. + */ + STB_WEAK = 2, + /** + * @brief Values in this inclusive range are reserved for operating system-specific semantics. + */ + STB_LOOS = 10, + /** + * @brief Values in this inclusive range are reserved for operating system-specific semantics. + */ + STB_HIOS = 12, + /** + * @brief Values in this inclusive range are reserved for processor-specific semantics. + */ + STB_LOPROC = 13, + /** + * @brief Values in this inclusive range are reserved for processor-specific semantics. + */ + STB_HIPROC = 15 +}; + +enum StT_Types +{ + STT_NOTYPE = 0, // No type + STT_OBJECT = 1, // Variables, arrays, etc. + STT_FUNC = 2 // Methods or functions +}; + +enum SegmentTypes +{ + PT_NULL = 0, + PT_LOAD = 1, + PT_DYNAMIC = 2, + PT_INTERP = 3, + PT_NOTE = 4, + PT_SHLIB = 5, + PT_PHDR = 6, + PT_LOSUNW = 0x6ffffffa, + PT_SUNWBSS = 0x6ffffffb, + PT_SUNWSTACK = 0x6ffffffa, + PT_HISUNW = 0x6fffffff, + PT_LOPROC = 0x70000000, + PT_HIPROC = 0x7fffffff +}; + +// used for Elf64_Sym st_info +#define ELF32_ST_BIND(info) ((info) >> 4) +#define ELF32_ST_TYPE(info) ((info)&0xf) +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type)&0xf)) +#define ELF64_ST_BIND(info) ((info) >> 4) +#define ELF64_ST_TYPE(info) ((info)&0xf) +#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type)&0xf)) + +// used for Elf64_Sym st_other +#define ELF32_ST_VISIBILITY(o) ((o)&0x3) +#define ELF64_ST_VISIBILITY(o) ((o)&0x3) + +#define DO_386_32(S, A) ((S) + (A)) +#define DO_386_PC32(S, A, P) ((S) + (A) - (P)) + +#define DO_64_64(S, A) ((S) + (A)) +#define DO_64_PC32(S, A, P) ((S) + (A) - (P)) + +#define ELF32_R_SYM(INFO) ((INFO) >> 8) +#define ELF32_R_TYPE(INFO) ((uint8_t)(INFO)) + +#define ELF64_R_SYM(INFO) ((INFO) >> 8) +#define ELF64_R_TYPE(INFO) ((uint8_t)(INFO)) + +#define SHN_UNDEF 0 +#define SHN_ABS 0xfff1 + +#define SHT_NOBITS 8 +#define SHT_REL 9 + +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 + +#define EM_386 (3) // x86 Machine Type +#define EM_AMD64 (0x3E) // 64bit +#define EM_AARCH64 (0xb7) // ARM64 +#define EV_CURRENT (1) // ELF Current Version + +#define ELFMAG0 0x7F // e_ident[EI_MAG0] +#define ELFMAG1 'E' // e_ident[EI_MAG1] +#define ELFMAG2 'L' // e_ident[EI_MAG2] +#define ELFMAG3 'F' // e_ident[EI_MAG3] + +#define ELFDATANONE 0 /* e_ident[EI_DATA] */ +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 + +#define ELFCLASSNONE 0 /* EI_CLASS */ +#define ELFCLASS32 1 +#define ELFCLASS64 2 +#define ELFCLASSNUM 3 + +#define SHT_NULL 0 /* Section header table entry unused */ +#define SHT_PROGBITS 1 /* Program data */ +#define SHT_SYMTAB 2 /* Symbol table */ +#define SHT_STRTAB 3 /* String table */ +#define SHT_RELA 4 /* Relocation entries with addends */ +#define SHT_HASH 5 /* Symbol hash table */ +#define SHT_DYNAMIC 6 /* Dynamic linking information */ +#define SHT_NOTE 7 /* Notes */ +#define SHT_NOBITS 8 /* Program space with no data (bss) */ +#define SHT_REL 9 /* Relocation entries, no addends */ +#define SHT_SHLIB 10 /* Reserved */ +#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ +#define SHT_INIT_ARRAY 14 /* Array of constructors */ +#define SHT_FINI_ARRAY 15 /* Array of destructors */ +#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ +#define SHT_GROUP 17 /* Section group */ +#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ +#define SHT_NUM 19 /* Number of defined types. */ +#define SHT_LOOS 0x60000000 /* Start OS-specific. */ +#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */ +#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */ +#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ +#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ +#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ +#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ +#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ +#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ +#define SHT_HIOS 0x6fffffff /* End OS-specific type */ +#define SHT_LOPROC 0x70000000 /* Start of processor-specific */ +#define SHT_HIPROC 0x7fffffff /* End of processor-specific */ +#define SHT_LOUSER 0x80000000 /* Start of application-specific */ +#define SHT_HIUSER 0x8fffffff /* End of application-specific */ + +#endif // !__FENNIX_KERNEL_ELF_H__ diff --git a/include/exec.hpp b/include/exec.hpp index 118b345..5d07153 100644 --- a/include/exec.hpp +++ b/include/exec.hpp @@ -4,6 +4,7 @@ #include #include +#include namespace Execute { @@ -11,8 +12,10 @@ namespace Execute { BinTypeInvalid, BinTypeFex, - BinTypeElf, + BinTypeELF, BinTypePE, + BinTypeNE, + BinTypeMZ, BinTypeUnknown }; @@ -38,6 +41,8 @@ namespace Execute BinaryType GetBinaryType(char *Path); SpawnData Spawn(char *Path, uint64_t Arg0, uint64_t Arg1); + + void *ELFLoadRel(Elf64_Ehdr *Header); } #endif // !__FENNIX_KERNEL_FILE_EXECUTE_H__ diff --git a/include/msexec.h b/include/msexec.h new file mode 100644 index 0000000..adf0b5f --- /dev/null +++ b/include/msexec.h @@ -0,0 +1,231 @@ +#ifndef __FENNIX_KERNEL_MSEXEC_H__ +#define __FENNIX_KERNEL_MSEXEC_H__ + +#include + +// some of the code is from: https://github.com/dotnet/llilc/blob/main/include/clr/ntimage.h + +#define near /* __near */ +#define far /* __far */ +#define NEAR near +#define FAR far +#define CONST const + +typedef char CHAR; +typedef unsigned char UCHAR; +typedef wchar_t WCHAR; +typedef unsigned short USHORT; +typedef long LONG; + +typedef unsigned long DWORD; +typedef int BOOL; +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef float FLOAT; +typedef FLOAT *PFLOAT; +typedef BOOL near *PBOOL; +typedef BOOL far *LPBOOL; +typedef BYTE near *PBYTE; +typedef BYTE far *LPBYTE; +typedef int near *PINT; +typedef int far *LPINT; +typedef WORD near *PWORD; +typedef WORD far *LPWORD; +typedef long far *LPLONG; +typedef DWORD near *PDWORD; +typedef DWORD far *LPDWORD; +typedef void far *LPVOID; +typedef CONST void far *LPCVOID; + +typedef int INT; +typedef unsigned int UINT; +typedef unsigned int *PUINT; + +typedef short SHORT; +typedef DWORD ULONG; +typedef double DOUBLE; + +#define IMAGE_DOS_SIGNATURE 0x5A4D /* MZ */ +#define IMAGE_OS2_SIGNATURE 0x454E /* NE */ +#define IMAGE_OS2_SIGNATURE_LE 0x454C /* LE */ +#define IMAGE_NT_SIGNATURE 0x00004550 /* PE00 */ +#define IMAGE_EDOS_SIGNATURE 0x44454550 /* PEED */ + +#define IMAGE_SIZEOF_FILE_HEADER 20 + +#define IMAGE_FILE_MACHINE_UNKNOWN 0 +#define IMAGE_FILE_MACHINE_I860 0x14d +#define IMAGE_FILE_MACHINE_I386 0x14c +#define IMAGE_FILE_MACHINE_R3000 0x162 +#define IMAGE_FILE_MACHINE_R4000 0x166 +#define IMAGE_FILE_MACHINE_R10000 0x0168 +#define IMAGE_FILE_MACHINE_ALPHA 0x184 +#define IMAGE_FILE_MACHINE_POWERPC 0x01F0 +#define IMAGE_FILE_MACHINE_POWERPCBE 0x01F2 +#define IMAGE_FILE_MACHINE_SH3 0x01a2 +#define IMAGE_FILE_MACHINE_SH3E 0x01a4 +#define IMAGE_FILE_MACHINE_SH4 0x01a6 +#define IMAGE_FILE_MACHINE_ARM 0x01c0 +#define IMAGE_FILE_MACHINE_THUMB 0x01c2 +#define IMAGE_FILE_MACHINE_IA64 0x0200 +#define IMAGE_FILE_MACHINE_MIPS16 0x0266 +#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 +#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 +#define IMAGE_FILE_MACHINE_ALPHA64 0x0284 +#define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64 +#define IMAGE_FILE_MACHINE_AMD64 0x8664 +#define IMAGE_FILE_MACHINE_CEF 0xC0EF + +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 +#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 +#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 +#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 +#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 +#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 +#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 +#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 +#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 +#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 +#define IMAGE_DIRECTORY_ENTRY_TLS 9 +#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 +#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 +#define IMAGE_DIRECTORY_ENTRY_IAT 12 +#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 +#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 + +typedef struct _IMAGE_DOS_HEADER // DOS .EXE header +{ + USHORT e_magic; // Magic number + USHORT e_cblp; // Bytes on last page of file + USHORT e_cp; // Pages in file + USHORT e_crlc; // Relocations + USHORT e_cparhdr; // Size of header in paragraphs + USHORT e_minalloc; // Minimum extra paragraphs needed + USHORT e_maxalloc; // Maximum extra paragraphs needed + USHORT e_ss; // Initial (relative) SS value + USHORT e_sp; // Initial SP value + USHORT e_csum; // Checksum + USHORT e_ip; // Initial IP value + USHORT e_cs; // Initial (relative) CS value + USHORT e_lfarlc; // File address of relocation table + USHORT e_ovno; // Overlay number + USHORT e_res[4]; // Reserved words + USHORT e_oemid; // OEM identifier (for e_oeminfo) + USHORT e_oeminfo; // OEM information; e_oemid specific + USHORT e_res2[10]; // Reserved words + USHORT e_lfanew; // File address of new exe header +} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; + +typedef struct _IMAGE_OS2_HEADER // OS/2 .EXE header +{ + USHORT ne_magic; // Magic number + UCHAR ne_ver; // Version number + UCHAR ne_rev; // Revision number + USHORT ne_enttab; // Offset of Entry Table + USHORT ne_cbenttab; // Number of bytes in Entry Table + UINT ne_crc; // Checksum of whole file + USHORT ne_flags; // Flag word + USHORT ne_autodata; // Automatic data segment number + USHORT ne_heap; // Initial heap allocation + USHORT ne_stack; // Initial stack allocation + UINT ne_csip; // Initial CS:IP setting + UINT ne_sssp; // Initial SS:SP setting + USHORT ne_cseg; // Count of file segments + USHORT ne_cmod; // Entries in Module Reference Table + USHORT ne_cbnrestab; // Size of non-resident name table + USHORT ne_segtab; // Offset of Segment Table + USHORT ne_rsrctab; // Offset of Resource Table + USHORT ne_restab; // Offset of resident name table + USHORT ne_modtab; // Offset of Module Reference Table + USHORT ne_imptab; // Offset of Imported Names Table + UINT ne_nrestab; // Offset of Non-resident Names Table + USHORT ne_cmovent; // Count of movable entries + USHORT ne_align; // Segment alignment shift count + USHORT ne_cres; // Count of resource segments + UCHAR ne_exetyp; // Target Operating system + UCHAR ne_flagsothers; // Other .EXE flags + USHORT ne_pretthunks; // offset to return thunks + USHORT ne_psegrefbytes; // offset to segment ref. bytes + USHORT ne_swaparea; // Minimum code swap area size + USHORT ne_expver; // Expected Windows version number +} IMAGE_OS2_HEADER, *PIMAGE_OS2_HEADER; + +typedef struct _IMAGE_SECTION_HEADER +{ +#define IMAGE_SIZEOF_SHORT_NAME 8 + uint8_t Name[IMAGE_SIZEOF_SHORT_NAME]; + union + { + uint32_t PhysicalAddress; + uint32_t VirtualSize; + } Misc; + uint32_t VirtualAddress; + uint32_t SizeOfRawData; + uint32_t PointerToRawData; + uint32_t PointerToRelocations; + uint32_t PointerToLinenumbers; + uint16_t NumberOfRelocations; + uint16_t NumberOfLinenumbers; + uint32_t Characteristics; +} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; + +typedef struct _IMAGE_FILE_HEADER +{ + uint16_t Machine; + uint16_t NumberOfSections; + uint32_t TimeDateStamp; + uint32_t PointerToSymbolTable; + uint32_t NumberOfSymbols; + uint16_t SizeOfOptionalHeader; + uint16_t Characteristics; +} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; + +typedef struct _IMAGE_DATA_DIRECTORY +{ + uint32_t VirtualAddress; + uint32_t Size; +} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; + +typedef struct _IMAGE_OPTIONAL_HEADER +{ + uint16_t Magic; + uint8_t MajorLinkerVersion; + uint8_t MinorLinkerVersion; + uint32_t SizeOfCode; + uint32_t SizeOfInitializedData; + uint32_t SizeOfUninitializedData; + uint32_t AddressOfEntryPoint; + uint32_t BaseOfCode; + uint32_t BaseOfData; + uint32_t ImageBase; + uint32_t SectionAlignment; + uint32_t FileAlignment; + uint16_t MajorOperatingSystemVersion; + uint16_t MinorOperatingSystemVersion; + uint16_t MajorImageVersion; + uint16_t MinorImageVersion; + uint16_t MajorSubsystemVersion; + uint16_t MinorSubsystemVersion; + uint32_t Win32VersionValue; + uint32_t SizeOfImage; + uint32_t SizeOfHeaders; + uint32_t CheckSum; + uint16_t Subsystem; + uint16_t DllCharacteristics; + uint32_t SizeOfStackReserve; + uint32_t SizeOfStackCommit; + uint32_t SizeOfHeapReserve; + uint32_t SizeOfHeapCommit; + uint32_t LoaderFlags; + uint32_t NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER; + +typedef struct _IMAGE_NT_HEADERS +{ + uint32_t Signature; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER OptionalHeader; +} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS; + +#endif // !__FENNIX_KERNEL_MSEXEC_H__ diff --git a/include/task.hpp b/include/task.hpp index 5b4da9e..4d14069 100644 --- a/include/task.hpp +++ b/include/task.hpp @@ -175,7 +175,7 @@ namespace Tasking __attribute__((no_stack_protector)) bool InvalidPCB(PCB *pcb) { - if (pcb == (PCB *)0xffffffffffffffff) + if (pcb >= (PCB *)0xfffffffffffff000) return true; if (!pcb) return true; @@ -184,7 +184,7 @@ namespace Tasking __attribute__((no_stack_protector)) bool InvalidTCB(TCB *tcb) { - if (tcb == (TCB *)0xffffffffffffffff) + if (tcb >= (TCB *)0xfffffffffffff000) return true; if (!tcb) return true;