-#endif\r
-\r
-// === PROTOTYPES ===\r
-void elf_doRelocate(Uint r_info, Uint32 *ptr, Uint32 addend, Elf32_Sym *symtab, Uint base);\r
-Uint ElfHashString(char *name);\r
-\r
-// === CODE ===\r
-/**\r
- \fn int ElfRelocate(void *Base, char **envp, char *Filename)\r
- \brief Relocates a loaded ELF Executable\r
-*/\r
-int ElfRelocate(void *Base, char **envp, char *Filename)\r
-{\r
- Elf32_Ehdr *hdr = Base;\r
- Elf32_Phdr *phtab;\r
- int i, j; // Counters\r
- char *libPath;\r
- Uint iRealBase = -1;\r
- Uint iBaseDiff;\r
- int iSegmentCount;\r
- int iSymCount;\r
- Elf32_Rel *rel = NULL;\r
- Elf32_Rela *rela = NULL;\r
- Uint32 *pltgot = NULL;\r
- void *plt = NULL;\r
- int relSz=0, relEntSz=8;\r
- int relaSz=0, relaEntSz=8;\r
- int pltSz=0, pltType=0;\r
- Elf32_Dyn *dynamicTab = NULL; // Dynamic Table Pointer\r
- char *dynstrtab = NULL; // .dynamic String Table\r
- Elf32_Sym *dynsymtab;\r
- \r
- DEBUGS("ElfRelocate: (Base=0x%x)\n", Base);\r
- \r
- // Parse Program Header to get Dynamic Table\r
- phtab = Base + hdr->phoff;\r
- iSegmentCount = hdr->phentcount;\r
- for(i=0;i<iSegmentCount;i++)\r
- {\r
- // Determine linked base address\r
- if(phtab[i].Type == PT_LOAD && iRealBase > phtab[i].VAddr)\r
- iRealBase = phtab[i].VAddr;\r
- \r
- // Find Dynamic Section\r
- if(phtab[i].Type == PT_DYNAMIC) {\r
- if(dynamicTab) {\r
- DEBUGS(" WARNING - elf_relocate: Multiple PT_DYNAMIC segments\n");\r
- continue;\r
- }\r
- dynamicTab = (void *) phtab[i].VAddr;\r
- j = i; // Save Dynamic Table ID\r
- }\r
- }\r
- \r
- // Page Align real base\r
- iRealBase &= ~0xFFF;\r
- DEBUGS(" elf_relocate: True Base = 0x%x, Compiled Base = 0x%x\n", Base, iRealBase);\r
- \r
- // Adjust "Real" Base\r
- iBaseDiff = (Uint)Base - iRealBase;\r
- \r
- hdr->entrypoint += iBaseDiff; // Adjust Entrypoint\r
- \r
- // Check if a PT_DYNAMIC segement was found\r
- if(!dynamicTab) {\r
- SysDebug(" elf_relocate: No PT_DYNAMIC segment in image, returning\n");\r
- return hdr->entrypoint;\r
- }\r
- \r
- // Adjust Dynamic Table\r
- dynamicTab = (void *) ((Uint)dynamicTab + iBaseDiff);\r
+#endif
+
+// === PROTOTYPES ===
+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 ===
+/**
+ * \fn int ElfRelocate(void *Base, char **envp, const char *Filename)
+ * \brief Relocates a loaded ELF Executable
+ */
+void *ElfRelocate(void *Base, char **envp, const char *Filename)
+{
+ Elf32_Ehdr *hdr = Base;
+
+ switch(hdr->e_ident[4])
+ {
+ case ELFCLASS32:
+ return Elf32Relocate(Base, envp, Filename);
+ case ELFCLASS64:
+ return Elf64Relocate(Base, envp, Filename);
+ default:
+ SysDebug("ld-acess - ElfRelocate: Unknown file class %i", hdr->e_ident[4]);
+ return NULL;
+ }
+}
+
+void *Elf64Relocate(void *Base, char **envp, const char *Filename)
+{
+ int i;
+ Elf64_Ehdr *hdr = Base;
+ Elf64_Phdr *phtab;
+ Elf64_Dyn *dyntab;
+ Elf64_Addr compiledBase = -1, baseDiff;
+ Elf64_Sym *symtab = NULL;
+ char *strtab = NULL;
+ Elf64_Word *hashtab = NULL;
+ Elf64_Rel *rel = NULL;
+ int rel_count = 0;
+ Elf64_Rela *rela = NULL;
+ int rela_count = 0;
+ void *pltrel = NULL;
+ int plt_size = 0, plt_type = 0;
+
+ DEBUGS("Elf64Relocate: hdr = {");
+ DEBUGS("Elf64Relocate: e_ident = '%.16s'", hdr->e_ident);
+ DEBUGS("Elf64Relocate: e_type = 0x%x", hdr->e_type);
+ DEBUGS("Elf64Relocate: e_machine = 0x%x", hdr->e_machine);
+ DEBUGS("Elf64Relocate: e_version = 0x%x", hdr->e_version);
+ DEBUGS("Elf64Relocate: e_entry = %p", hdr->e_entry);
+ DEBUGS("Elf64Relocate: e_phoff = 0x%llx", hdr->e_phoff);
+ DEBUGS("Elf64Relocate: e_shoff = 0x%llx", hdr->e_shoff);
+ DEBUGS("Elf64Relocate: e_flags = 0x%x", hdr->e_flags);
+ DEBUGS("Elf64Relocate: e_ehsize = 0x%x", hdr->e_ehsize);
+ DEBUGS("Elf64Relocate: e_phentsize = 0x%x", hdr->e_phentsize);
+ DEBUGS("Elf64Relocate: e_phnum = %i", hdr->e_phnum);
+
+ // Scan for the dynamic table (and find the compiled base)
+ phtab = Base + hdr->e_phoff;
+ for( i = 0; i < hdr->e_phnum; i ++ )
+ {
+ if(phtab[i].p_type == PT_DYNAMIC)
+ dyntab = (void *)(intptr_t)phtab[i].p_vaddr;
+ if(phtab[i].p_type == PT_LOAD && compiledBase > phtab[i].p_vaddr)
+ compiledBase = phtab[i].p_vaddr;
+ }
+
+ baseDiff = (Elf64_Addr)Base - compiledBase;
+
+ DEBUGS("baseDiff = %p", baseDiff);
+
+ if(dyntab == NULL) {
+ SysDebug(" Elf64Relocate: No PT_DYNAMIC segment in image %p, returning", Base);
+ return (void *)(hdr->e_entry + baseDiff);
+ }
+
+ dyntab = (void *)((Elf64_Addr)dyntab + baseDiff);
+
+ // Parse the dynamic table (first pass)
+ // - Search for String, Symbol and Hash tables
+ for(i = 0; dyntab[i].d_tag != DT_NULL; i ++)
+ {
+ switch(dyntab[i].d_tag)
+ {
+ case DT_SYMTAB:
+ dyntab[i].d_un.d_ptr += baseDiff;
+ symtab = (void *)dyntab[i].d_un.d_ptr;
+ break;
+ case DT_STRTAB:
+ dyntab[i].d_un.d_ptr += baseDiff;
+ strtab = (void *)dyntab[i].d_un.d_ptr;
+ break;
+ case DT_HASH:
+ dyntab[i].d_un.d_ptr += baseDiff;
+ hashtab = (void *)dyntab[i].d_un.d_ptr;
+ break;
+ }
+ }
+
+ if( !symtab || !strtab || !hashtab ) {
+ SysDebug("ld-acess - Elf64Relocate: Missing Symbol, string or hash table");
+ return NULL;
+ }
+
+ // Ready for symbol use
+ AddLoaded( Filename, Base );
+
+ // Second pass on dynamic table
+ for(i = 0; dyntab[i].d_tag != DT_NULL; i ++)
+ {
+ DEBUGS("dyntab[%i].d_tag = %i", i, dyntab[i].d_tag);
+ switch(dyntab[i].d_tag)
+ {
+ case DT_SONAME: break;
+
+ case DT_NEEDED: {
+ char *libPath = strtab + dyntab[i].d_un.d_val;
+ DEBUGS("Elf64Relocate: libPath = '%s'", libPath);
+ if(LoadLibrary(libPath, NULL, envp) == 0) {
+ SysDebug("ld-acess - Elf64Relocate: Unable to load '%s'", libPath);
+ return NULL;
+ }
+ } break;
+
+ // Relocation entries
+ case DT_REL:
+ dyntab[i].d_un.d_ptr += baseDiff;
+ rel = (void *)dyntab[i].d_un.d_ptr;
+ break;
+ case DT_RELSZ:
+ rel_count = dyntab[i].d_un.d_val / sizeof(Elf64_Rel);
+ break;
+ case DT_RELENT:
+ if( dyntab[i].d_un.d_val != sizeof(Elf64_Rel) ) {
+ SysDebug("ld-acess - Elf64Relocate: DT_RELENT(%i) != sizeof(Elf64_Rel)(%i)",
+ dyntab[i].d_un.d_val, sizeof(Elf64_Rel));
+ return NULL;
+ }
+ break;
+ case DT_RELA:
+ dyntab[i].d_un.d_ptr += baseDiff;
+ rela = (void *)dyntab[i].d_un.d_ptr;
+ break;
+ case DT_RELASZ:
+ rela_count = dyntab[i].d_un.d_val / sizeof(Elf64_Rela);
+ break;
+ case DT_RELAENT:
+ if( dyntab[i].d_un.d_val != sizeof(Elf64_Rela) ) {
+ SysDebug("ld-acess - Elf64Relocate: DT_RELAENT(%i) != sizeof(Elf64_Rela)(%i)",
+ dyntab[i].d_un.d_val, sizeof(Elf64_Rela));
+ return NULL;
+ }
+ break;
+ case DT_JMPREL:
+ dyntab[i].d_un.d_ptr += baseDiff;
+ pltrel = (void *)dyntab[i].d_un.d_ptr;
+ break;
+ case DT_PLTREL:
+ plt_type = dyntab[i].d_un.d_val;
+ break;
+ case DT_PLTRELSZ:
+ plt_size = dyntab[i].d_un.d_val;
+ break;
+ }
+ }
+
+ // Relocation function
+ void _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;
+ switch( type )
+ {
+ 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:
+ 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;
+ }
+ }
+
+ if( rel )
+ {
+ DEBUGS("rel_count = %i", rel_count);
+ for( i = 0; i < rel_count; i ++ )
+ {
+ uint64_t *ptr = (void *)( rel[i].r_offset + baseDiff );
+ _Elf64DoReloc( rel[i].r_info, ptr, *ptr);
+ }
+ }
+
+ if( rela )
+ {
+ DEBUGS("rela_count = %i", rela_count);
+ for( i = 0; i < rela_count; i ++ )
+ {
+ _Elf64DoReloc( rela[i].r_info, (void *)( rela[i].r_offset + baseDiff ), rela[i].r_addend );
+ }
+ }
+
+ if( pltrel && plt_type )
+ {
+ if( plt_type == DT_REL ) {
+ Elf64_Rel *plt = pltrel;
+ int count = plt_size / sizeof(Elf64_Rel);
+ DEBUGS("plt rel count = %i", count);
+ for( i = 0; i < count; i ++ )
+ {
+ uint64_t *ptr = (void *)( plt[i].r_offset + baseDiff );
+ _Elf64DoReloc( plt[i].r_info, ptr, *ptr);
+ }
+ }
+ else {
+ Elf64_Rela *plt = pltrel;
+ int count = plt_size / sizeof(Elf64_Rela);
+ DEBUGS("plt rela count = %i", count);
+ for( i = 0; i < count; i ++ )
+ {
+ _Elf64DoReloc( plt[i].r_info, (void *)(plt[i].r_offset + baseDiff), plt[i].r_addend);
+ }
+ }
+ }
+
+ DEBUGS("Elf64Relocate: Relocations done, return %p", (void *)(hdr->e_entry + baseDiff));
+ return (void *)(hdr->e_entry + baseDiff);
+}
+
+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;
+ Uint32 *pltgot = NULL;
+ void *plt = NULL;
+ int relSz=0, relEntSz=8;
+ int relaSz=0, relaEntSz=8;
+ int pltSz=0, pltType=0;
+ Elf32_Dyn *dynamicTab = NULL; // Dynamic Table Pointer
+ char *dynstrtab = NULL; // .dynamic String Table
+ Elf32_Sym *dynsymtab;
+
+ DEBUGS("ElfRelocate: (Base=0x%x)", Base);