#include #include #include #include #include #include #include #ifdef DEBUG #include #endif #include "../../kernel.h" #include "../../Fex.hpp" using namespace Tasking; NewLock(ExecuteServiceLock); namespace Execute { Memory::MemMgr *mem = nullptr; Vector Libs; void StartExecuteService() { mem = new Memory::MemMgr; return; while (true) { ExecuteServiceLock.Lock(__FUNCTION__); foreach (auto &Lib in Libs) { if (Lib.RefCount > 0) { Lib.Timeout = TimeManager->CalculateTarget(600000); debug("Reset timeout for %s", Lib.Identifier); continue; } if (Lib.Timeout < TimeManager->GetCounter()) { // TODO: Remove fixme("Removed library %s because of timeout", Lib.Identifier); } else debug("Timeout for %s is %ld", Lib.Identifier, Lib.Timeout); } debug("Waiting 10 seconds..."); ExecuteServiceLock.Unlock(); TaskManager->Sleep(10000); } } SharedLibraries *AddLibrary(char *Identifier, void *LibraryImage, size_t Length) { SmartLock(ExecuteServiceLock); SharedLibraries sl; strcpy(sl.Identifier, Identifier); sl.Timeout = TimeManager->CalculateTarget(600000); /* 10 minutes */ sl.RefCount = 0; void *BaseLibImage = mem->RequestPages(TO_PAGES(Length)); memcpy(BaseLibImage, (void *)LibraryImage, Length); sl.Address = BaseLibImage; sl.Length = Length; debug("Library %s loaded at %#lx", Identifier, BaseLibImage); Libs.push_back(sl); return &Libs[Libs.size() - 1]; } void SearchLibrary(char *Identifier) { SmartLock(ExecuteServiceLock); } void AttachLibrary(SharedLibraries *Lib, void *BaseImage) { SmartLock(ExecuteServiceLock); BinaryType Type = GetBinaryType(BaseImage); switch (Type) { case BinaryType::BinTypeFex: { fixme("Fex is not supported yet"); return; } case BinaryType::BinTypeELF: { Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)BaseImage; uintptr_t BaseAddress = UINTPTR_MAX; size_t ElfAppSize = 0; Elf64_Phdr ItrProgramHeader; Elf64_Shdr *ElfSections = (Elf64_Shdr *)((uintptr_t)BaseImage + ELFHeader->e_shoff); Elf64_Shdr *Dynamic = nullptr; Elf64_Shdr *DynamicSymbol = nullptr; Elf64_Shdr *DynamicString = nullptr; Elf64_Shdr *SymbolTable = nullptr; Elf64_Shdr *StringTable = nullptr; Elf64_Shdr *RelaPlt = nullptr; Elf64_Shdr *GotPlt = nullptr; size_t SymbolCount = 0; size_t GOTSize = 0; Elf64_Addr *GOTEntry = 0; uintptr_t RelaOffset = 0; uint64_t RelaEnt = 0; size_t RelaSize = 0; for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++) { memcpy(&ItrProgramHeader, (uint8_t *)BaseImage + ELFHeader->e_phoff + ELFHeader->e_phentsize * i, sizeof(Elf64_Phdr)); BaseAddress = MIN(BaseAddress, ItrProgramHeader.p_vaddr); } for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++) { memcpy(&ItrProgramHeader, (uint8_t *)BaseImage + ELFHeader->e_phoff + ELFHeader->e_phentsize * i, sizeof(Elf64_Phdr)); uintptr_t SegmentEnd; SegmentEnd = ItrProgramHeader.p_vaddr - BaseAddress + ItrProgramHeader.p_memsz; ElfAppSize = MAX(ElfAppSize, SegmentEnd); for (Elf64_Half i = 0; i < ELFHeader->e_shnum; i++) { char *DynamicStringTable = (char *)((uintptr_t)BaseImage + ElfSections[ELFHeader->e_shstrndx].sh_offset + ElfSections[i].sh_name); if (strcmp(DynamicStringTable, ".dynamic") == 0) { Dynamic = &ElfSections[i]; } else if (strcmp(DynamicStringTable, ".dynsym") == 0) { DynamicSymbol = &ElfSections[i]; } else if (strcmp(DynamicStringTable, ".dynstr") == 0) { DynamicString = &ElfSections[i]; } else if (strcmp(DynamicStringTable, ".strtab") == 0) { StringTable = &ElfSections[i]; } else if (strcmp(DynamicStringTable, ".rela.plt") == 0) { RelaPlt = &ElfSections[i]; } else if (strcmp(DynamicStringTable, ".got.plt") == 0) { GotPlt = &ElfSections[i]; } else if (strcmp(DynamicStringTable, ".symtab") == 0) { SymbolTable = &ElfSections[i]; } } if (ItrProgramHeader.p_type == PT_DYNAMIC) { Elf64_Dyn *Dynamic = (Elf64_Dyn *)((uint8_t *)BaseImage + ItrProgramHeader.p_offset); for (uint64_t i = 0; i < ItrProgramHeader.p_filesz / sizeof(Elf64_Dyn); i++) { switch (Dynamic[i].d_tag) { case DT_PLTRELSZ: { GOTSize = Dynamic[i].d_un.d_val; break; } case DT_PLTGOT: { GOTEntry = (Elf64_Addr *)Dynamic[i].d_un.d_ptr; break; } case DT_RELA: { RelaOffset = Dynamic[i].d_un.d_ptr; break; } case DT_RELASZ: { RelaSize = Dynamic[i].d_un.d_val; break; } case DT_RELAENT: { RelaEnt = Dynamic[i].d_un.d_val; break; } default: break; } if (Dynamic[i].d_tag == DT_NULL) break; } break; } } debug("BaseAddress: %#lx Size: %ld", BaseAddress, ElfAppSize); if (RelaOffset != 0) { if (RelaEnt != sizeof(Elf64_Rela)) { error("RelaEnt != sizeof(Elf64_Rela)"); /* I should exit here I guess... */ } else { for (size_t RelaOffsetItr = 0; RelaOffsetItr < RelaSize; RelaOffsetItr += RelaEnt) { Elf64_Rela *Rela = (Elf64_Rela *)(((char *)BaseImage) + RelaOffset + RelaOffsetItr); switch (Rela->r_info) { case R_X86_64_RELATIVE: { uintptr_t *Ptr = (uintptr_t *)((uintptr_t)BaseImage + Rela->r_offset); *Ptr = (uintptr_t)Lib->Address + Rela->r_addend; break; } default: fixme("Rela: %ld", Rela->r_info); break; } } } } else debug("No Rela"); if (DynamicSymbol != nullptr) SymbolCount = DynamicSymbol->sh_size / sizeof(Elf64_Sym); else if (SymbolTable != nullptr) SymbolCount = SymbolTable->sh_size / sizeof(Elf64_Sym); debug("GOT Address %#lx Size %#lx Entry %#lx", GOTEntry, GOTSize, GOTEntry ? GOTEntry : 0); #ifdef DEBUG DumpData("Old GOT", (void *)GOTEntry, GOTSize); if (DynamicSymbol && DynamicString) for (size_t i = 0; i < SymbolCount; i++) { Elf64_Sym *Symbol = (Elf64_Sym *)((uintptr_t)BaseImage + DynamicSymbol->sh_offset + i * sizeof(Elf64_Sym)); char *SymbolName = (char *)((uintptr_t)BaseImage + DynamicString->sh_offset + Symbol->st_name); if (GOTEntry) if (GOTEntry[i]) { uintptr_t SymbolAddress = GOTEntry[i]; debug("New GOTEntry[%d] - Symbol %s Address %#lx", i, SymbolName, SymbolAddress); } } for (size_t i = 0; i < GOTSize; i++) if (GOTEntry) if (GOTEntry[i]) debug("GOTEntry[%d] = %#lx", i, GOTEntry[i]); #endif GOTEntry[1] = (uintptr_t)BaseImage; GOTEntry[2] = (uintptr_t)ElfLazyResolver; if (DynamicSymbol && DynamicString && GOTEntry) for (size_t i = 0; i < SymbolCount; i++) { Elf64_Sym *Symbol = (Elf64_Sym *)((uintptr_t)BaseImage + DynamicSymbol->sh_offset + i * sizeof(Elf64_Sym)); char *SymbolName = (char *)((uintptr_t)BaseImage + DynamicString->sh_offset + Symbol->st_name); switch (ELF64_ST_TYPE(Symbol->st_info)) { case STT_OBJECT: fixme("STT_OBJECT"); case STT_FUNC: { uintptr_t SymbolAddress = (uintptr_t)ELFLookupSymbol((Elf64_Ehdr *)Lib->Address, SymbolName); if (SymbolAddress == 0) { error("Symbol %s not found", SymbolName); continue; } GOTEntry[i] = (uintptr_t)Lib->Address + SymbolAddress; debug("%d %#lx Symbol %s at %#lx (%#lx)", i, &GOTEntry[i], SymbolName, SymbolAddress, (uintptr_t)Lib->Address + SymbolAddress); break; } case STT_NOTYPE: break; default: error("Unsupported symbol type %d", ELF64_ST_TYPE(Symbol->st_info)); break; } } #ifdef DEBUG DumpData("New GOT", (void *)GOTEntry, GOTSize); if (DynamicSymbol && DynamicString) for (size_t i = 0; i < SymbolCount; i++) { Elf64_Sym *Symbol = (Elf64_Sym *)((uintptr_t)BaseImage + DynamicSymbol->sh_offset + i * sizeof(Elf64_Sym)); char *SymbolName = (char *)((uintptr_t)BaseImage + DynamicString->sh_offset + Symbol->st_name); if (GOTEntry) if (GOTEntry[i]) { uintptr_t SymbolAddress = GOTEntry[i]; debug("New GOTEntry[%d] - Symbol %s Address %#lx", i, SymbolName, SymbolAddress); } } for (size_t i = 0; i < GOTSize; i++) if (GOTEntry) if (GOTEntry[i]) debug("GOTEntry[%d] = %#lx", i, GOTEntry[i]); #endif break; } default: { fixme("Unsupported binary type %d", Type); return; } } Lib->RefCount++; debug("Attached library %s", Lib->Identifier); } }