-#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
- // Check magic header\r
- \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);
+ 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, 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
+void *Elf64Relocate(void *Base, char **envp, const char *Filename);
+ int Elf64GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size);
+#endif
+uint32_t 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);
+#ifdef SUPPORT_ELF64
+ case ELFCLASS64:
+ return Elf64Relocate(Base, envp, Filename);
+#endif
+ default:
+ SysDebug("ld-acess - ElfRelocate: Unknown file class %i", hdr->e_ident[4]);
+ return NULL;
+ }
+}
+
+/**
+ * \fn int ElfGetSymbol(Uint 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, Size);
+#ifdef SUPPORT_ELF64
+ case ELFCLASS64:
+ return Elf64GetSymbol(Base, Name, ret, Size);
+#endif
+ default:
+ SysDebug("ld-acess - ElfRelocate: Unknown file class %i", hdr->e_ident[4]);
+ return 0;
+ }
+}
+
+int elf_doRelocate_386(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type,
+ int bRela, const char *Sym, intptr_t iBaseDiff)
+{
+ void *symval;
+ switch( type )
+ {
+ // Standard 32 Bit Relocation (S+A)
+ case R_386_32:
+ if( !GetSymbol(Sym, &symval, NULL) )
+ return 1;
+ DEBUGS(" elf_doRelocate: R_386_32 *0x%x += %p('%s')",
+ ptr, symval, Sym);
+ *ptr = (intptr_t)symval + addend;
+ break;
+
+ // 32 Bit Relocation wrt. Offset (S+A-P)
+ case R_386_PC32:
+ DEBUGS(" elf_doRelocate: '%s'", Sym);
+ if( !GetSymbol(Sym, &symval, NULL) ) return 1;
+ DEBUGS(" elf_doRelocate: R_386_PC32 *0x%x = 0x%x + 0x%p - 0x%x",
+ ptr, *ptr, symval, (intptr_t)ptr );
+ *ptr = (intptr_t)symval + addend - (intptr_t)ptr;
+ //*ptr = val + addend - ((Uint)ptr - iBaseDiff);
+ break;
+
+ // Absolute Value of a symbol (S)
+ case R_386_GLOB_DAT:
+ case R_386_JMP_SLOT:
+ DEBUGS(" elf_doRelocate: '%s'", Sym);
+ if( !GetSymbol(Sym, &symval, NULL) ) return 1;
+ DEBUGS(" elf_doRelocate: %s *0x%x = %p", csaR_NAMES[type], ptr, symval);
+ *ptr = (intptr_t)symval;
+ break;
+
+ // Base Address (B+A)
+ case R_386_RELATIVE:
+ 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;
+ if( !GetSymbol(Sym, &symval, &size) ) return 1;
+ DEBUGS(" elf_doRelocate_386: R_386_COPY (%p, %p, %i)", ptr, symval, size);
+ memcpy(ptr, symval, size);
+ break; }
+
+ default:
+ SysDebug("elf_doRelocate_386: Unknown relocation %i", type);
+ return 2;
+ }
+ return 0;
+}
+
+int elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff)
+{
+ uint32_t val;
+ switch(type)
+ {
+ // (S + A) | T
+ case R_ARM_ABS32:
+ DEBUGS(" elf_doRelocate_arm: R_ARM_ABS32 %p (%s + %x)", ptr, Sym, addend);
+ if( !GetSymbol(Sym, (void**)&val, NULL) ) return 1;
+ *ptr = val + addend;
+ break;
+ case R_ARM_GLOB_DAT:
+ DEBUGS(" elf_doRelocate_arm: R_ARM_GLOB_DAT %p (%s + %x)", ptr, Sym, addend);
+ if( !GetSymbol(Sym, (void**)&val, NULL) ) return 1;
+ *ptr = val + addend;
+ break;
+ case R_ARM_JUMP_SLOT:
+ if(!bRela) addend = 0;
+ DEBUGS(" elf_doRelocate_arm: R_ARM_JUMP_SLOT %p (%s + %x)", ptr, Sym, addend);
+ if( !GetSymbol(Sym, (void**)&val, NULL) ) return 1;
+ *ptr = val + addend;
+ break;
+ // Copy
+ case R_ARM_COPY: {
+ size_t size;
+ void *src;
+ if( !GetSymbol(Sym, &src, &size) ) return 1;
+ DEBUGS(" elf_doRelocate_arm: R_ARM_COPY (%p, %p, %i)", ptr, src, size);
+ memcpy(ptr, src, size);
+ break; }
+ // Delta between link and runtime locations + A
+ case R_ARM_RELATIVE:
+ DEBUGS(" elf_doRelocate_arm: R_ARM_RELATIVE %p (0x%x + 0x%x)", ptr, iBaseDiff, addend);
+ if(Sym[0] != '\0') {
+ // TODO: Get delta for a symbol
+ SysDebug("elf_doRelocate_arm: TODO - Implment R_ARM_RELATIVE for symbols");
+ return 2;
+ }
+ else {
+ *ptr = iBaseDiff + addend;
+ }
+ break;
+ default:
+ SysDebug("elf_doRelocate_arm: Unknown Relocation, %i", type);
+ return 2;
+ }
+ 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;
+ 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;
+ int (*do_relocate)(uint32_t t_info, uint32_t *ptr, Elf32_Addr addend, int Type, int bRela, const char *Sym, intptr_t iBaseDiff);
+
+ DEBUGS("ElfRelocate: (Base=0x%x)", Base);
+
+ // Check magic header
+
+
+ // Parse Program Header to get Dynamic Table
+ phtab = (void*)( (uintptr_t)Base + hdr->phoff );
+ iSegmentCount = hdr->phentcount;
+ for(i=0;i<iSegmentCount;i++)
+ {
+ // Determine linked base address
+ if(phtab[i].Type == PT_LOAD && iRealBase > phtab[i].VAddr)
+ iRealBase = phtab[i].VAddr;
+
+ // Find Dynamic Section
+ if(phtab[i].Type == PT_DYNAMIC) {
+ if(dynamicTab) {
+ DEBUGS(" WARNING - elf_relocate: Multiple PT_DYNAMIC segments");
+ continue;
+ }
+ dynamicTab = (void *) (intptr_t) phtab[i].VAddr;
+ j = i; // Save Dynamic Table ID
+ }
+ }
+
+ // Page Align real base
+ iRealBase &= ~0xFFF;
+ DEBUGS(" elf_relocate: True Base = 0x%x, Compiled Base = 0x%x", Base, iRealBase);
+
+ // Adjust "Real" Base
+ iBaseDiff = (intptr_t)Base - iRealBase;
+
+// hdr->entrypoint += iBaseDiff; // Adjust Entrypoint
+
+ // Check if a PT_DYNAMIC segement was found
+ if(!dynamicTab) {
+ SysDebug(" elf_relocate: No PT_DYNAMIC segment in image %p, returning", Base);
+ return (void *)(intptr_t)(hdr->entrypoint + iBaseDiff);
+ }
+
+ // 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 ++ )
+ {
+ 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
+ }
+ }
+
+ // Adjust Dynamic Table
+ dynamicTab = (void *)( (intptr_t)dynamicTab + iBaseDiff );