From 032ec5adf8d4faeaa9293da50ad2e32c83dd1704 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Wed, 19 Oct 2011 12:29:12 +0800 Subject: [PATCH] Usermode/ld-acess - Implemented R_836_COPY and R_X86_64_COPY --- Usermode/Libraries/ld-acess.so_src/common.h | 11 ++-- Usermode/Libraries/ld-acess.so_src/elf.c | 60 ++++++++++++-------- Usermode/Libraries/ld-acess.so_src/lib.c | 7 +++ Usermode/Libraries/ld-acess.so_src/loadlib.c | 12 ++-- Usermode/Libraries/ld-acess.so_src/main.c | 2 - Usermode/Libraries/ld-acess.so_src/pe.c | 15 +++-- 6 files changed, 66 insertions(+), 41 deletions(-) diff --git a/Usermode/Libraries/ld-acess.so_src/common.h b/Usermode/Libraries/ld-acess.so_src/common.h index d44008f1..379efc11 100644 --- a/Usermode/Libraries/ld-acess.so_src/common.h +++ b/Usermode/Libraries/ld-acess.so_src/common.h @@ -39,8 +39,8 @@ extern void *DoRelocate(void *Base, char **envp, const char *Filename); // === Library/Symbol Manipulation == extern void *LoadLibrary(const char *Filename, const char *SearchDir, char **envp); extern void AddLoaded(const char *File, void *base); -extern void *GetSymbol(const char *name); -extern int GetSymbolFromBase(void *base, const char *name, void **ret); +extern void *GetSymbol(const char *name, size_t *size); +extern int GetSymbolFromBase(void *base, const char *name, void **ret, size_t *size); // === Library Functions === extern char *strcpy(char *dest, const char *src); @@ -48,6 +48,7 @@ extern char *strcat(char *dest, const char *src); extern int strcmp(const char *s1, const char *s2); extern int strlen(const char *str); extern int file_exists(const char *filename); +extern void *memcpy(void *dest, const void *src, size_t len); // === System Calls === extern void _exit(int retval); @@ -60,9 +61,11 @@ extern int open(const char *filename, int flags); extern int close(int fd); // === ELF Loader === -extern int ElfGetSymbol(void *Base, const char *name, void **ret); +extern void *ElfRelocate(void *Base, char **envp, const char *Filename); +extern int ElfGetSymbol(void *Base, const char *name, void **ret, size_t *Size); // === PE Loader === -extern int PE_GetSymbol(void *Base, const char *Name, void **ret); +extern void *PE_Relocate(void *Base, char **envp, const char *Filename); +extern int PE_GetSymbol(void *Base, const char *Name, void **ret, size_t *Size); #endif diff --git a/Usermode/Libraries/ld-acess.so_src/elf.c b/Usermode/Libraries/ld-acess.so_src/elf.c index f14205e0..582c67ae 100644 --- a/Usermode/Libraries/ld-acess.so_src/elf.c +++ b/Usermode/Libraries/ld-acess.so_src/elf.c @@ -27,12 +27,12 @@ static const char *csaR_NAMES[] = {"R_386_NONE", "R_386_32", "R_386_PC32", "R_38 // === PROTOTYPES === void *ElfRelocate(void *Base, char **envp, const char *Filename); - int ElfGetSymbol(void *Base, const char *Name, void **Ret); + int ElfGetSymbol(void *Base, const char *Name, void **Ret, size_t *Size); void *Elf32Relocate(void *Base, char **envp, const char *Filename); - int Elf32GetSymbol(void *Base, const char *Name, void **Ret); + int Elf32GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size); #ifdef SUPPORT_ELF64 void *Elf64Relocate(void *Base, char **envp, const char *Filename); - int Elf64GetSymbol(void *Base, const char *Name, void **Ret); + int Elf64GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size); #endif Uint32 ElfHashString(const char *name); @@ -62,17 +62,17 @@ void *ElfRelocate(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) +int ElfGetSymbol(void *Base, const char *Name, void **ret, size_t *Size) { Elf32_Ehdr *hdr = Base; switch(hdr->e_ident[4]) { case ELFCLASS32: - return Elf32GetSymbol(Base, Name, ret); + return Elf32GetSymbol(Base, Name, ret, Size); #ifdef SUPPORT_ELF64 case ELFCLASS64: - return Elf64GetSymbol(Base, Name, ret); + return Elf64GetSymbol(Base, Name, ret, Size); #endif default: SysDebug("ld-acess - ElfRelocate: Unknown file class %i", hdr->e_ident[4]); @@ -155,26 +155,26 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) 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*)(dynamicTab[j].d_val); + dynsymtab = (void*)(intptr_t)dynamicTab[j].d_val; 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*)(dynamicTab[j].d_val); + dynstrtab = (void*)(intptr_t)dynamicTab[j].d_val; break; // --- Hash Table -- case DT_HASH: if(iBaseDiff != 0) dynamicTab[j].d_val += iBaseDiff; - iSymCount = ((Elf32_Word*)(dynamicTab[j].d_val))[1]; + iSymCount = ((Elf32_Word*)(intptr_t)dynamicTab[j].d_val)[1]; break; } } if(dynsymtab == NULL) { SysDebug("ld-acess.so - WARNING: No Dynamic Symbol table in %p, returning", hdr); - return (void *) hdr->entrypoint + iBaseDiff; + return (void *)(intptr_t) (hdr->entrypoint + iBaseDiff); } // === Add to loaded list (can be imported now) === @@ -244,7 +244,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) { // Standard 32 Bit Relocation (S+A) case R_386_32: - val = (intptr_t) GetSymbol( Sym ); + val = (intptr_t) GetSymbol(Sym, NULL); DEBUGS(" elf_doRelocate: R_386_32 *0x%x += 0x%x('%s')", ptr, val, Sym); *ptr = val + addend; @@ -253,7 +253,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) // 32 Bit Relocation wrt. Offset (S+A-P) case R_386_PC32: DEBUGS(" elf_doRelocate: '%s'", Sym); - val = (intptr_t) GetSymbol( Sym ); + val = (intptr_t) GetSymbol(Sym, NULL); DEBUGS(" elf_doRelocate: R_386_PC32 *0x%x = 0x%x + 0x%x - 0x%x", ptr, *ptr, val, (intptr_t)ptr ); *ptr = val + addend - (intptr_t)ptr; @@ -264,7 +264,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) case R_386_GLOB_DAT: case R_386_JMP_SLOT: DEBUGS(" elf_doRelocate: '%s'", Sym); - val = (intptr_t) GetSymbol( Sym ); + val = (intptr_t) GetSymbol( Sym, NULL ); DEBUGS(" elf_doRelocate: %s *0x%x = 0x%x", csaR_NAMES[type], ptr, val); *ptr = val; break; @@ -274,7 +274,14 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) DEBUGS(" elf_doRelocate: R_386_RELATIVE *0x%x = 0x%x + 0x%x", ptr, iBaseDiff, addend); *ptr = iBaseDiff + addend; break; - + + case R_386_COPY: { + size_t size; + void *src = GetSymbol(Sym, &size); + DEBUGS(" elf_doRelocate_386: R_386_COPY (%p, %p, %i)", ptr, val, size); + memcpy(ptr, src, size); + break; } + default: SysDebug("elf_doRelocate_386: Unknown relocation %i", type); break; @@ -289,7 +296,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) // (S + A) | T case R_ARM_GLOB_DAT: case R_ARM_JUMP_SLOT: - val = (intptr_t)GetSymbol(Sym); + val = (intptr_t)GetSymbol(Sym, NULL); *ptr = val + addend; break; default: @@ -375,10 +382,10 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) } DEBUGS("ElfRelocate: RETURN 0x%x", hdr->entrypoint + iBaseDiff); - return (void*)hdr->entrypoint + iBaseDiff; + return (void*)(intptr_t)( hdr->entrypoint + iBaseDiff ); } -int Elf32GetSymbol(void *Base, const char *Name, void **ret) +int Elf32GetSymbol(void *Base, const char *Name, void **ret, size_t *Size) { Elf32_Ehdr *hdr = Base; Elf32_Sym *symtab; @@ -440,6 +447,7 @@ int Elf32GetSymbol(void *Base, const char *Name, void **ret) i = pBuckets[ iNameHash ]; if(symtab[i].shndx != SHN_UNDEF && strcmp(dynstrtab + symtab[i].nameOfs, Name) == 0) { *ret = (void*) (intptr_t) symtab[ i ].value + iBaseDiff; + if(Size) *Size = symtab[i].size; return 1; } @@ -448,6 +456,7 @@ int Elf32GetSymbol(void *Base, const char *Name, void **ret) i = pChains[i]; if(symtab[i].shndx != SHN_UNDEF && strcmp(dynstrtab + symtab[ i ].nameOfs, Name) == 0) { *ret = (void*)(intptr_t)symtab[ i ].value + iBaseDiff; + if(Size) *Size = symtab[i].size; return 1; } } @@ -606,15 +615,18 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename) case R_X86_64_NONE: break; case R_X86_64_64: - *(uint64_t*)ptr = (uint64_t)GetSymbol(symname) + addend; - break; - case R_X86_64_COPY: + *(uint64_t*)ptr = (uint64_t)GetSymbol(symname, NULL) + addend; break; + case R_X86_64_COPY: { + size_t size; + void *sym = GetSymbol(symname, &size); + memcpy(ptr, sym, size); + } break; case R_X86_64_GLOB_DAT: - *(uint64_t*)ptr = (uint64_t)GetSymbol(symname); + *(uint64_t*)ptr = (uint64_t)GetSymbol(symname, NULL); break; case R_X86_64_JUMP_SLOT: - *(uint64_t*)ptr = (uint64_t)GetSymbol(symname); + *(uint64_t*)ptr = (uint64_t)GetSymbol(symname, NULL); break; case R_X86_64_RELATIVE: *(uint64_t*)ptr = (intptr_t)Base + addend; @@ -671,7 +683,7 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename) return (void *)(hdr->e_entry + baseDiff); } -int Elf64GetSymbol(void *Base, const char *Name, void **Ret) +int Elf64GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size) { Elf64_Ehdr *hdr = Base; Elf64_Sym *symtab; @@ -744,6 +756,7 @@ int Elf64GetSymbol(void *Base, const char *Name, void **Ret) i = pBuckets[ iNameHash ]; if(symtab[i].st_shndx != SHN_UNDEF && strcmp(dynstrtab + symtab[i].st_name, Name) == 0) { *Ret = (void*) (intptr_t) symtab[i].st_value + iBaseDiff; + if(Size) *Size = symtab[i].st_size; DEBUGS("%s = %p", Name, *Ret); return 1; } @@ -753,6 +766,7 @@ int Elf64GetSymbol(void *Base, const char *Name, void **Ret) i = pChains[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; + if(Size) *Size = symtab[i].st_size; DEBUGS("%s = %p", Name, *Ret); return 1; } diff --git a/Usermode/Libraries/ld-acess.so_src/lib.c b/Usermode/Libraries/ld-acess.so_src/lib.c index 7c8005bc..a3192bc8 100644 --- a/Usermode/Libraries/ld-acess.so_src/lib.c +++ b/Usermode/Libraries/ld-acess.so_src/lib.c @@ -58,6 +58,13 @@ int memcmp(const void *p1, const void *p2, int len) return 0; } +void *memcpy(void *dest, const void *src, size_t len) +{ + uint8_t *d=dest, *s=src; + while(len--) *d++ = *s++; + return dest; +} + /** * \fn int file_exists(char *filename) * \brief Checks if a file exists diff --git a/Usermode/Libraries/ld-acess.so_src/loadlib.c b/Usermode/Libraries/ld-acess.so_src/loadlib.c index b6637c22..eec3dee2 100644 --- a/Usermode/Libraries/ld-acess.so_src/loadlib.c +++ b/Usermode/Libraries/ld-acess.so_src/loadlib.c @@ -15,7 +15,7 @@ // === PROTOTYPES === void *IsFileLoaded(const char *file); - int GetSymbolFromBase(void *base, const char *name, void **ret); + int GetSymbolFromBase(void *base, const char *name, void **ret, size_t *size); // === IMPORTS === extern const struct { @@ -197,7 +197,7 @@ void Unload(void *Base) \fn Uint GetSymbol(const char *name) \brief Gets a symbol value from a loaded library */ -void *GetSymbol(const char *name) +void *GetSymbol(const char *name, size_t *Size) { int i; void *ret; @@ -216,7 +216,7 @@ void *GetSymbol(const char *name) //SysDebug(" GetSymbol: Trying 0x%x, '%s'", // gLoadedLibraries[i].Base, gLoadedLibraries[i].Name); - if(GetSymbolFromBase(gLoadedLibraries[i].Base, name, &ret)) return ret; + if(GetSymbolFromBase(gLoadedLibraries[i].Base, name, &ret, Size)) return ret; } SysDebug("GetSymbol: === Symbol '%s' not found ===", name); return 0; @@ -226,13 +226,13 @@ void *GetSymbol(const char *name) \fn int GetSymbolFromBase(Uint base, char *name, Uint *ret) \breif Gets a symbol from a specified library */ -int GetSymbolFromBase(void *base, const char *name, void **ret) +int GetSymbolFromBase(void *base, const char *name, void **ret, size_t *Size) { uint8_t *hdr = base; if(hdr[0] == 0x7F && hdr[1] == 'E' && hdr[2] == 'L' && hdr[3] == 'F') - return ElfGetSymbol(base, name, ret); + return ElfGetSymbol(base, name, ret, Size); if(hdr[0] == 'M' && hdr[1] == 'Z') - return PE_GetSymbol(base, name, ret); + return PE_GetSymbol(base, name, ret, Size); 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 6ccdc0c1..ff715bb3 100644 --- a/Usermode/Libraries/ld-acess.so_src/main.c +++ b/Usermode/Libraries/ld-acess.so_src/main.c @@ -9,8 +9,6 @@ // === PROTOTYPES === void *DoRelocate(void *base, char **envp, const char *Filename); int CallUser(void *Entry, void *SP); -void *ElfRelocate(void *Base, char **envp, const char *Filename); -void *PE_Relocate(void *Base, char **envp, const char *Filename); // === Imports === extern char gLinkedBase[]; diff --git a/Usermode/Libraries/ld-acess.so_src/pe.c b/Usermode/Libraries/ld-acess.so_src/pe.c index d567ed15..057345cd 100644 --- a/Usermode/Libraries/ld-acess.so_src/pe.c +++ b/Usermode/Libraries/ld-acess.so_src/pe.c @@ -19,12 +19,12 @@ #endif // === PROTOTYPES === - int PE_Relocate(void *Base, char **envp, char *Filename); +void *PE_Relocate(void *Base, char **envp, const char *Filename); char *PE_int_GetTrueFile(char *file); int PE_int_GetForwardSymbol(char *Fwd, void **Value); // === CODE === -int PE_Relocate(void *Base, char *envp[], char *Filename) +void *PE_Relocate(void *Base, char **envp, const char *Filename) { tPE_DOS_HEADER *dosHdr = Base; tPE_IMAGE_HEADERS *peHeaders; @@ -67,7 +67,8 @@ int PE_Relocate(void *Base, char *envp[], char *Filename) void *symPtr = 0; name = (void*)( iBase + importTab[j] ); DEBUGS(" PE_Relocate: Import Name '%s', Hint 0x%x\n", name->Name, name->Hint); - if( GetSymbolFromBase(pLibBase, name->Name, symPtr) == 0 ) { + if( GetSymbolFromBase(pLibBase, name->Name, symPtr, NULL) == 0 ) + { SysDebug("Unable to find symbol '%s' in library '%s'\n", name->Name, impDir[i].DLLName); return 0; } @@ -85,13 +86,13 @@ int PE_Relocate(void *Base, char *envp[], char *Filename) DEBUGS("PE_Relocate: RETURN 0x%x\n", iBase + peHeaders->OptHeader.EntryPoint); - return iBase + peHeaders->OptHeader.EntryPoint; + return (void*)( iBase + peHeaders->OptHeader.EntryPoint ); } /** * \fn int PE_GetSymbol(Uint Base, const char *Name, Uint *Ret) */ -int PE_GetSymbol(void *Base, const char *Name, void **Ret) +int PE_GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size) { tPE_DOS_HEADER *dosHdr = Base; tPE_IMAGE_HEADERS *peHeaders; @@ -129,6 +130,7 @@ int PE_GetSymbol(void *Base, const char *Name, void **Ret) return PE_int_GetForwardSymbol(fwd, Ret); } *Ret = (void*)retVal; + if(Size) *Size = 0; return 1; } } @@ -174,9 +176,10 @@ int PE_int_GetForwardSymbol(char *Fwd, void **Value) DEBUGS(" PE_int_GetForwardSymbol: Get '%s' from '%s'\n", sym, libname); libbase = LoadLibrary(libname, DLL_BASE_PATH, NULL); - ret = GetSymbolFromBase(libbase, sym, Value); + ret = GetSymbolFromBase(libbase, sym, Value, NULL); if(!ret) { SysDebug(" PE_int_GetForwardSymbol: Unable to find '%s' in '%s'\n", sym, libname); + return 0; } Fwd[i] = '.'; return ret; -- 2.20.1