This commit is contained in:
Alex 2023-02-10 05:44:06 +02:00
parent 5de802f825
commit dff306fa2e
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
14 changed files with 1056 additions and 40 deletions

View File

@ -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

292
libc/ElfInterpreter/elf.h Normal file
View File

@ -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__

View File

@ -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;
}

343
libc/ElfInterpreter/ld.c Normal file
View File

@ -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;
}

View File

@ -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)
;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -1,18 +1,7 @@
#include <sysbase.h>
#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;
}

View File

@ -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

View File

@ -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

View File

@ -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