From c20aae950434d96598034f9974a8cc6f00ec8546 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 7 Apr 2023 05:28:38 +0300 Subject: [PATCH] Fix elf interpreter (less broken) --- libc/ElfInterpreter/elf.h | 82 +++++++++++++++++--------------- libc/ElfInterpreter/ld.c | 99 ++++++++++++++++++++++++--------------- 2 files changed, 105 insertions(+), 76 deletions(-) diff --git a/libc/ElfInterpreter/elf.h b/libc/ElfInterpreter/elf.h index 7d49b76..152af14 100644 --- a/libc/ElfInterpreter/elf.h +++ b/libc/ElfInterpreter/elf.h @@ -16,42 +16,45 @@ 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 +enum SectionHeaderType +{ + SHT_NULL = 0, + SHT_PROGBITS = 1, + SHT_SYMTAB = 2, + SHT_STRTAB = 3, + SHT_RELA = 4, + SHT_HASH = 5, + SHT_DYNAMIC = 6, + SHT_NOTE = 7, + SHT_NOBITS = 8, + SHT_REL = 9, + SHT_SHLIB = 10, + SHT_DYNSYM = 11, + SHT_INIT_ARRAY = 14, + SHT_FINI_ARRAY = 15, + SHT_PREINIT_ARRAY = 16, + SHT_GROUP = 17, + SHT_SYMTAB_SHNDX = 18, + SHT_NUM = 19, + SHT_LOOS = 0x60000000, + SHT_GNU_ATTRIBUTES = 0x6ffffff5, + SHT_GNU_HASH = 0x6ffffff6, + SHT_GNU_LIBLIST = 0x6ffffff7, + SHT_CHECKSUM = 0x6ffffff8, + SHT_LOSUNW = 0x6ffffffa, + SHT_SUNW_move = 0x6ffffffa, + SHT_SUNW_COMDAT = 0x6ffffffb, + SHT_SUNW_syminfo = 0x6ffffffc, + SHT_GNU_verdef = 0x6ffffffd, + SHT_GNU_verneed = 0x6ffffffe, + SHT_GNU_versym = 0x6fffffff, + SHT_HISUNW = 0x6fffffff, + SHT_HIOS = 0x6fffffff, + SHT_LOPROC = 0x70000000, + SHT_HIPROC = 0x7fffffff, + SHT_LOUSER = 0x80000000, + SHT_HIUSER = 0x8fffffff +}; #define ELF32_R_SYM(i) ((i) >> 8) #define ELF32_R_TYPE(i) ((unsigned char)(i)) @@ -63,7 +66,10 @@ typedef __INT64_TYPE__ Elf64_Sxword; #define EI_NIDENT 16 -enum DynamicArrayTags +#define SHN_UNDEF 0 +#define SHN_ABS 0xfff1 + +enum DynamicTags { DT_NULL = 0, DT_NEEDED = 1, @@ -287,6 +293,6 @@ typedef struct elf64_sym Elf64_Xword st_size; } Elf64_Sym; -struct Elf64_Dyn *ELFGetDynamicTag(void *ElfFile, enum DynamicArrayTags Tag); +struct Elf64_Dyn *ELFGetDynamicTag(void *ElfFile, enum DynamicTags Tag); #endif // !__FENNIX_LIB_ELF_LAZY_RESOLVE_H__ diff --git a/libc/ElfInterpreter/ld.c b/libc/ElfInterpreter/ld.c index 900e28a..57b6719 100644 --- a/libc/ElfInterpreter/ld.c +++ b/libc/ElfInterpreter/ld.c @@ -138,7 +138,7 @@ void PrintNL(char *String) Print("\n"); } -void *memcpy(void *dest, const void *src, __SIZE_TYPE__ n) +void *memcpy(void *dest, const void *src, size_t n) { uint8_t *d = dest; const uint8_t *s = src; @@ -147,7 +147,7 @@ void *memcpy(void *dest, const void *src, __SIZE_TYPE__ n) return dest; } -void *memset(void *s, int c, __SIZE_TYPE__ n) +void *memset(void *s, int c, size_t n) { uint8_t *p = s; while (n--) @@ -161,7 +161,7 @@ int strcmp(const char *l, const char *r) return *(unsigned char *)l - *(unsigned char *)r; } -struct Elf64_Dyn *ELFGetDynamicTag(void *ElfFile, enum DynamicArrayTags Tag) +struct Elf64_Dyn *ELFGetDynamicTag(void *ElfFile, enum DynamicTags Tag) { Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile; @@ -172,39 +172,72 @@ struct Elf64_Dyn *ELFGetDynamicTag(void *ElfFile, enum DynamicArrayTags Tag) if (ItrProgramHeader.p_type == PT_DYNAMIC) { struct Elf64_Dyn *Dynamic = (struct Elf64_Dyn *)((uint8_t *)ElfFile + ItrProgramHeader.p_offset); - for (__SIZE_TYPE__ i = 0; i < ItrProgramHeader.p_filesz / sizeof(struct Elf64_Dyn); i++) + for (size_t 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; } -Elf64_Sym *ELFGetSymbol(uintptr_t ElfFile, char *SymbolName) +Elf64_Shdr *GetELFSheader(Elf64_Ehdr *Header) { - struct Elf64_Dyn *symTab = ELFGetDynamicTag((void *)ElfFile, DT_SYMTAB); - struct Elf64_Dyn *strTab = ELFGetDynamicTag((void *)ElfFile, DT_STRTAB); - Elf64_Sym *DynSym = (Elf64_Sym *)(ElfFile + symTab->d_un.d_ptr); - char *dynStr = (char *)(ElfFile + strTab->d_un.d_ptr); + Elf64_Off SheaderOffset = Header->e_shoff; + return (Elf64_Shdr *)((uintptr_t)Header + SheaderOffset); +} - for (int i = 0; i < symTab->d_un.d_val; i++) +Elf64_Shdr *GetELFSection(Elf64_Ehdr *Header, uint64_t Index) +{ + Elf64_Shdr *Sheader = GetELFSheader(Header); + return &Sheader[Index]; +} + +char *GetELFStringTable(Elf64_Ehdr *Header) +{ + if (Header->e_shstrndx == SHN_UNDEF) + return NULL; + return (char *)Header + GetELFSection(Header, Header->e_shstrndx)->sh_offset; +} + +Elf64_Sym *ELFLookupSymbol(Elf64_Ehdr *Header, const char *Name) +{ + Elf64_Shdr *SymbolTable = NULL; + Elf64_Shdr *StringTable = NULL; + Elf64_Sym *Symbol = NULL; + char *String = NULL; + + for (Elf64_Half i = 0; i < Header->e_shnum; i++) { - if (strcmp(dynStr + DynSym[i].st_name, SymbolName) == 0) - return &DynSym[i]; + Elf64_Shdr *shdr = GetELFSection(Header, i); + switch (shdr->sh_type) + { + case SHT_SYMTAB: + SymbolTable = shdr; + StringTable = GetELFSection(Header, shdr->sh_link); + break; + default: + { + break; + } + } } - PrintNL("ELFGetSymbol: Symbol not found!"); - return (Elf64_Sym *)0; + + if (SymbolTable == NULL || StringTable == NULL) + return NULL; + + for (size_t i = 0; i < (SymbolTable->sh_size / sizeof(Elf64_Sym)); i++) + { + Symbol = (Elf64_Sym *)((uintptr_t)Header + SymbolTable->sh_offset + (i * sizeof(Elf64_Sym))); + String = (char *)((uintptr_t)Header + StringTable->sh_offset + Symbol->st_name); + + if (strcmp(String, Name) == 0) + return (void *)Symbol; + } + return NULL; } void (*ELF_LAZY_RESOLVE_MAIN(struct LibAddressCollection *Info, long RelIndex))() @@ -250,22 +283,6 @@ void (*ELF_LAZY_RESOLVE_MAIN(struct LibAddressCollection *Info, long RelIndex))( app_BaseAddress = MIN(app_BaseAddress, ItrProgramHeader.p_vaddr); } - ltoa((long)CurLib->MemoryImage, DbgBuff, 16); - Print("lib:mmImg 0x"); - PrintNL(DbgBuff); - - ltoa((long)CurLib->ParentMemoryImage, DbgBuff, 16); - Print("lib:mmImg 0x"); - PrintNL(DbgBuff); - - ltoa(lib_BaseAddress, DbgBuff, 16); - Print("lib:BAddr 0x"); - PrintNL(DbgBuff); - - ltoa(app_BaseAddress, DbgBuff, 16); - Print("lib:BAddr 0x"); - PrintNL(DbgBuff); - struct Elf64_Dyn *lib_JmpRel = ELFGetDynamicTag((void *)CurLib->ElfFile, DT_JMPREL); struct Elf64_Dyn *lib_SymTab = ELFGetDynamicTag((void *)CurLib->ElfFile, DT_SYMTAB); struct Elf64_Dyn *lib_StrTab = ELFGetDynamicTag((void *)CurLib->ElfFile, DT_STRTAB); @@ -339,7 +356,12 @@ void (*ELF_LAZY_RESOLVE_MAIN(struct LibAddressCollection *Info, long RelIndex))( Print("SymName: "); PrintNL(SymName); - Elf64_Sym *LibSym = ELFGetSymbol(CurLib->ElfFile, SymName); + Elf64_Sym *LibSym = ELFLookupSymbol(CurLib->ElfFile, SymName); + + Print("LibSym: 0x"); + ltoa((long)LibSym, DbgBuff, 16); + PrintNL(DbgBuff); + if (LibSym) { *GOTEntry = (Elf64_Addr)(CurLib->MemoryImage + LibSym->st_value); @@ -351,6 +373,7 @@ void (*ELF_LAZY_RESOLVE_MAIN(struct LibAddressCollection *Info, long RelIndex))( Lock = 0; return (void (*)()) * GOTEntry; } + PrintNL("Not found in lib"); } break; }