From dff306fa2ef1395299bcbcbc73bd20b739b31131 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 10 Feb 2023 05:44:06 +0200 Subject: [PATCH] Stub --- libc/{Interpreter => ElfInterpreter}/Makefile | 5 +- libc/ElfInterpreter/elf.h | 292 +++++++++++++++ libc/{Interpreter => ElfInterpreter}/hash.c | 0 libc/ElfInterpreter/helper.c | 31 ++ libc/ElfInterpreter/ld.c | 343 +++++++++++++++++ libc/{Interpreter => ElfInterpreter}/ld.h | 0 libc/ElfInterpreter/ldstart.c | 33 ++ libc/ElfInterpreter/resolve.c | 344 ++++++++++++++++++ libc/Interpreter/ld.c | 17 - libc/Makefile | 4 +- libs/libgraph/Graphics.c | 15 +- libs/libgraph/Makefile | 4 +- libs/libinit/Makefile | 4 +- libs/libsys/Makefile | 4 +- 14 files changed, 1056 insertions(+), 40 deletions(-) rename libc/{Interpreter => ElfInterpreter}/Makefile (88%) create mode 100644 libc/ElfInterpreter/elf.h rename libc/{Interpreter => ElfInterpreter}/hash.c (100%) create mode 100644 libc/ElfInterpreter/helper.c create mode 100644 libc/ElfInterpreter/ld.c rename libc/{Interpreter => ElfInterpreter}/ld.h (100%) create mode 100644 libc/ElfInterpreter/ldstart.c create mode 100644 libc/ElfInterpreter/resolve.c delete mode 100644 libc/Interpreter/ld.c diff --git a/libc/Interpreter/Makefile b/libc/ElfInterpreter/Makefile similarity index 88% rename from libc/Interpreter/Makefile rename to libc/ElfInterpreter/Makefile index 472d2e2e..90a8c9bc 100644 --- a/libc/Interpreter/Makefile +++ b/libc/ElfInterpreter/Makefile @@ -29,13 +29,14 @@ else ifeq ($(OSARCH), i686) ASM_ARCH := elf32 endif -CFLAGS := -fPIC -fPIE -I$(INCLUDE) +CFLAGS := -pie -fPIE -I$(INCLUDE) +LDFLAGS := -nostartfiles -nostdlib -pie -fPIE -Wl,-e_ld_start,-soname,$(SO_NAME) $(SYSROOT) build: $(OBJECT_NAME) $(OBJECT_NAME): $(OBJ) $(info Linking $@) - $(CC) -static -fPIC -fPIE -Wl,-soname,$(SO_NAME) $(SYSROOT) $(OBJ) -o $(OUTPUT_DIR)$@ + $(CC) $(LDFLAGS) $(OBJ) -o $(OUTPUT_DIR)$@ $(OBJDUMP) -d $(OUTPUT_DIR)$@ > file_dump.map %.o: %.c diff --git a/libc/ElfInterpreter/elf.h b/libc/ElfInterpreter/elf.h new file mode 100644 index 00000000..7d49b76d --- /dev/null +++ b/libc/ElfInterpreter/elf.h @@ -0,0 +1,292 @@ +#ifndef __FENNIX_LIB_ELF_LAZY_RESOLVE_H__ +#define __FENNIX_LIB_ELF_LAZY_RESOLVE_H__ + +typedef __UINT32_TYPE__ Elf32_Addr; +typedef __UINT16_TYPE__ Elf32_Half; +typedef __UINT32_TYPE__ Elf32_Off; +typedef __INT32_TYPE__ Elf32_Sword; +typedef __UINT32_TYPE__ Elf32_Word; + +typedef __UINT64_TYPE__ Elf64_Addr; +typedef __UINT16_TYPE__ Elf64_Half; +typedef __INT16_TYPE__ Elf64_SHalf; +typedef __UINT64_TYPE__ Elf64_Off; +typedef __INT32_TYPE__ Elf64_Sword; +typedef __UINT32_TYPE__ Elf64_Word; +typedef __UINT64_TYPE__ Elf64_Xword; +typedef __INT64_TYPE__ Elf64_Sxword; + +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_INIT_ARRAY 14 +#define SHT_FINI_ARRAY 15 +#define SHT_PREINIT_ARRAY 16 +#define SHT_GROUP 17 +#define SHT_SYMTAB_SHNDX 18 +#define SHT_NUM 19 +#define SHT_LOOS 0x60000000 +#define SHT_GNU_ATTRIBUTES 0x6ffffff5 +#define SHT_GNU_HASH 0x6ffffff6 +#define SHT_GNU_LIBLIST 0x6ffffff7 +#define SHT_CHECKSUM 0x6ffffff8 +#define SHT_LOSUNW 0x6ffffffa +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_GNU_verdef 0x6ffffffd +#define SHT_GNU_verneed 0x6ffffffe +#define SHT_GNU_versym 0x6fffffff +#define SHT_HISUNW 0x6fffffff +#define SHT_HIOS 0x6fffffff +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0x8fffffff + +#define ELF32_R_SYM(i) ((i) >> 8) +#define ELF32_R_TYPE(i) ((unsigned char)(i)) +#define ELF32_R_INFO(s, t) (((s) << 8) + (unsigned char)(t)) + +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i)&0xffffffffL) +#define ELF64_R_INFO(s, t) (((s) << 32) + ((t)&0xffffffffL)) + +#define EI_NIDENT 16 + +enum DynamicArrayTags +{ + DT_NULL = 0, + DT_NEEDED = 1, + DT_PLTRELSZ = 2, + DT_PLTGOT = 3, + DT_HASH = 4, + DT_STRTAB = 5, + DT_SYMTAB = 6, + DT_RELA = 7, + DT_RELASZ = 8, + DT_RELAENT = 9, + DT_STRSZ = 10, + DT_SYMENT = 11, + DT_INIT = 12, + DT_FINI = 13, + DT_SONAME = 14, + DT_RPATH = 15, + DT_SYMBOLIC = 16, + DT_REL = 17, + DT_RELSZ = 18, + DT_RELENT = 19, + DT_PLTREL = 20, + DT_DEBUG = 21, + DT_TEXTREL = 22, + DT_JMPREL = 23, + DT_BIND_NOW = 24, + DT_INIT_ARRAY = 25, + DT_FINI_ARRAY = 26, + DT_INIT_ARRAYSZ = 27, + DT_FINI_ARRAYSZ = 28, + DT_RUNPATH = 29, + DT_FLAGS = 30, + DT_ENCODING = 32, + DT_PREINIT_ARRAY = 32, + DT_PREINIT_ARRAYSZ = 33, + DT_LOOS = 0x6000000d, + DT_SUNW_RTLDINF = 0x6000000e, + DT_HIOS = 0x6ffff000, + DT_VALRNGLO = 0x6ffffd00, + DT_CHECKSUM = 0x6ffffdf8, + DT_PLTPADSZ = 0x6ffffdf9, + DT_MOVEENT = 0x6ffffdfa, + DT_MOVESZ = 0x6ffffdfb, + DT_FEATURE_1 = 0x6ffffdfc, + DT_POSFLAG_1 = 0x6ffffdfd, + DT_SYMINSZ = 0x6ffffdfe, + DT_SYMINENT = 0x6ffffdff, + DT_VALRNGHI = 0x6ffffdff, + DT_ADDRRNGLO = 0x6ffffe00, + DT_CONFIG = 0x6ffffefa, + DT_DEPAUDIT = 0x6ffffefb, + DT_AUDIT = 0x6ffffefc, + DT_PLTPAD = 0x6ffffefd, + DT_MOVETAB = 0x6ffffefe, + DT_SYMINFO = 0x6ffffeff, + DT_ADDRRNGHI = 0x6ffffeff, + DT_RELACOUNT = 0x6ffffff9, + DT_RELCOUNT = 0x6ffffffa, + DT_FLAGS_1 = 0x6ffffffb, + DT_VERDEF = 0x6ffffffc, + DT_VERDEFNUM = 0x6ffffffd, + DT_VERNEED = 0x6ffffffe, + DT_VERNEEDNUM = 0x6fffffff, + DT_LOPROC = 0x70000000, + DT_SPARC_REGISTER = 0x70000001, + DT_AUXILIARY = 0x7ffffffd, + DT_USED = 0x7ffffffe, + DT_FILTER = 0x7fffffff, + DT_HIPROC = 0x7fffffff +}; + +enum SegmentTypes +{ + PT_NULL = 0, + PT_LOAD = 1, + PT_DYNAMIC = 2, + PT_INTERP = 3, + PT_NOTE = 4, + PT_SHLIB = 5, + PT_PHDR = 6, + PT_TLS = 7, + PT_LOSUNW = 0x6ffffffa, + PT_SUNWBSS = 0x6ffffffb, + PT_SUNWSTACK = 0x6ffffffa, + PT_HISUNW = 0x6fffffff, + PT_LOPROC = 0x70000000, + PT_HIPROC = 0x7fffffff +}; + +enum RtT_Types +{ + R_386_NONE = 0, + R_386_32 = 1, + R_386_PC32 = 2, + + R_X86_64_NONE = 0, + R_X86_64_64 = 1, + R_X86_64_PC32 = 2, + R_X86_64_GOT32 = 3, + R_X86_64_PLT32 = 4, + R_X86_64_COPY = 5, + R_X86_64_GLOB_DAT = 6, + R_X86_64_JUMP_SLOT = 7, + R_X86_64_RELATIVE = 8, + R_X86_64_GOTPCREL = 9, + R_X86_64_32 = 10, + R_X86_64_32S = 11, + R_X86_64_16 = 12, +}; + +typedef struct elf32_hdr +{ + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + 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]; + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; + Elf64_Off e_phoff; + Elf64_Off e_shoff; + 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; + Elf64_Word sh_type; + Elf64_Xword sh_flags; + Elf64_Addr sh_addr; + Elf64_Off sh_offset; + Elf64_Xword sh_size; + Elf64_Word sh_link; + Elf64_Word sh_info; + Elf64_Xword sh_addralign; + Elf64_Xword sh_entsize; +} Elf64_Shdr; + +struct Elf32_Dyn +{ + Elf32_Sword d_tag; + union + { + Elf32_Word d_val; + Elf32_Addr d_ptr; + } d_un; +}; + +struct Elf64_Dyn +{ + Elf64_Sxword d_tag; + union + { + Elf64_Xword d_val; + Elf64_Addr d_ptr; + } d_un; +}; + +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 +{ + Elf64_Addr r_offset; + Elf64_Xword r_info; + Elf64_Sxword r_addend; +} Elf64_Rela; + +typedef struct elf64_sym +{ + Elf64_Word st_name; + unsigned char st_info; + unsigned char st_other; + Elf64_Half st_shndx; + Elf64_Addr st_value; + Elf64_Xword st_size; +} Elf64_Sym; + +struct Elf64_Dyn *ELFGetDynamicTag(void *ElfFile, enum DynamicArrayTags Tag); + +#endif // !__FENNIX_LIB_ELF_LAZY_RESOLVE_H__ diff --git a/libc/Interpreter/hash.c b/libc/ElfInterpreter/hash.c similarity index 100% rename from libc/Interpreter/hash.c rename to libc/ElfInterpreter/hash.c diff --git a/libc/ElfInterpreter/helper.c b/libc/ElfInterpreter/helper.c new file mode 100644 index 00000000..472f1682 --- /dev/null +++ b/libc/ElfInterpreter/helper.c @@ -0,0 +1,31 @@ +#include "elf.h" + +struct Elf64_Dyn *ELFGetDynamicTag(void *ElfFile, enum DynamicArrayTags Tag) +{ + Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile; + + Elf64_Phdr ItrProgramHeader; + for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++) + { + memcpy(&ItrProgramHeader, (__UINT8_TYPE__ *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i, sizeof(Elf64_Phdr)); + if (ItrProgramHeader.p_type == PT_DYNAMIC) + { + struct Elf64_Dyn *Dynamic = (struct Elf64_Dyn *)((__UINT8_TYPE__ *)ElfFile + ItrProgramHeader.p_offset); + for (__SIZE_TYPE__ i = 0; i < ItrProgramHeader.p_filesz / sizeof(struct Elf64_Dyn); i++) + { + if (Dynamic[i].d_tag == Tag) + { + // debug("Found dynamic tag %d at %#lx [d_val: %#lx].", Tag, &Dynamic[i], Dynamic[i].d_un.d_val); + return &Dynamic[i]; + } + if (Dynamic[i].d_tag == DT_NULL) + { + // debug("Reached end of dynamic tag list for tag %d.", Tag); + return (void *)0; + } + } + } + } + // debug("Dynamic tag %d not found.", Tag); + return (void *)0; +} diff --git a/libc/ElfInterpreter/ld.c b/libc/ElfInterpreter/ld.c new file mode 100644 index 00000000..da467ec1 --- /dev/null +++ b/libc/ElfInterpreter/ld.c @@ -0,0 +1,343 @@ +#include "ld.h" + +#include "../../../Kernel/syscalls.h" +#include "../../../Kernel/ipc.h" +#include "elf.h" + +enum KCtl +{ + KCTL_NULL, + KCTL_GET_PID, + KCTL_GET_TID, + KCTL_GET_UID, + KCTL_GET_GID, + KCTL_GET_PAGE_SIZE, +}; + +// bool ELFAddLazyResolverToGOT(void *ElfFile, void *MemoryImage, LibAddressCollection *Libs) +// { +// struct Elf64_Dyn *Dyn = (struct Elf64_Dyn *)ELFGetDynamicTag(ElfFile, DT_PLTGOT); +// if (!Dyn) +// return false; + +// Elf64_Addr *GOT = (Elf64_Addr *)Dyn->d_un.d_ptr; + +// for (size_t i = 0; i < 16; i++) +// debug("GOT[%d]: %#lx (val: %#lx)", i, &GOT[i], GOT[i]); + +// GOT[1] = (uintptr_t)Libs; +// GOT[2] = (uintptr_t)ElfLazyResolver; +// return true; +// } + +/* This function is a mess and needs to be cleaned up. */ +/* +bool ELFDynamicReallocation(void *ElfFile, void *MemoryImage) +{ + debug("ELF dynamic reallocation for image at %#lx.", ElfFile); + + Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile; + uintptr_t BaseAddress = UINTPTR_MAX; + size_t ElfAppSize = 0; + Elf64_Phdr ItrPhdr; + + for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++) + { + memcpy(&ItrPhdr, + (uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i, + sizeof(Elf64_Phdr)); + BaseAddress = MIN(BaseAddress, ItrPhdr.p_vaddr); + } + + for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++) + { + memcpy(&ItrPhdr, + (uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i, + sizeof(Elf64_Phdr)); + uintptr_t SegmentEnd = ItrPhdr.p_vaddr - BaseAddress + ItrPhdr.p_memsz; + ElfAppSize = MAX(ElfAppSize, SegmentEnd); + } + + debug("BaseAddress: %#lx Size: %ld", BaseAddress, ElfAppSize); + + Elf64_Dyn *_GOTEntry = (Elf64_Dyn *)ELFGetDynamicTag(ElfFile, DT_PLTGOT); + Elf64_Dyn *_Rela = ELFGetDynamicTag(ElfFile, DT_RELA); + Elf64_Dyn *_RelaEnt = ELFGetDynamicTag(ElfFile, DT_RELAENT); + Elf64_Dyn *_JmpRel = ELFGetDynamicTag(ElfFile, DT_JMPREL); + Elf64_Dyn *_SymTab = ELFGetDynamicTag(ElfFile, DT_SYMTAB); + Elf64_Dyn *_StrTab = ELFGetDynamicTag(ElfFile, DT_STRTAB); + Elf64_Dyn *RelaSize = ELFGetDynamicTag(ElfFile, DT_RELASZ); + Elf64_Dyn *PltRelSize = ELFGetDynamicTag(ElfFile, DT_PLTRELSZ); + + Elf64_Addr *GOTEntry = (Elf64_Addr *)((uintptr_t)(_GOTEntry->d_un.d_ptr - BaseAddress) + (uintptr_t)MemoryImage); + Elf64_Dyn *Rela = (Elf64_Dyn *)((uintptr_t)(_Rela->d_un.d_ptr - BaseAddress) + (uintptr_t)MemoryImage); + Elf64_Dyn *RelaEnt = (Elf64_Dyn *)((uintptr_t)(_RelaEnt->d_un.d_ptr - BaseAddress) + (uintptr_t)MemoryImage); + Elf64_Dyn *JmpRel = (Elf64_Dyn *)((uintptr_t)(_JmpRel->d_un.d_ptr - BaseAddress) + (uintptr_t)MemoryImage); + Elf64_Dyn *SymTab = (Elf64_Dyn *)((uintptr_t)(_SymTab->d_un.d_ptr - BaseAddress) + (uintptr_t)MemoryImage); + Elf64_Dyn *StrTab = (Elf64_Dyn *)((uintptr_t)(_StrTab->d_un.d_ptr - BaseAddress) + (uintptr_t)MemoryImage); + + debug("GOTEntry: %#lx [%#lx]", _GOTEntry, GOTEntry); + debug("Rela: %#lx [%#lx]", _Rela, Rela); + debug("RelaEnt: %#lx [%#lx]", _RelaEnt, RelaEnt); + debug("JmpRel: %#lx [%#lx]", _JmpRel, JmpRel); + debug("SymTab: %#lx [%#lx]", _SymTab, SymTab); + debug("StrTab: %#lx [%#lx]", _StrTab, StrTab); + if (RelaSize) + debug("RelaSize: %ld", RelaSize->d_un.d_val); + if (PltRelSize) + debug("PltRelSize: %ld", PltRelSize->d_un.d_val); + + Elf64_Xword PltRelSizeVal = PltRelSize ? PltRelSize->d_un.d_val : 0; + Elf64_Xword RelaSizeVal = RelaSize ? RelaSize->d_un.d_val : 0; + + Elf64_Xword PltRelSizeValCount = PltRelSizeVal / sizeof(Elf64_Rela); + Elf64_Xword RelaSizeValCount = RelaSizeVal / sizeof(Elf64_Rela); + + debug("PltRelSizeVal: %ld", PltRelSizeVal); + debug("RelaSizeVal: %ld", RelaSizeVal); + debug("PltRelSizeValCount: %ld", PltRelSizeValCount); + debug("RelaSizeValCount: %ld", RelaSizeValCount); + + for (Elf64_Xword i = 0; i < PltRelSizeValCount; i++) + { + Elf64_Rela *RelaF = (Elf64_Rela *)((uintptr_t)JmpRel + i); + Elf64_Xword RelaType = ELF64_R_TYPE(RelaF->r_info); + debug("Itr %ld Type %ld", i, RelaType); + + switch (RelaType) + { + case R_X86_64_NONE: + { + debug("No relocation needed"); + break; + } + case R_X86_64_JUMP_SLOT: + { + debug("Relocation for jump slot"); + Elf64_Xword SymIndex = ELF64_R_SYM(RelaF->r_info); + Elf64_Sym *Sym = (Elf64_Sym *)((uintptr_t)SymTab + SymIndex); + char *SymName = (char *)((uintptr_t)StrTab + Sym->st_name); + debug("Symbol %s at %#lx", SymName, Sym->st_value); + + Elf64_Addr *GOTEntry = (Elf64_Addr *)RelaF->r_offset; + if (Sym->st_value) + { + fixme("Not implemented"); + *GOTEntry = (Elf64_Addr)ElfFile + Sym->st_value; + } + // else + // *GOTEntry = (Elf64_Addr)ElfLazyResolver; + + // Elf64_Sym *Sym = (Elf64_Sym *)((uintptr_t)ElfFile + (uintptr_t)SymTab + ELF64_R_SYM(RelaF->r_info) * sizeof(Elf64_Sym)); + // char *SymName = (char *)((uintptr_t)ElfFile + (uintptr_t)StrTab + Sym->st_name); + // void *SymAddr = (void *)Lib->Address + Sym->st_value; + // debug("Symbol %s at %#lx", SymName, SymAddr); + // *(void **)(RelaF->r_offset + (uintptr_t)ElfFile) = SymAddr; + break; + } + case R_X86_64_RELATIVE: + { + debug("Relative relocation"); + uintptr_t *Ptr = (uintptr_t *)((uintptr_t)ElfFile + RelaF->r_offset); + *Ptr = (uintptr_t)MemoryImage + RelaF->r_addend; + break; + } + default: + { + fixme("RelaType %d", RelaType); + break; + } + } + } + + for (Elf64_Xword i = 0; i < RelaSizeValCount; i++) + { + Elf64_Rela *RelaF = (Elf64_Rela *)((uintptr_t)ElfFile + (uintptr_t)Rela + i); + Elf64_Xword RelaType = ELF64_R_TYPE(RelaF->r_info); + debug("Itr %ld Type %ld", i, RelaType); + + switch (RelaType) + { + case R_X86_64_NONE: + { + debug("No relocation needed"); + break; + } + case R_X86_64_64: + { + debug("64-bit relocation"); + Elf64_Xword SymIndex = ELF64_R_SYM(RelaF->r_info); + Elf64_Sym *Sym = (Elf64_Sym *)((uintptr_t)ElfFile + (uintptr_t)SymTab + SymIndex); + char *SymName = (char *)((uintptr_t)ElfFile + (uintptr_t)StrTab + Sym->st_name); + debug("Symbol %s at %#lx", SymName, Sym->st_value); + + uintptr_t *Ptr = (uintptr_t *)((uintptr_t)ElfFile + RelaF->r_offset); + *Ptr = (uintptr_t)MemoryImage + Sym->st_value + RelaF->r_addend; + break; + } + case R_X86_64_GLOB_DAT: + { + debug("Global data relocation"); + Elf64_Xword SymIndex = ELF64_R_SYM(RelaF->r_info); + Elf64_Sym *Sym = (Elf64_Sym *)((uintptr_t)ElfFile + (uintptr_t)SymTab + SymIndex); + char *SymName = (char *)((uintptr_t)ElfFile + (uintptr_t)StrTab + Sym->st_name); + debug("Symbol %s at %#lx", SymName, Sym->st_value); + + uintptr_t *Ptr = (uintptr_t *)((uintptr_t)ElfFile + RelaF->r_offset); + *Ptr = (uintptr_t)MemoryImage + Sym->st_value; + break; + } + case R_X86_64_RELATIVE: + { + debug("Relative relocation"); + Elf64_Xword SymIndex = ELF64_R_SYM(RelaF->r_info); + Elf64_Sym *Sym = (Elf64_Sym *)((uintptr_t)ElfFile + (uintptr_t)SymTab + SymIndex); + char *SymName = (char *)((uintptr_t)ElfFile + (uintptr_t)StrTab + Sym->st_name); + debug("Symbol %s at %#lx", SymName, Sym->st_value); + + uintptr_t *Ptr = (uintptr_t *)((uintptr_t)ElfFile + RelaF->r_offset); + *Ptr = (uintptr_t)MemoryImage + RelaF->r_addend; + break; + } + default: + { + fixme("RelaType %d", RelaType); + break; + } + } + } + return true; +} +*/ + +/* + + ELFDynamicReallocation(ElfFile, MemoryImage); + + LibAddressCollection *LibsForLazyResolver = (LibAddressCollection *)ELFBase.TmpMem->RequestPages(TO_PAGES(sizeof(LibAddressCollection)), true); + memset(LibsForLazyResolver, 0, sizeof(LibAddressCollection)); + LibAddressCollection *LFLRTmp = LibsForLazyResolver; + debug("LibsForLazyResolver: %#lx", LibsForLazyResolver); + + if (NeededLibraries.size() > 0) + { + VirtualFileSystem::Node *ParentNode = ExFile->Node->Parent; // Working Directory + if (ParentNode) + { + char *WorkingDirAbsolutePath = vfs->GetPathFromNode(ParentNode); + debug("Working directory: \"%s\"", WorkingDirAbsolutePath); + + int LibCount = 0; + foreach (auto Library in NeededLibraries) + { + char LibPath[256]; + strcpy(LibPath, WorkingDirAbsolutePath); + strcat(LibPath, "/"); + strcat(LibPath, Library); + debug("Searching for \"%s\"...", LibPath); + + bool AlreadyTried = false; + + LibPathRetry: + VirtualFileSystem::FILE *LibNode = vfs->Open(LibPath); + + if (LibNode->Status != VirtualFileSystem::FileStatus::OK) + { + vfs->Close(LibNode); + if (!AlreadyTried) + { + debug("Library \"%s\" not found, retrying... (%#x)", LibPath, LibNode->Status); + memset(LibPath, 0, 256); + strcpy(LibPath, "/system/lib/"); + strcat(LibPath, Library); + AlreadyTried = true; + goto LibPathRetry; + } + else + warn("Failed to load library \"%s\" (%#x)", Library, LibNode->Status); + } + else + { + debug("Library found \"%s\" (%#x)", LibPath, LibNode->Status); + SharedLibraries *sl = AddLibrary(Library, (void *)LibNode->Node->Address, LibNode->Node->Length); + strcpy(LFLRTmp->Name, Library); + LFLRTmp->ElfFile = (uintptr_t *)sl->Address; + LFLRTmp->MemoryImage = (uintptr_t *)sl->MemoryImage; + LFLRTmp->ParentElfFile = (uintptr_t *)ElfFile; + LFLRTmp->ParentMemoryImage = (uintptr_t *)MemoryImage; + LFLRTmp->Valid = true; + debug("LIBRARY: %s, %#lx, %#lx", Library, LFLRTmp->ElfFile, LFLRTmp->MemoryImage); + + LFLRTmp->Next = (LibAddressCollection *)ELFBase.TmpMem->RequestPages(TO_PAGES(sizeof(LibAddressCollection)), true); + LFLRTmp = LFLRTmp->Next; + memset(LFLRTmp, 0, sizeof(LibAddressCollection)); + } + } + } + else + { + error("Couldn't get the parent node from path %s", vfs->GetPathFromNode(ExFile->Node)); + } + } + + ELFAddLazyResolverToGOT(ElfFile, MemoryImage, LibsForLazyResolver); +*/ + +/* Preload */ +void ld_main() +{ + __asm__ __volatile__("syscall" + : + : "a"(1), "D"('H'), "S"(0) + : "rcx", "r11", "memory"); + + return; +} + +uintptr_t RequestPages(size_t Count) +{ + return syscall1(_RequestPages, Count); +} + +int FreePages(uintptr_t Address, size_t Count) +{ + return syscall2(_FreePages, Address, Count); +} + +int IPC(enum IPCCommand Command, enum IPCType Type, int ID, int Flags, void *Buffer, size_t Size) +{ + return syscall6(_IPC, Command, Type, ID, Flags, Buffer, Size); +} + +uintptr_t KernelCTL(enum KCtl Command, uint64_t Arg1, uint64_t Arg2, uint64_t Arg3, uint64_t Arg4) +{ + return syscall5(_KernelCTL, Command, Arg1, Arg2, Arg3, Arg4); +} + +/* Actual load */ +int ld_load(int argc, char *argv[], char *envp[]) +{ + __asm__ __volatile__("syscall" + : + : "a"(1), "D"('L'), "S"(0) + : "rcx", "r11", "memory"); + + void *IPCBuffer = (void *)RequestPages(1); + + uintptr_t PageSize = KernelCTL(KCTL_GET_PAGE_SIZE, 0, 0, 0, 0); + + int IPC_ID = IPC(IPC_CREATE, IPC_TYPE_MessagePassing, 0, 0, "LOAD", PageSize); + + while (1) + { + IPC(IPC_LISTEN, IPC_TYPE_MessagePassing, IPC_ID, 1, NULL, 0); + IPC(IPC_WAIT, IPC_TYPE_MessagePassing, IPC_ID, 0, NULL, 0); + int IPCResult = IPC(IPC_READ, IPC_TYPE_MessagePassing, IPC_ID, 0, IPCBuffer, PageSize); + if (IPCResult == IPC_E_CODE_Success) + break; + } + + IPC(IPC_DELETE, IPC_TYPE_MessagePassing, IPC_ID, 0, NULL, 0); + // FreePages((uintptr_t)IPCBuffer, 1); <- The kernel will free the buffer for us + return *(uintptr_t *)IPCBuffer; +} diff --git a/libc/Interpreter/ld.h b/libc/ElfInterpreter/ld.h similarity index 100% rename from libc/Interpreter/ld.h rename to libc/ElfInterpreter/ld.h diff --git a/libc/ElfInterpreter/ldstart.c b/libc/ElfInterpreter/ldstart.c new file mode 100644 index 00000000..b1fe4728 --- /dev/null +++ b/libc/ElfInterpreter/ldstart.c @@ -0,0 +1,33 @@ +void __attribute__((naked, used, no_stack_protector)) _ld_start() +{ + __asm__("movq $0, %rbp\n" + "pushq %rbp\n" + "pushq %rbp\n" + "movq %rsp, %rbp\n" + + "pushq %rcx\n" + "pushq %rdx\n" + "pushq %rsi\n" + "pushq %rdi\n" + + "call ld_main\n" + + "popq %rdi\n" + "popq %rsi\n" + "popq %rdx\n" + "popq %rcx\n" + + "call ld_load\n" + "movl %eax, %edi\n" + "call _exit"); +} + +void _exit(int Code) +{ + __asm__ __volatile__("syscall" + : + : "a"(0), "D"(Code) + : "rcx", "r11", "memory"); + while (1) + ; +} diff --git a/libc/ElfInterpreter/resolve.c b/libc/ElfInterpreter/resolve.c new file mode 100644 index 00000000..565fa952 --- /dev/null +++ b/libc/ElfInterpreter/resolve.c @@ -0,0 +1,344 @@ +#include "elf.h" + +struct LibAddressCollection +{ + char Name[32]; + __UINTPTR_TYPE__ *ElfFile; + __UINTPTR_TYPE__ *MemoryImage; + __UINTPTR_TYPE__ *ParentElfFile; + __UINTPTR_TYPE__ *ParentMemoryImage; + struct LibAddressCollection *Next; + char Valid; +}; + +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +static char Lock = 0; + +__attribute__((naked, used, no_stack_protector)) void ELF_LAZY_RESOLVE_STUB() +{ + while (Lock == 1) + ; + __asm__ __volatile__("mfence\n"); + Lock = 1; + __asm__ __volatile__("pop %r11\n" + "pop %r10\n" + + "push %rdi\n" + "push %rsi\n" + "push %rdx\n" + "push %rcx\n" + "push %r8\n" + "push %r9\n" + + "mov %r11, %rdi\n" + "mov %r10, %rsi\n" + + "call ELF_LAZY_RESOLVE_MAIN\n" + + "mov %rax, %r11\n" + + "pop %r9\n" + "pop %r8\n" + "pop %rcx\n" + "pop %rdx\n" + "pop %rsi\n" + "pop %rdi\n" + + "jmp *%r11\n"); +} + +long abs(long i) { return i < 0 ? -i : i; } + +void swap(char *x, char *y) +{ + char t = *x; + *x = *y; + *y = t; +} + +char *reverse(char *Buffer, int i, int j) +{ + while (i < j) + swap(&Buffer[i++], &Buffer[j--]); + return Buffer; +} + +char *ltoa(long Value, char *Buffer, int Base) +{ + if (Base < 2 || Base > 32) + return Buffer; + + long n = abs(Value); + int i = 0; + + while (n) + { + int r = n % Base; + if (r >= 10) + Buffer[i++] = 65 + (r - 10); + else + Buffer[i++] = 48 + r; + n = n / Base; + } + + if (i == 0) + Buffer[i++] = '0'; + + if (Value < 0 && Base == 10) + Buffer[i++] = '-'; + + Buffer[i] = '\0'; + return reverse(Buffer, 0, i - 1); +} + +static inline void PutCharToKernelConsole(char c) +{ + __asm__ __volatile__("syscall" + : + : "a"(1), "D"(c), "S"(0) + : "rcx", "r11", "memory"); +} + +void *memcpy(void *dest, const void *src, __SIZE_TYPE__ n) +{ + __UINT8_TYPE__ *d = dest; + const __UINT8_TYPE__ *s = src; + while (n--) + *d++ = *s++; + return dest; +} + +int strcmp(const char *l, const char *r) +{ + for (; *l == *r && *l; l++, r++) + ; + return *(unsigned char *)l - *(unsigned char *)r; +} + +Elf64_Sym *ELFGetSymbol(__UINTPTR_TYPE__ *ElfFile, char *SymbolName) +{ + struct Elf64_Dyn *_SymTab = ELFGetDynamicTag(ElfFile, DT_SYMTAB); + struct Elf64_Dyn *_StrTab = ELFGetDynamicTag(ElfFile, DT_STRTAB); + Elf64_Sym *DynSym = (Elf64_Sym *)(ElfFile + _SymTab->d_un.d_ptr); + char *DynStr = (char *)(ElfFile + _StrTab->d_un.d_ptr); + + for (int i = 0; i < _SymTab->d_un.d_val; i++) + { + if (strcmp(DynStr + DynSym[i].st_name, SymbolName) == 0) + return &DynSym[i]; + } + return (Elf64_Sym *)0; +} + +void Print(char *String) +{ + for (short i = 0; String[i] != '\0'; i++) + PutCharToKernelConsole(String[i]); +} + +void PrintNL(char *String) +{ + for (short i = 0; String[i] != '\0'; i++) + PutCharToKernelConsole(String[i]); + + PutCharToKernelConsole('\n'); +} + +long RelTmpIndex = 0xdead; + +void *SymbolNotFound() +{ + // TODO: Print the symbol name and the library name. + // TODO: This should go to the stderr. + char Buffer[32]; + + Print("Symbol index "); + ltoa(RelTmpIndex, Buffer, 10); + Print(Buffer); + PrintNL(" not found"); + return (void *)0xdeadbeef; +} + +void (*ELF_LAZY_RESOLVE_MAIN(struct LibAddressCollection *Info, long RelIndex))() +{ + RelTmpIndex = RelIndex; + if (Info) + { + struct LibAddressCollection *tmp = Info; + PrintNL("________________"); + // The last entry is the null entry (Valid == false) which determines the end of the list. + while (tmp->Valid) + { + Print("-- "); + Print(tmp->Name); + PrintNL(" --"); + __UINTPTR_TYPE__ BaseAddress = __UINTPTR_MAX__; + + Elf64_Phdr ItrProgramHeader; + + for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)tmp->ElfFile)->e_phnum; i++) + { + memcpy(&ItrProgramHeader, (__UINT8_TYPE__ *)tmp->ElfFile + ((Elf64_Ehdr *)tmp->ElfFile)->e_phoff + ((Elf64_Ehdr *)tmp->ElfFile)->e_phentsize * i, sizeof(Elf64_Phdr)); + BaseAddress = MIN(BaseAddress, ItrProgramHeader.p_vaddr); + } + + char LibAddressBuffer[32]; + ltoa(tmp->MemoryImage, LibAddressBuffer, 16); + Print("MemoryImage: 0x"); + PrintNL(LibAddressBuffer); + + char BaseAddressBuffer[32]; + ltoa(BaseAddress, BaseAddressBuffer, 16); + Print("BaseAddress: 0x"); + PrintNL(BaseAddressBuffer); + + struct Elf64_Dyn *_JmpRel = ELFGetDynamicTag(tmp->ElfFile, DT_JMPREL); + struct Elf64_Dyn *_SymTab = ELFGetDynamicTag(tmp->ElfFile, DT_SYMTAB); + struct Elf64_Dyn *_StrTab = ELFGetDynamicTag(tmp->ElfFile, DT_STRTAB); + + if (!_JmpRel) + { + PrintNL("No DT_JMPREL"); + goto RetryNextLib; + } + else if (RelIndex >= _JmpRel->d_un.d_val / sizeof(Elf64_Rela)) + { + PrintNL("RelIndex is greater than the number of relocations"); + goto RetryNextLib; + } + + if (!_SymTab) + { + PrintNL("No DT_SYMTAB"); + goto RetryNextLib; + } + + if (!_StrTab) + { + PrintNL("No DT_STRTAB"); + goto RetryNextLib; + } + + if (!_JmpRel && !_SymTab && !_StrTab) + goto RetryNextLib; + + char JmpRel_d_ptr[32]; + ltoa(_JmpRel->d_un.d_ptr, JmpRel_d_ptr, 16); + Print("JmpRel_d_ptr: 0x"); + PrintNL(JmpRel_d_ptr); + + char SymTab_d_ptr[32]; + ltoa(_SymTab->d_un.d_ptr, SymTab_d_ptr, 16); + Print("SymTab_d_ptr: 0x"); + PrintNL(SymTab_d_ptr); + + char StrTab_d_ptr[32]; + ltoa(_StrTab->d_un.d_ptr, StrTab_d_ptr, 16); + Print("StrTab_d_ptr: 0x"); + PrintNL(StrTab_d_ptr); + + Elf64_Rela *JmpRel = tmp->MemoryImage + (_JmpRel->d_un.d_ptr - BaseAddress); + Elf64_Sym *SymTab = tmp->MemoryImage + (_SymTab->d_un.d_ptr - BaseAddress); + char *DynStr = tmp->MemoryImage + (_StrTab->d_un.d_ptr - BaseAddress); + + Elf64_Rela *Rel = JmpRel + RelIndex; + // Elf64_Rela *Rel = &JmpRel[RelIndex]; + Elf64_Addr *GOTEntry = (Elf64_Addr *)(tmp->MemoryImage + Rel->r_offset); + + int RelType = ELF64_R_TYPE(Rel->r_info); + + char RelBuffer[32]; + ltoa(Rel, RelBuffer, 16); + Print("Rel: 0x"); + PrintNL(RelBuffer); + + char LibRelInfoBuffer[32]; + ltoa(Rel->r_info, LibRelInfoBuffer, 16); + Print(" Rel->r_info: 0x"); + PrintNL(LibRelInfoBuffer); + + char LibRelOffsetBuffer[32]; + ltoa(Rel->r_offset, LibRelOffsetBuffer, 16); + Print(" Rel->r_offset: 0x"); + PrintNL(LibRelOffsetBuffer); + + char LibRelAddEntBuffer[32]; + ltoa(Rel->r_addend, LibRelAddEntBuffer, 16); + Print(" Rel->r_addend: 0x"); + PrintNL(LibRelAddEntBuffer); + + char RelIndexBuffer[32]; + ltoa(RelIndex, RelIndexBuffer, 16); + Print("RelIndex: 0x"); + PrintNL(RelIndexBuffer); + + char GotAddressBuffer[32]; + ltoa(GOTEntry, GotAddressBuffer, 16); + Print("GOTEntry: 0x"); + PrintNL(GotAddressBuffer); + + if (GOTEntry && GOTEntry < 0x10000000) + { + char GotInsideBuffer[32]; + ltoa(*GOTEntry, GotInsideBuffer, 16); + Print("*GOTEntry: 0x"); + PrintNL(GotInsideBuffer); + } + + switch (RelType) + { + case R_X86_64_NONE: + { + PrintNL("R_X86_64_NONE"); + + if (*GOTEntry == 0) + { + PrintNL("GOTEntry is 0"); + break; + } + Lock = 0; + return (void (*)()) * GOTEntry; + } + case R_X86_64_JUMP_SLOT: + { + PrintNL("R_X86_64_JUMP_SLOT"); + int SymIndex = ELF64_R_SYM(Rel->r_info); + Elf64_Sym *Sym = SymTab + SymIndex; + // Elf64_Sym *Sym = &SymTab[SymIndex]; + + if (Sym->st_name) + { + char *SymName = DynStr + Sym->st_name; + PrintNL(SymName); + + Elf64_Sym *LibSym = ELFGetSymbol(tmp->ElfFile, SymName); + if (LibSym) + { + *GOTEntry = (Elf64_Addr)(tmp->MemoryImage + LibSym->st_value); + Lock = 0; + return (void (*)()) * GOTEntry; + } + } + break; + } + default: + { + char RelTypeBuffer[32]; + ltoa(RelType, RelTypeBuffer, 10); + Print("RelType not supported "); + PrintNL(RelTypeBuffer); + break; + } + } + + RetryNextLib: + tmp = tmp->Next; + } + } + + Lock = 0; + __asm__ __volatile__("mfence\n"); + return SymbolNotFound; +} diff --git a/libc/Interpreter/ld.c b/libc/Interpreter/ld.c deleted file mode 100644 index 06d3561d..00000000 --- a/libc/Interpreter/ld.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "ld.h" - -/* TODO: Implement ELF interpreter. Currently it's implemented in the kernel. */ -int main(int argc, char *argv[], char *envp[]) -{ - __asm__ __volatile__("syscall" - : - : "a"(1), "D"('H'), "S"(0) - : "rcx", "r11", "memory"); - if (argc < 2) - return -1; - - int envc = 0; - while (envp[envc] != NULL) - envc++; - return -0xD0D0; -} diff --git a/libc/Makefile b/libc/Makefile index a38ca158..61b133b3 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -3,9 +3,9 @@ build: cp ../../Kernel/syscalls.h ../out/system/include/sys make --quiet -C runtime build make --quiet -C src build - make --quiet -C Interpreter build + make --quiet -C ElfInterpreter build clean: make -C runtime clean make -C src clean - make -C Interpreter clean + make -C ElfInterpreter clean diff --git a/libs/libgraph/Graphics.c b/libs/libgraph/Graphics.c index fcfd9c1a..8f63cfbf 100644 --- a/libs/libgraph/Graphics.c +++ b/libs/libgraph/Graphics.c @@ -1,18 +1,7 @@ -#include #include "../../../Kernel/syscalls.h" -long DoCtl(uint64_t Command, uint64_t Arg1, uint64_t Arg2, uint64_t Arg3, uint64_t Arg4) +int stub() { - return syscall5(_KernelCTL, Command, Arg1, Arg2, Arg3, Arg4); -} - -uintptr_t KrnlRequestPages(size_t Count) -{ - return syscall1(_RequestPages, Count); -} - -void KrnlFreePages(uintptr_t Address, size_t Count) -{ - syscall2(_FreePages, Address, Count); + return 0; } diff --git a/libs/libgraph/Makefile b/libs/libgraph/Makefile index 4ad3821b..e39085d3 100644 --- a/libs/libgraph/Makefile +++ b/libs/libgraph/Makefile @@ -27,13 +27,13 @@ else ifeq ($(OSARCH), i686) ASM_ARCH := elf32 endif -CFLAGS := -fPIC -I../include -I../../libc/include +CFLAGS := -fPIC -fPIE -I../include -I../../libc/include build: $(OBJECT_NAME) $(OBJECT_NAME): $(OBJ) $(info Linking $@) - $(CC) -nostdlib -shared -fPIC -Wl,-soname,$(SO_NAME) $(SYSROOT) $(OBJ) -o $(OUTPUT_DIR)$@ + $(CC) -nostdlib -shared -fPIC -fPIE -Wl,-soname,$(SO_NAME) $(SYSROOT) $(OBJ) -o $(OUTPUT_DIR)$@ $(OBJDUMP) -d $(OUTPUT_DIR)$@ > file_dump.map %.o: %.c diff --git a/libs/libinit/Makefile b/libs/libinit/Makefile index cc69eecd..007b5d62 100644 --- a/libs/libinit/Makefile +++ b/libs/libinit/Makefile @@ -27,13 +27,13 @@ else ifeq ($(OSARCH), i686) ASM_ARCH := elf32 endif -CFLAGS := -fPIC -I../include -I../../libc/include +CFLAGS := -fPIC -fPIE -I../include -I../../libc/include build: $(OBJECT_NAME) $(OBJECT_NAME): $(OBJ) $(info Linking $@) - $(CC) -nostdlib -shared -fPIC -Wl,-soname,$(SO_NAME) $(SYSROOT) $(OBJ) -o $(OUTPUT_DIR)$@ + $(CC) -nostdlib -shared -fPIC -fPIE -Wl,-soname,$(SO_NAME) $(SYSROOT) $(OBJ) -o $(OUTPUT_DIR)$@ $(OBJDUMP) -d $(OUTPUT_DIR)$@ > file_dump.map %.o: %.c diff --git a/libs/libsys/Makefile b/libs/libsys/Makefile index 76b41daa..c52459cf 100644 --- a/libs/libsys/Makefile +++ b/libs/libsys/Makefile @@ -27,13 +27,13 @@ else ifeq ($(OSARCH), i686) ASM_ARCH := elf32 endif -CFLAGS := -fPIC -I../include -I../../libc/include +CFLAGS := -fPIC -fPIE -I../include -I../../libc/include build: $(OBJECT_NAME) $(OBJECT_NAME): $(OBJ) $(info Linking $@) - $(CC) -nostdlib -shared -fPIC -Wl,-soname,$(SO_NAME) $(SYSROOT) $(OBJ) -o $(OUTPUT_DIR)$@ + $(CC) -nostdlib -shared -fPIC -fPIE -Wl,-soname,$(SO_NAME) $(SYSROOT) $(OBJ) -o $(OUTPUT_DIR)$@ $(OBJDUMP) -d $(OUTPUT_DIR)$@ > file_dump.map %.o: %.c