#include "elf32.h"
#include "elf64.h"
-#define DEBUG 1
+#define DEBUG 0
#if DEBUG
# define DEBUGS(v...) SysDebug("ld-acess - " v)
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 ===
case R_X86_64_64:
*(uint64_t*)ptr = (uint64_t)GetSymbol(symname) + addend;
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;
Elf32_Phdr *phtab;
int i, j; // Counters
char *libPath;
- Uint iRealBase = -1;
- Uint iBaseDiff;
+ intptr_t iRealBase = -1;
+ intptr_t iBaseDiff;
int iSegmentCount;
int iSymCount;
Elf32_Rel *rel = NULL;
// Check if a PT_DYNAMIC segement was found
if(!dynamicTab) {
SysDebug(" elf_relocate: No PT_DYNAMIC segment in image %p, returning", Base);
- return (void *)hdr->entrypoint + iBaseDiff;
+ return (void *)(intptr_t)(hdr->entrypoint + iBaseDiff);
}
// Adjust Dynamic Table
// --- Hash Table --
case DT_HASH:
if(iBaseDiff != 0) dynamicTab[j].d_val += iBaseDiff;
- iSymCount = ((Uint*)(dynamicTab[j].d_val))[1];
+ iSymCount = ((Elf32_Word*)(dynamicTab[j].d_val))[1];
// hdr->misc.HashTable = dynamicTab[j].d_val; // Saved in unused bytes of ident
break;
}
DEBUGS(" elf_relocate: Beginning Relocation");
- void elf_doRelocate(Uint r_info, Uint32 *ptr, Uint32 addend, Elf32_Sym *symtab)
+ void elf_doRelocate(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, Elf32_Sym *symtab)
{
int type = ELF32_R_TYPE(r_info);
int sym = ELF32_R_SYM(r_info);
* \fn int ElfGetSymbol(Uint Base, const char *name, void **ret)
*/
int ElfGetSymbol(void *Base, const char *Name, void **ret)
+{
+ Elf32_Ehdr *hdr = Base;
+
+ switch(hdr->e_ident[4])
+ {
+ case ELFCLASS32:
+ return Elf32GetSymbol(Base, Name, ret);
+ case ELFCLASS64:
+ return Elf64GetSymbol(Base, Name, ret);
+ default:
+ SysDebug("ld-acess - ElfRelocate: Unknown file class %i", hdr->e_ident[4]);
+ return 0;
+ }
+}
+
+int Elf64GetSymbol(void *Base, const char *Name, void **Ret)
+{
+ Elf64_Ehdr *hdr = Base;
+ Elf64_Sym *symtab;
+ int nbuckets = 0;
+ int iSymCount = 0;
+ int i;
+ Elf64_Word *pBuckets;
+ Elf64_Word *pChains;
+ uint32_t iNameHash;
+ const char *dynstrtab;
+ uintptr_t iBaseDiff = -1;
+
+// DEBUGS("sizeof(uint32_t) = %i, sizeof(Elf64_Word) = %i", sizeof(uint32_t), sizeof(Elf64_Word));
+
+ dynstrtab = NULL;
+ pBuckets = NULL;
+ symtab = NULL;
+
+ // Catch the current executable
+ if( !pBuckets )
+ {
+ Elf64_Phdr *phtab;
+ Elf64_Dyn *dynTab = NULL;
+ int j;
+
+ // Locate the tables
+ phtab = (void*)( Base + hdr->e_phoff );
+ for( i = 0; i < hdr->e_phnum; i ++ )
+ {
+ if(phtab[i].p_type == PT_LOAD && iBaseDiff > phtab[i].p_vaddr)
+ iBaseDiff = phtab[i].p_vaddr;
+ if( phtab[i].p_type == PT_DYNAMIC ) {
+ dynTab = (void*)(intptr_t)phtab[i].p_vaddr;
+ }
+ }
+ if( !dynTab ) {
+ SysDebug("ERROR - Unable to find DYNAMIC segment in %p", Base);
+ return 0;
+ }
+ iBaseDiff = (intptr_t)Base - iBaseDiff; // Make iBaseDiff actually the diff
+ dynTab = (void*)( (intptr_t)dynTab + iBaseDiff );
+
+ for( j = 0; dynTab[j].d_tag != DT_NULL; j++)
+ {
+ switch(dynTab[j].d_tag)
+ {
+ // --- Symbol Table ---
+ case DT_SYMTAB:
+ symtab = (void*)(intptr_t) dynTab[j].d_un.d_val; // Rebased in Relocate
+ break;
+ case DT_STRTAB:
+ dynstrtab = (void*)(intptr_t) dynTab[j].d_un.d_val;
+ break;
+ // --- Hash Table --
+ case DT_HASH:
+ pBuckets = (void*)(intptr_t) dynTab[j].d_un.d_val;
+ break;
+ }
+ }
+ }
+// DEBUGS("pBuckets = %p", pBuckets);
+
+ nbuckets = pBuckets[0];
+ iSymCount = pBuckets[1];
+ pBuckets = &pBuckets[2];
+// DEBUGS("nbuckets = %i", nbuckets);
+ pChains = &pBuckets[ nbuckets ];
+
+ // Get hash
+ iNameHash = ElfHashString(Name);
+ iNameHash %= nbuckets;
+
+ // Walk Chain
+ i = pBuckets[ iNameHash ];
+// DEBUGS("dynstrtab = %p", dynstrtab);
+// DEBUGS("symtab = %p, i = %i", symtab, 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;
+ DEBUGS("%s = %p", Name, *Ret);
+ return 1;
+ }
+
+ while(pChains[i] != STN_UNDEF)
+ {
+ i = pChains[i];
+// DEBUGS("chains i = %i", 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;
+ DEBUGS("%s = %p", Name, *Ret);
+ return 1;
+ }
+ }
+
+// DEBUGS("Elf64GetSymbol: RETURN 0, Symbol '%s' not found", Name);
+ return 0;
+}
+
+int Elf32GetSymbol(void *Base, const char *Name, void **ret)
{
Elf32_Ehdr *hdr = Base;
Elf32_Sym *symtab;
int i;
Uint32 *pBuckets;
Uint32 *pChains;
- Uint iNameHash;
+ uint32_t iNameHash;
const char *dynstrtab;
uintptr_t iBaseDiff = -1;
//DEBUGS("ElfGetSymbol: (Base=0x%x, Name='%s')", Base, Name);
- #if 0
- pBuckets = (void *) (intptr_t) hdr->misc.HashTable;
- symtab = (void *) (intptr_t) hdr->misc.SymTable;
- dynstrtab = (void *) (intptr_t) hdr->misc.StrTab;
- #else
dynstrtab = NULL;
pBuckets = NULL;
symtab = NULL;
- #endif
// Catch the current executable
if( !pBuckets )
}
}
if( !dynTab ) {
- SysDebug("ERROR - Unable to find DYNAMIC segment in %p");
+ SysDebug("ERROR - Unable to find DYNAMIC segment in %p", Base);
return 0;
}
iBaseDiff = (intptr_t)Base - iBaseDiff; // Make iBaseDiff actually the diff
}
#if 0
- hdr->misc.HashTable = pBucktets;
+ hdr->misc.HashTable = pBuckets;
hdr->misc.SymTable = symtab;
hdr->misc.StrTab = dynstrtab;
#endif
By thePowersGang
*/
#include "common.h"
+#include <stdint.h>
#define DEBUG 1
void *base;
void (*fEntry)(void *, int, char *[], char**);
- DEBUGS("LoadLibrary: (SoName='%s', SearchDir='%s', envp=0x%x)", SoName, SearchDir, envp);
+ DEBUGS("LoadLibrary: (SoName='%s', SearchDir='%s', envp=%p)", SoName, SearchDir, envp);
// Create Temp Name
filename = FindLibrary(sTmpName, SoName, SearchDir);
return 0;
}
- DEBUGS(" LoadLibrary: iArg=%p, iEntry=0x%x", base, fEntry);
+ DEBUGS(" LoadLibrary: iArg=%p, fEntry=%p", base, fEntry);
// Load Symbols
fEntry = DoRelocate( base, envp, filename );
// Call Entrypoint
- DEBUGS(" LoadLibrary: '%s' Entry 0x%x", SoName, fEntry);
+ DEBUGS(" LoadLibrary: '%s' Entry %p", SoName, fEntry);
fEntry(base, 0, NULL, envp);
DEBUGS("LoadLibrary: RETURN 1");
if(gLoadedLibraries[i].Base == 0) break; // Last entry has Base set to NULL
DEBUGS(" strcmp('%s', '%s')", gLoadedLibraries[i].Name, file);
if(strcmp(gLoadedLibraries[i].Name, file) == 0) {
- DEBUGS("IsFileLoaded: Found %i (0x%x)", i, gLoadedLibraries[i].Base);
+ DEBUGS("IsFileLoaded: Found %i (%p)", i, gLoadedLibraries[i].Base);
return gLoadedLibraries[i].Base;
}
}
int i, length;
char *name = gsNextAvailString;
- DEBUGS("AddLoaded: (File='%s', base=0x%x)", File, base);
+ DEBUGS("AddLoaded: (File='%s', base=%p)", File, base);
// Find a free slot
for( i = 0; i < MAX_LOADED_LIBRARIES; i ++ )
strcpy(name, File);
gLoadedLibraries[i].Name = name;
gsNextAvailString = &name[length+1];
- DEBUGS("'%s' (0x%x) loaded as %i", name, base, i);
+ DEBUGS("'%s' (%p) loaded as %i", name, base, i);
return;
}
*/
int GetSymbolFromBase(void *base, const char *name, void **ret)
{
- if(*(Uint32*)base == (0x7F|('E'<<8)|('L'<<16)|('F'<<24)))
+ uint8_t *hdr = base;
+ if(hdr[0] == 0x7F && hdr[1] == 'E' && hdr[2] == 'L' && hdr[3] == 'F')
return ElfGetSymbol(base, name, ret);
- if(*(Uint16*)base == ('M'|('Z'<<8)))
+ if(hdr[0] == 'M' && hdr[1] == 'Z')
return PE_GetSymbol(base, name, ret);
- SysDebug("Unknown type at %p", base);
+ SysDebug("Unknown type at %p (%02x %02x %02x %02x)", base,
+ hdr[0], hdr[1], hdr[2], hdr[3]);
return 0;
}