X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Usermode%2FLibraries%2Fld-acess.so_src%2Felf.c;h=27cf96c1a7f4af6748a3ad1179f207c974c6aecc;hb=9ceb37a5d9ab9c5506c9a4ba2d0112a86f0e6073;hp=13347a642512f3c4e97720a49372bbf247e1fb84;hpb=04a050f42807686dc119838c82372409246d55bb;p=tpg%2Facess2.git diff --git a/Usermode/Libraries/ld-acess.so_src/elf.c b/Usermode/Libraries/ld-acess.so_src/elf.c index 13347a64..27cf96c1 100644 --- a/Usermode/Libraries/ld-acess.so_src/elf.c +++ b/Usermode/Libraries/ld-acess.so_src/elf.c @@ -15,6 +15,7 @@ #include "common.h" #include +#include #include "elf32.h" #include "elf64.h" @@ -43,6 +44,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename); int elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff); int elf_doRelocate_unk(uint32_t , uint32_t *, Elf32_Addr , int , int , const char *, intptr_t); #ifdef SUPPORT_ELF64 +int _Elf64DoReloc_X86_64(void *Base, const char *strtab, Elf64_Sym *symtab, Elf64_Xword r_info, void *ptr, Elf64_Sxword addend); void *Elf64Relocate(void *Base, char **envp, const char *Filename); int Elf64GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size); #endif @@ -204,12 +206,10 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) { Elf32_Ehdr *hdr = Base; Elf32_Phdr *phtab; - int i, j; // Counters char *libPath; intptr_t iRealBase = -1; intptr_t iBaseDiff; int iSegmentCount; -// int iSymCount; Elf32_Rel *rel = NULL; Elf32_Rela *rela = NULL; void *plt = NULL; @@ -229,20 +229,24 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) // Parse Program Header to get Dynamic Table phtab = (void*)( (uintptr_t)Base + hdr->phoff ); iSegmentCount = hdr->phentcount; - for(i=0;i phtab[i].VAddr) - iRealBase = phtab[i].VAddr; - - // Find Dynamic Section - if(phtab[i].Type == PT_DYNAMIC) { - if(dynamicTab) { + switch(phtab[i].Type) + { + case PT_LOAD: + // Determine linked base address + if( iRealBase > phtab[i].VAddr) + iRealBase = phtab[i].VAddr; + break; + case PT_DYNAMIC: + // Find Dynamic Section + if(!dynamicTab) { + dynamicTab = (void *) (intptr_t) phtab[i].VAddr; + } + else { DEBUGS(" WARNING - elf_relocate: Multiple PT_DYNAMIC segments"); - continue; } - dynamicTab = (void *) (intptr_t) phtab[i].VAddr; - j = i; // Save Dynamic Table ID + break; } } @@ -263,7 +267,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) // Allow writing to read-only segments, just in case they need to be relocated // - Will be reversed at the end of the function - for( i = 0; i < iSegmentCount; i ++ ) + for( int i = 0; i < iSegmentCount; i ++ ) { if(phtab[i].Type == PT_LOAD && !(phtab[i].Flags & PF_W) ) { uintptr_t addr = phtab[i].VAddr + iBaseDiff; @@ -278,7 +282,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) // === Get Symbol table and String Table === dynsymtab = NULL; - for( j = 0; dynamicTab[j].d_tag != DT_NULL; j++) + for( int j = 0; dynamicTab[j].d_tag != DT_NULL; j++) { switch(dynamicTab[j].d_tag) { @@ -286,19 +290,19 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) case DT_SYMTAB: DEBUGS(" elf_relocate: DYNAMIC Symbol Table 0x%x (0x%x)", dynamicTab[j].d_val, dynamicTab[j].d_val + iBaseDiff); - if(iBaseDiff != 0) dynamicTab[j].d_val += iBaseDiff; - dynsymtab = (void*)(intptr_t)dynamicTab[j].d_val; + dynsymtab = (void*)((intptr_t)dynamicTab[j].d_val + iBaseDiff); + //if(iBaseDiff != 0) dynamicTab[j].d_val += iBaseDiff; break; // --- String Table --- case DT_STRTAB: DEBUGS(" elf_relocate: DYNAMIC String Table 0x%x (0x%x)", dynamicTab[j].d_val, dynamicTab[j].d_val + iBaseDiff); - if(iBaseDiff != 0) dynamicTab[j].d_val += iBaseDiff; - dynstrtab = (void*)(intptr_t)dynamicTab[j].d_val; + dynstrtab = (void*)((intptr_t)dynamicTab[j].d_val + iBaseDiff); + //if(iBaseDiff != 0) dynamicTab[j].d_val += iBaseDiff; break; // --- Hash Table -- case DT_HASH: - if(iBaseDiff != 0) dynamicTab[j].d_val += iBaseDiff; + //if(iBaseDiff != 0) dynamicTab[j].d_val += iBaseDiff; // iSymCount = ((Elf32_Word*)(intptr_t)dynamicTab[j].d_val)[1]; break; } @@ -314,7 +318,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) // === Parse Relocation Data === DEBUGS(" elf_relocate: dynamicTab = 0x%x", dynamicTab); - for( j = 0; dynamicTab[j].d_tag != DT_NULL; j++) + for( int j = 0; dynamicTab[j].d_tag != DT_NULL; j++) { switch(dynamicTab[j].d_tag) { @@ -325,6 +329,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) // --- Needed Library --- case DT_NEEDED: libPath = dynstrtab + dynamicTab[j].d_val; + DEBUGS(" dynstrtab = %p, d_val = 0x%x", dynstrtab, dynamicTab[j].d_val); DEBUGS(" Required Library '%s'", libPath); if(LoadLibrary(libPath, NULL, envp) == 0) { #if DEBUG @@ -397,8 +402,8 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) { Elf32_Word *ptr; DEBUGS(" elf_relocate: rel=0x%x, relSz=0x%x, relEntSz=0x%x", rel, relSz, relEntSz); - j = relSz / relEntSz; - for( i = 0; i < j; i++ ) + int max = relSz / relEntSz; + for( int i = 0; i < max; i++ ) { //DEBUGS(" Rel %i: 0x%x+0x%x", i, iBaseDiff, rel[i].r_offset); ptr = (void*)(iBaseDiff + rel[i].r_offset); @@ -410,8 +415,8 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) { Elf32_Word *ptr; DEBUGS(" elf_relocate: rela=0x%x, relaSz=0x%x, relaEntSz=0x%x", rela, relaSz, relaEntSz); - j = relaSz / relaEntSz; - for( i = 0; i < j; i++ ) + int count = relaSz / relaEntSz; + for( int i = 0; i < count; i++ ) { ptr = (void*)(iBaseDiff + rela[i].r_offset); fail |= _doRelocate(rel[i].r_info, ptr, 1, rela[i].r_addend); @@ -426,9 +431,9 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) if(pltType == DT_REL) { Elf32_Rel *pltRel = plt; - j = pltSz / sizeof(Elf32_Rel); - DEBUGS(" elf_relocate: PLT Reloc Type = Rel, %i entries", j); - for(i=0;iphoff ); - for( i = 0; i < hdr->phentcount; i ++ ) + for( int i = 0; i < hdr->phentcount; i ++ ) { if(phtab[i].Type == PT_LOAD && iBaseDiff > phtab[i].VAddr) iBaseDiff = phtab[i].VAddr; @@ -500,20 +504,20 @@ int Elf32GetSymbol(void *Base, const char *Name, void **ret, size_t *Size) } iBaseDiff = (intptr_t)Base - iBaseDiff; // Make iBaseDiff actually the diff dynTab = (void*)( (intptr_t)dynTab + iBaseDiff ); - for( i = 0; dynTab[i].d_tag != DT_NULL; i++) + for( int i = 0; dynTab[i].d_tag != DT_NULL; i++) { switch(dynTab[i].d_tag) { // --- Symbol Table --- case DT_SYMTAB: - symtab = (void*)(intptr_t) dynTab[i].d_val; // Rebased in Relocate + symtab = (void*)((intptr_t)dynTab[i].d_val + iBaseDiff); // Rebased in Relocate break; case DT_STRTAB: - dynstrtab = (void*)(intptr_t) dynTab[i].d_val; + dynstrtab = (void*)((intptr_t)dynTab[i].d_val + iBaseDiff); break; // --- Hash Table -- case DT_HASH: - pBuckets = (void*)(intptr_t) dynTab[i].d_val; + pBuckets = (void*)((intptr_t)dynTab[i].d_val + iBaseDiff); break; } } @@ -544,33 +548,69 @@ int Elf32GetSymbol(void *Base, const char *Name, void **ret, size_t *Size) // iSymCount = pBuckets[1]; pBuckets = &pBuckets[2]; pChains = &pBuckets[ nbuckets ]; + assert(pChains); // Get hash iNameHash = ElfHashString(Name); iNameHash %= nbuckets; // Walk Chain - i = pBuckets[ iNameHash ]; - if(symtab[i].shndx != SHN_UNDEF && strcmp(dynstrtab + symtab[i].nameOfs, Name) == 0) { - *ret = (void*)( (uintptr_t) symtab[ i ].value + iBaseDiff ); - if(Size) *Size = symtab[i].size; - return 1; - } - - while(pChains[i] != STN_UNDEF) - { - i = pChains[i]; - if(symtab[i].shndx != SHN_UNDEF && strcmp(dynstrtab + symtab[ i ].nameOfs, Name) == 0) { - *ret = (void*)( (uintptr_t)symtab[ i ].value + iBaseDiff ); - if(Size) *Size = symtab[i].size; + int idx = pBuckets[ iNameHash ]; + do { + Elf32_Sym *sym = &symtab[idx]; + assert(sym); + if(sym->shndx != SHN_UNDEF && strcmp(dynstrtab + sym->nameOfs, Name) == 0) { + *ret = (void*)( (uintptr_t)sym->value + iBaseDiff ); + if(Size) *Size = sym->size; return 1; } - } + } while( (idx = pChains[idx]) != STN_UNDEF && idx != pBuckets[iNameHash] ); return 0; } #ifdef SUPPORT_ELF64 +typedef int (*t_elf64_doreloc)(void *Base, const char *strtab, Elf64_Sym *symtab, Elf64_Xword r_info, void *ptr, Elf64_Sxword addend); + +int _Elf64DoReloc_X86_64(void *Base, const char *strtab, Elf64_Sym *symtab, Elf64_Xword r_info, void *ptr, Elf64_Sxword addend) +{ + int sym = ELF64_R_SYM(r_info); + int type = ELF64_R_TYPE(r_info); + const char *symname = strtab + symtab[sym].st_name; + void *symval; + //DEBUGS("_Elf64DoReloc: %s", symname); + switch( type ) + { + case R_X86_64_NONE: + break; + case R_X86_64_64: + if( !GetSymbol(symname, &symval, NULL) ) return 1; + *(uint64_t*)ptr = (uintptr_t)symval + addend; + break; + case R_X86_64_COPY: { + size_t size; + if( !GetSymbol(symname, &symval, &size) ) return 1; + memcpy(ptr, symval, size); + } break; + case R_X86_64_GLOB_DAT: + if( !GetSymbol(symname, &symval, NULL) ) return 1; + *(uint64_t*)ptr = (uintptr_t)symval; + break; + case R_X86_64_JUMP_SLOT: + if( !GetSymbol(symname, &symval, NULL) ) return 1; + *(uint64_t*)ptr = (uintptr_t)symval; + break; + case R_X86_64_RELATIVE: + *(uint64_t*)ptr = (uintptr_t)Base + addend; + break; + default: + SysDebug("ld-acess - _Elf64DoReloc: Unknown relocation type %i", type); + return 2; + } + //DEBUGS("_Elf64DoReloc: - Good"); + return 0; +} + void *Elf64Relocate(void *Base, char **envp, const char *Filename) { int i; @@ -711,45 +751,8 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename) } // Relocation function - auto int _Elf64DoReloc(Elf64_Xword r_info, void *ptr, Elf64_Sxword addend); - int _Elf64DoReloc(Elf64_Xword r_info, void *ptr, Elf64_Sxword addend) - { - int sym = ELF64_R_SYM(r_info); - int type = ELF64_R_TYPE(r_info); - const char *symname = strtab + symtab[sym].st_name; - void *symval; - //DEBUGS("_Elf64DoReloc: %s", symname); - switch( type ) - { - case R_X86_64_NONE: - break; - case R_X86_64_64: - if( !GetSymbol(symname, &symval, NULL) ) return 1; - *(uint64_t*)ptr = (uintptr_t)symval + addend; - break; - case R_X86_64_COPY: { - size_t size; - if( !GetSymbol(symname, &symval, &size) ) return 1; - memcpy(ptr, symval, size); - } break; - case R_X86_64_GLOB_DAT: - if( !GetSymbol(symname, &symval, NULL) ) return 1; - *(uint64_t*)ptr = (uintptr_t)symval; - break; - case R_X86_64_JUMP_SLOT: - if( !GetSymbol(symname, &symval, NULL) ) return 1; - *(uint64_t*)ptr = (uintptr_t)symval; - break; - case R_X86_64_RELATIVE: - *(uint64_t*)ptr = (uintptr_t)Base + addend; - break; - default: - SysDebug("ld-acess - _Elf64DoReloc: Unknown relocation type %i", type); - return 2; - } - //DEBUGS("_Elf64DoReloc: - Good"); - return 0; - } + t_elf64_doreloc fpElf64DoReloc = &_Elf64DoReloc_X86_64; + #define _Elf64DoReloc(info, ptr, addend) fpElf64DoReloc(Base, strtab, symtab, info, ptr, addend) int fail = 0; if( rel )