From c43c05ef3234d6118ce601d299df60383d54ac7b Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 9 Oct 2011 14:04:45 +0800 Subject: [PATCH] Usermode/ld-acess - Fixing Elf64 support (and incorrect Uint* sizes) --- Usermode/Libraries/ld-acess.so_src/common.h | 14 +- Usermode/Libraries/ld-acess.so_src/elf.c | 147 +++++++++++++++++-- Usermode/Libraries/ld-acess.so_src/elf32.h | 18 ++- Usermode/Libraries/ld-acess.so_src/loadlib.c | 21 +-- Usermode/Libraries/ld-acess.so_src/main.c | 2 +- 5 files changed, 163 insertions(+), 39 deletions(-) diff --git a/Usermode/Libraries/ld-acess.so_src/common.h b/Usermode/Libraries/ld-acess.so_src/common.h index 8fa626a7..d44008f1 100644 --- a/Usermode/Libraries/ld-acess.so_src/common.h +++ b/Usermode/Libraries/ld-acess.so_src/common.h @@ -9,6 +9,12 @@ #include #include +#include + +typedef uintptr_t Uint; +typedef uint8_t Uint8; +typedef uint16_t Uint16; +typedef uint32_t Uint32; // HACK: Replace with underscored #define SysDebug _SysDebug @@ -19,14 +25,6 @@ #define SYSTEM_LIB_DIR "/Acess/Libs/" // === Types === -typedef unsigned int Uint; -typedef unsigned char Uint8; -typedef unsigned short Uint16; -typedef unsigned long Uint32; -typedef signed char Sint8; -typedef signed short Sint16; -typedef signed long Sint32; - typedef struct { void *Base; char *Name; diff --git a/Usermode/Libraries/ld-acess.so_src/elf.c b/Usermode/Libraries/ld-acess.so_src/elf.c index 00f2431d..acda5c4d 100644 --- a/Usermode/Libraries/ld-acess.so_src/elf.c +++ b/Usermode/Libraries/ld-acess.so_src/elf.c @@ -7,7 +7,7 @@ #include "elf32.h" #include "elf64.h" -#define DEBUG 1 +#define DEBUG 0 #if DEBUG # define DEBUGS(v...) SysDebug("ld-acess - " v) @@ -25,6 +25,9 @@ static const char *csaR_NAMES[] = {"R_386_NONE", "R_386_32", "R_386_PC32", "R_38 void *ElfRelocate(void *Base, char **envp, const char *Filename); void *Elf32Relocate(void *Base, char **envp, const char *Filename); void *Elf64Relocate(void *Base, char **envp, const char *Filename); + int ElfGetSymbol(void *Base, const char *Name, void **Ret); + int Elf64GetSymbol(void *Base, const char *Name, void **Ret); + int Elf32GetSymbol(void *Base, const char *Name, void **Ret); Uint32 ElfHashString(const char *name); // === CODE === @@ -200,6 +203,12 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename) case R_X86_64_64: *(uint64_t*)ptr = (uint64_t)GetSymbol(symname) + addend; break; + case R_X86_64_GLOB_DAT: + *(uint64_t*)ptr = (uint64_t)GetSymbol(symname); + break; + case R_X86_64_JUMP_SLOT: + *(uint64_t*)ptr = (uint64_t)GetSymbol(symname); + break; default: SysDebug("ld-acess - _Elf64DoReloc: Unknown relocation type %i", type); break; @@ -258,8 +267,8 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) Elf32_Phdr *phtab; int i, j; // Counters char *libPath; - Uint iRealBase = -1; - Uint iBaseDiff; + intptr_t iRealBase = -1; + intptr_t iBaseDiff; int iSegmentCount; int iSymCount; Elf32_Rel *rel = NULL; @@ -310,7 +319,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) // Check if a PT_DYNAMIC segement was found if(!dynamicTab) { SysDebug(" elf_relocate: No PT_DYNAMIC segment in image %p, returning", Base); - return (void *)hdr->entrypoint + iBaseDiff; + return (void *)(intptr_t)(hdr->entrypoint + iBaseDiff); } // Adjust Dynamic Table @@ -339,7 +348,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) // --- Hash Table -- case DT_HASH: if(iBaseDiff != 0) dynamicTab[j].d_val += iBaseDiff; - iSymCount = ((Uint*)(dynamicTab[j].d_val))[1]; + iSymCount = ((Elf32_Word*)(dynamicTab[j].d_val))[1]; // hdr->misc.HashTable = dynamicTab[j].d_val; // Saved in unused bytes of ident break; } @@ -419,7 +428,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) DEBUGS(" elf_relocate: Beginning Relocation"); - void elf_doRelocate(Uint r_info, Uint32 *ptr, Uint32 addend, Elf32_Sym *symtab) + void elf_doRelocate(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, Elf32_Sym *symtab) { int type = ELF32_R_TYPE(r_info); int sym = ELF32_R_SYM(r_info); @@ -530,6 +539,120 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) * \fn int ElfGetSymbol(Uint Base, const char *name, void **ret) */ int ElfGetSymbol(void *Base, const char *Name, void **ret) +{ + Elf32_Ehdr *hdr = Base; + + switch(hdr->e_ident[4]) + { + case ELFCLASS32: + return Elf32GetSymbol(Base, Name, ret); + case ELFCLASS64: + return Elf64GetSymbol(Base, Name, ret); + default: + SysDebug("ld-acess - ElfRelocate: Unknown file class %i", hdr->e_ident[4]); + return 0; + } +} + +int Elf64GetSymbol(void *Base, const char *Name, void **Ret) +{ + Elf64_Ehdr *hdr = Base; + Elf64_Sym *symtab; + int nbuckets = 0; + int iSymCount = 0; + int i; + Elf64_Word *pBuckets; + Elf64_Word *pChains; + uint32_t iNameHash; + const char *dynstrtab; + uintptr_t iBaseDiff = -1; + +// DEBUGS("sizeof(uint32_t) = %i, sizeof(Elf64_Word) = %i", sizeof(uint32_t), sizeof(Elf64_Word)); + + dynstrtab = NULL; + pBuckets = NULL; + symtab = NULL; + + // Catch the current executable + if( !pBuckets ) + { + Elf64_Phdr *phtab; + Elf64_Dyn *dynTab = NULL; + int j; + + // Locate the tables + phtab = (void*)( Base + hdr->e_phoff ); + for( i = 0; i < hdr->e_phnum; i ++ ) + { + if(phtab[i].p_type == PT_LOAD && iBaseDiff > phtab[i].p_vaddr) + iBaseDiff = phtab[i].p_vaddr; + if( phtab[i].p_type == PT_DYNAMIC ) { + dynTab = (void*)(intptr_t)phtab[i].p_vaddr; + } + } + if( !dynTab ) { + SysDebug("ERROR - Unable to find DYNAMIC segment in %p", Base); + return 0; + } + iBaseDiff = (intptr_t)Base - iBaseDiff; // Make iBaseDiff actually the diff + dynTab = (void*)( (intptr_t)dynTab + iBaseDiff ); + + for( j = 0; dynTab[j].d_tag != DT_NULL; j++) + { + switch(dynTab[j].d_tag) + { + // --- Symbol Table --- + case DT_SYMTAB: + symtab = (void*)(intptr_t) dynTab[j].d_un.d_val; // Rebased in Relocate + break; + case DT_STRTAB: + dynstrtab = (void*)(intptr_t) dynTab[j].d_un.d_val; + break; + // --- Hash Table -- + case DT_HASH: + pBuckets = (void*)(intptr_t) dynTab[j].d_un.d_val; + break; + } + } + } +// DEBUGS("pBuckets = %p", pBuckets); + + nbuckets = pBuckets[0]; + iSymCount = pBuckets[1]; + pBuckets = &pBuckets[2]; +// DEBUGS("nbuckets = %i", nbuckets); + pChains = &pBuckets[ nbuckets ]; + + // Get hash + iNameHash = ElfHashString(Name); + iNameHash %= nbuckets; + + // Walk Chain + i = pBuckets[ iNameHash ]; +// DEBUGS("dynstrtab = %p", dynstrtab); +// DEBUGS("symtab = %p, i = %i", symtab, i); + if(symtab[i].st_shndx != SHN_UNDEF && strcmp(dynstrtab + symtab[i].st_name, Name) == 0) { + *Ret = (void*) (intptr_t) symtab[i].st_value + iBaseDiff; + DEBUGS("%s = %p", Name, *Ret); + return 1; + } + + while(pChains[i] != STN_UNDEF) + { + i = pChains[i]; +// DEBUGS("chains i = %i", i); + if(symtab[i].st_shndx != SHN_UNDEF && strcmp(dynstrtab + symtab[i].st_name, Name) == 0) { + *Ret = (void*)(intptr_t)symtab[i].st_value + iBaseDiff; + DEBUGS("%s = %p", Name, *Ret); + return 1; + } + } + +// DEBUGS("Elf64GetSymbol: RETURN 0, Symbol '%s' not found", Name); + return 0; +} + +int Elf32GetSymbol(void *Base, const char *Name, void **ret) { Elf32_Ehdr *hdr = Base; Elf32_Sym *symtab; @@ -538,20 +661,14 @@ int ElfGetSymbol(void *Base, const char *Name, void **ret) int i; Uint32 *pBuckets; Uint32 *pChains; - Uint iNameHash; + uint32_t iNameHash; const char *dynstrtab; uintptr_t iBaseDiff = -1; //DEBUGS("ElfGetSymbol: (Base=0x%x, Name='%s')", Base, Name); - #if 0 - pBuckets = (void *) (intptr_t) hdr->misc.HashTable; - symtab = (void *) (intptr_t) hdr->misc.SymTable; - dynstrtab = (void *) (intptr_t) hdr->misc.StrTab; - #else dynstrtab = NULL; pBuckets = NULL; symtab = NULL; - #endif // Catch the current executable if( !pBuckets ) @@ -571,7 +688,7 @@ int ElfGetSymbol(void *Base, const char *Name, void **ret) } } if( !dynTab ) { - SysDebug("ERROR - Unable to find DYNAMIC segment in %p"); + SysDebug("ERROR - Unable to find DYNAMIC segment in %p", Base); return 0; } iBaseDiff = (intptr_t)Base - iBaseDiff; // Make iBaseDiff actually the diff @@ -596,7 +713,7 @@ int ElfGetSymbol(void *Base, const char *Name, void **ret) } #if 0 - hdr->misc.HashTable = pBucktets; + hdr->misc.HashTable = pBuckets; hdr->misc.SymTable = symtab; hdr->misc.StrTab = dynstrtab; #endif diff --git a/Usermode/Libraries/ld-acess.so_src/elf32.h b/Usermode/Libraries/ld-acess.so_src/elf32.h index 983917bd..580bbb4a 100644 --- a/Usermode/Libraries/ld-acess.so_src/elf32.h +++ b/Usermode/Libraries/ld-acess.so_src/elf32.h @@ -6,6 +6,12 @@ #ifndef _ELF32_H #define _ELF32_H +#include + +typedef uint32_t Elf32_Addr; +typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; + #define ELFCLASS32 1 /** @@ -13,8 +19,8 @@ \brief ELF File Header */ struct sElf32_Ehdr { - Uint8 e_ident[16]; //!< Identifier Bytes - Uint16 filetype; //!< File Type + uint8_t e_ident[16]; //!< Identifier Bytes + uint16_t filetype; //!< File Type Uint16 machine; //!< Machine / Arch Uint32 version; //!< Version (File?) Uint32 entrypoint; //!< Entry Point @@ -121,9 +127,9 @@ enum { struct sElf32_Phdr { Uint32 Type; - Uint Offset; - Uint VAddr; - Uint PAddr; + Uint32 Offset; + Elf32_Addr VAddr; + Elf32_Addr PAddr; Uint32 FileSize; Uint32 MemSize; Uint32 Flags; @@ -138,7 +144,7 @@ struct elf32_rel_s { struct elf32_rela_s { Uint32 r_offset; Uint32 r_info; - Sint32 r_addend; + Elf32_Sword r_addend; }; enum { diff --git a/Usermode/Libraries/ld-acess.so_src/loadlib.c b/Usermode/Libraries/ld-acess.so_src/loadlib.c index 9a1bc10d..182109bf 100644 --- a/Usermode/Libraries/ld-acess.so_src/loadlib.c +++ b/Usermode/Libraries/ld-acess.so_src/loadlib.c @@ -3,6 +3,7 @@ By thePowersGang */ #include "common.h" +#include #define DEBUG 1 @@ -61,7 +62,7 @@ void *LoadLibrary(const char *SoName, const char *SearchDir, char **envp) void *base; void (*fEntry)(void *, int, char *[], char**); - DEBUGS("LoadLibrary: (SoName='%s', SearchDir='%s', envp=0x%x)", SoName, SearchDir, envp); + DEBUGS("LoadLibrary: (SoName='%s', SearchDir='%s', envp=%p)", SoName, SearchDir, envp); // Create Temp Name filename = FindLibrary(sTmpName, SoName, SearchDir); @@ -82,13 +83,13 @@ void *LoadLibrary(const char *SoName, const char *SearchDir, char **envp) return 0; } - DEBUGS(" LoadLibrary: iArg=%p, iEntry=0x%x", base, fEntry); + DEBUGS(" LoadLibrary: iArg=%p, fEntry=%p", base, fEntry); // Load Symbols fEntry = DoRelocate( base, envp, filename ); // Call Entrypoint - DEBUGS(" LoadLibrary: '%s' Entry 0x%x", SoName, fEntry); + DEBUGS(" LoadLibrary: '%s' Entry %p", SoName, fEntry); fEntry(base, 0, NULL, envp); DEBUGS("LoadLibrary: RETURN 1"); @@ -108,7 +109,7 @@ void *IsFileLoaded(const char *file) if(gLoadedLibraries[i].Base == 0) break; // Last entry has Base set to NULL DEBUGS(" strcmp('%s', '%s')", gLoadedLibraries[i].Name, file); if(strcmp(gLoadedLibraries[i].Name, file) == 0) { - DEBUGS("IsFileLoaded: Found %i (0x%x)", i, gLoadedLibraries[i].Base); + DEBUGS("IsFileLoaded: Found %i (%p)", i, gLoadedLibraries[i].Base); return gLoadedLibraries[i].Base; } } @@ -125,7 +126,7 @@ void AddLoaded(const char *File, void *base) int i, length; char *name = gsNextAvailString; - DEBUGS("AddLoaded: (File='%s', base=0x%x)", File, base); + DEBUGS("AddLoaded: (File='%s', base=%p)", File, base); // Find a free slot for( i = 0; i < MAX_LOADED_LIBRARIES; i ++ ) @@ -149,7 +150,7 @@ void AddLoaded(const char *File, void *base) strcpy(name, File); gLoadedLibraries[i].Name = name; gsNextAvailString = &name[length+1]; - DEBUGS("'%s' (0x%x) loaded as %i", name, base, i); + DEBUGS("'%s' (%p) loaded as %i", name, base, i); return; } @@ -227,11 +228,13 @@ void *GetSymbol(const char *name) */ int GetSymbolFromBase(void *base, const char *name, void **ret) { - if(*(Uint32*)base == (0x7F|('E'<<8)|('L'<<16)|('F'<<24))) + uint8_t *hdr = base; + if(hdr[0] == 0x7F && hdr[1] == 'E' && hdr[2] == 'L' && hdr[3] == 'F') return ElfGetSymbol(base, name, ret); - if(*(Uint16*)base == ('M'|('Z'<<8))) + if(hdr[0] == 'M' && hdr[1] == 'Z') return PE_GetSymbol(base, name, ret); - SysDebug("Unknown type at %p", base); + SysDebug("Unknown type at %p (%02x %02x %02x %02x)", base, + hdr[0], hdr[1], hdr[2], hdr[3]); return 0; } diff --git a/Usermode/Libraries/ld-acess.so_src/main.c b/Usermode/Libraries/ld-acess.so_src/main.c index 49bbe2de..6ccdc0c1 100644 --- a/Usermode/Libraries/ld-acess.so_src/main.c +++ b/Usermode/Libraries/ld-acess.so_src/main.c @@ -62,7 +62,7 @@ void *SoMain(void *base) */ void *DoRelocate(void *base, char **envp, const char *Filename) { - Uint8 *hdr = base; + uint8_t *hdr = base; // Load Executable if(memcmp(base, "\x7F""ELF", 4) == 0) return ElfRelocate(base, envp, Filename); -- 2.20.1