static void load_adjustCopyGotEntry(const char *name,uintptr_t copyAddr) { uintptr_t address; /* go through all libraries and copy the address of the object (copy-relocated) to * the corresponding GOT-entry. this ensures that all DSO's use the same object */ for(sSharedLib *l = libs; l != NULL; l = l->next) { /* don't do that in the executable */ if(!l->isDSO) continue; if(lookup_byNameIn(l,name,&address)) { /* TODO we should store DT_REL and DT_RELSZ */ sElfRel *rel = (sElfRel*)load_getDyn(l->dyn,DT_REL); if(rel) { size_t x,relCount = load_getDyn(l->dyn,DT_RELSZ); relCount /= sizeof(sElfRel); rel = (sElfRel*)((uintptr_t)rel + l->loadAddr); for(x = 0; x < relCount; x++) { if(ELF_R_TYPE(rel[x].r_info) == R_GLOB_DAT) { uint symIndex = ELF_R_SYM(rel[x].r_info); if(l->dynsyms[symIndex].st_value + l->loadAddr == address) { uintptr_t *ptr = (uintptr_t*)(rel[x].r_offset + l->loadAddr); *ptr = copyAddr; break; } } } } sElfRela *rela = (sElfRela*)load_getDyn(l->dyn,DT_RELA); if(rela) { size_t x,relCount = load_getDyn(l->dyn,DT_RELASZ); relCount /= sizeof(sElfRela); rela = (sElfRela*)((uintptr_t)rela + l->loadAddr); for(x = 0; x < relCount; x++) { if(ELF_R_TYPE(rela[x].r_info) == R_GLOB_DAT) { uint symIndex = ELF_R_SYM(rela[x].r_info); if(l->dynsyms[symIndex].st_value + l->loadAddr == address) { uintptr_t *ptr = (uintptr_t*)(rela[x].r_offset + l->loadAddr); *ptr = copyAddr; break; } } } } } } }
static void load_initLib(sSharedLib *l) { /* already initialized? */ if(l->initialized) return; /* first go through the dependencies */ for(sDep *dl = l->deps; dl != NULL; dl = dl->next) load_initLib(dl->lib); /* if its not the executable, call the init-function */ if(l->isDSO) { uintptr_t initAddr = (uintptr_t)load_getDyn(l->dyn,DT_INIT); if(initAddr) { DBGDL("Calling _init of %s...\n",l->name); void (*initFunc)(void) = (void (*)(void))(initAddr + l->loadAddr); initFunc(); } } l->initialized = true; }
static void load_relocLib(sSharedLib *l) { ElfAddr *got; sElfRel *rel; /* already relocated? */ if(l->relocated) return; /* first go through the dependencies; this may be required for the R_386_COPY-relocation */ for(sDep *dl = l->deps; dl != NULL; dl = dl->next) load_relocLib(dl->lib); if(load_hasDyn(l->dyn,DT_TEXTREL)) load_error("Unable to reloc library %s: requires a writable text segment\n",l->name); DBGDL("Relocating %s (loaded @ %p)\n",l->name,l->loadAddr ? l->loadAddr : l->textAddr); rel = (sElfRel*)load_getDyn(l->dyn,DT_REL); if(rel) load_relocDyn(l,rel,load_getDyn(l->dyn,DT_RELSZ),DT_REL); rel = (sElfRel*)load_getDyn(l->dyn,DT_RELA); if(rel) load_relocDyn(l,rel,load_getDyn(l->dyn,DT_RELASZ),DT_RELA); /* adjust addresses in PLT-jumps */ if(l->jmprel) { load_relocDyn(l,(void*)((uintptr_t)l->jmprel - l->loadAddr), load_getDyn(l->dyn,DT_PLTRELSZ),l->jmprelType); } /* store pointer to library and lookup-function into GOT */ got = (ElfAddr*)load_getDyn(l->dyn,DT_PLTGOT); DBGDL("GOT-Address of %s: %p\n",l->name,got); if(got) { got = (ElfAddr*)((uintptr_t)got + l->loadAddr); got[1] = (ElfAddr)l; got[2] = (ElfAddr)&lookup_resolveStart; } l->relocated = true; /* no longer needed */ close(l->fd); }