X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Usermode%2FLibraries%2Fld-acess.so_src%2Felf.c;h=27cf96c1a7f4af6748a3ad1179f207c974c6aecc;hb=b7d9f86f7a1c23be18b50d5c647fd5d3c08369c3;hp=0b3656b26a44ed4745b2595a360074eef5227029;hpb=1409c5235c5228061ba6605fc1f41302f4f3fe78;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 0b3656b2..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" @@ -41,7 +42,9 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename); int Elf32GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size); int elf_doRelocate_386(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff); 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 @@ -194,16 +197,19 @@ int elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int ty return 0; } +int elf_doRelocate_unk(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff) +{ + return 1; +} + 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; @@ -214,7 +220,6 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) char *dynstrtab = NULL; // .dynamic String Table Elf32_Sym *dynsymtab; int (*do_relocate)(uint32_t t_info, uint32_t *ptr, Elf32_Addr addend, int Type, int bRela, const char *Sym, intptr_t iBaseDiff); - auto int _doRelocate(uint32_t r_info, uint32_t *ptr, int bRela, Elf32_Addr addend); DEBUGS("ElfRelocate: (Base=0x%x)", Base); @@ -224,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; } } @@ -258,13 +267,13 @@ 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; uintptr_t end = addr + phtab[i].MemSize; for( ; addr < end; addr += PAGE_SIZE ) - SysSetMemFlags(addr, 0, 1); // Unset RO + _SysSetMemFlags(addr, 0, 1); // Unset RO } } @@ -272,7 +281,8 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) dynamicTab = (void *)( (intptr_t)dynamicTab + iBaseDiff ); // === Get Symbol table and String Table === - for( j = 0; dynamicTab[j].d_tag != DT_NULL; j++) + dynsymtab = NULL; + for( int j = 0; dynamicTab[j].d_tag != DT_NULL; j++) { switch(dynamicTab[j].d_tag) { @@ -280,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; } @@ -308,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) { @@ -319,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 @@ -363,13 +374,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) DEBUGS(" elf_relocate: Beginning Relocation"); - int _doRelocate(uint32_t r_info, uint32_t *ptr, int bRela, Elf32_Addr addend) - { - int type = ELF32_R_TYPE(r_info); - int sym = ELF32_R_SYM(r_info); - const char *symname = dynstrtab + dynsymtab[sym].nameOfs; - return do_relocate(r_info, ptr, addend, type, bRela, symname, iBaseDiff); - } + int fail = 0; switch(hdr->machine) { @@ -381,21 +386,24 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) break; default: SysDebug("Elf32Relocate: Unknown machine type %i", hdr->machine); - // TODO: Chuck sad + do_relocate = elf_doRelocate_unk; + fail = 1; break; } DEBUGS("do_relocate = %p (%p or %p)", do_relocate, &elf_doRelocate_386, &elf_doRelocate_arm); - int fail = 0; + #define _doRelocate(r_info, ptr, bRela, addend) \ + do_relocate(r_info, ptr, addend, ELF32_R_TYPE(r_info), bRela, \ + dynstrtab + dynsymtab[ELF32_R_SYM(r_info)].nameOfs, iBaseDiff); // Parse Relocation Entries if(rel && relSz) { 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); @@ -407,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); @@ -423,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;ientrypoint + iBaseDiff, __builtin_return_address(0)); return (void*)(intptr_t)( hdr->entrypoint + iBaseDiff ); } @@ -477,11 +487,10 @@ int Elf32GetSymbol(void *Base, const char *Name, void **ret, size_t *Size) uintptr_t iBaseDiff = -1; Elf32_Phdr *phtab; Elf32_Dyn *dynTab = NULL; - int i; // Locate the tables phtab = (void*)( (uintptr_t)Base + hdr->phoff ); - 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; @@ -495,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; } } @@ -539,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; @@ -706,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 )