Exemplo n.º 1
0
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);
}
Exemplo n.º 2
0
A_REGPARM(0) uintptr_t lookup_resolve(A_UNUSED SavedRegs regs,sSharedLib *lib,size_t off) {
#endif
	sElfSym *foundSym;
	ulong info,offset;
	if(lib->jmprelType == DT_REL) {
		sElfRel *rel = (sElfRel*)((uintptr_t)lib->jmprel + off);
		info = rel->r_info;
		offset = rel->r_offset;
	}
	else {
		// TODO it's only the index on x86_64?
		sElfRela *rel = (sElfRela*)lib->jmprel + off;
		info = rel->r_info;
		offset = rel->r_offset;
	}

	sElfSym *sym = lib->dynsyms + ELF_R_SYM(info);
	uintptr_t value = 0,*addr;
	foundSym = lookup_byName(NULL,lib->dynstrtbl + sym->st_name,&value);
	if(foundSym == NULL)
		error("Unable to find symbol %s",lib->dynstrtbl + sym->st_name);
	addr = (uintptr_t*)(offset + lib->loadAddr);

#if defined(CALLTRACE_PID)
	pid = getpid();
	if(pid == CALLTRACE_PID) {
		if(depth < 100) {
			sSharedLib *calling = libs;
			for(sSharedLib *l = libs; l != NULL; l = l->next) {
				if(retAddr >= l->loadAddr && retAddr < l->loadAddr + l->textSize) {
					calling = l;
					break;
				}
			}
			debugf("%*s\\ %x(%s) -> %s (%x)\n",depth,"",retAddr - calling->loadAddr,
					calling->name,lib->dynstrtbl + sym->st_name,value);
			depth++;
		}
	}
	else
		*addr = value;
#else
	DBGDL("Found: %s @ %p (off: %p) in %s (GOT: 0x%x)\n",
		lib->dynstrtbl + sym->st_name,value,value - lib->loadAddr,lib->name,off);
	*addr = value;
#endif

	return value;
}
Exemplo n.º 3
0
Arquivo: init.c Projeto: jarn0x/Escape
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;
}
Exemplo n.º 4
0
static void load_relocDyn(sSharedLib *l,void *entries,size_t size,uint type) {
	sElfRel *rel = (sElfRel*)((uintptr_t)entries + l->loadAddr);
	sElfRela *rela = (sElfRela*)((uintptr_t)entries + l->loadAddr);
	size_t count = type == DT_REL ? size / sizeof(sElfRel) : size / sizeof(sElfRela);
	for(size_t x = 0; x < count; x++) {
		ulong info,offset,addend;
		if(type == DT_REL) {
			info = rel[x].r_info;
			offset = rel[x].r_offset;
			addend = 0;
		}
		else {
			info = rela[x].r_info;
			offset = rela[x].r_offset;
			addend = rela[x].r_addend;
		}

		int rtype = ELF_R_TYPE(info);
		if(rtype == R_NONE)
			continue;

		size_t symIndex = ELF_R_SYM(info);
		sElfSym *sym = l->dynsyms + symIndex;
		const char *symname = l->dynstrtbl + sym->st_name;
		uintptr_t value = sym->st_value;
		uintptr_t *ptr = (uintptr_t*)(offset + l->loadAddr);

		if(rtype == R_JUMP_SLOT) {
			value = *ptr;
			if(*ptr == 0 || LD_BIND_NOW) {
				if(!lookup_byName(l,symname,&value)) {
					if(!lookup_byName(NULL,symname,&value))
						load_error("Unable to find symbol '%s'\n",symname);
				}
				value -= l->loadAddr;
			}
		}
		/* if the symbol-value is 0, it seems that we have to lookup the symbol now and
		 * store that value instead. TODO I'm not sure if thats correct */
		else if(rtype != R_RELATIVE && (rtype == R_COPY || value == 0)) {
			if(!lookup_byName(l,symname,&value))
				load_error("Unable to find symbol '%s'\n",symname);
			// we'll add that again
			value -= l->loadAddr;
		}

		switch(rtype) {
			case R_COPY:
				memcpy((void*)offset,(void*)(value + l->loadAddr),sym->st_size);
				/* set the GOT-Entry in the library of the symbol to the address we've copied
				 * the value to. TODO I'm not sure if that's the intended way... */
				load_adjustCopyGotEntry(symname,offset);
				break;

			default:
				if(!perform_reloc(l,rtype,offset,ptr,value,addend)) {
					load_error("In library %s: Unknown relocation: off=%p info=%p type=%d addend=%x\n",
						l->name,offset,info,ELF_R_TYPE(info),addend);
				}
				break;
		}

		DBGDL("Rel (%s) off=%p reloc=%p value=%p symbol=%s\n",
		 	load_getRelName(rtype),offset,*ptr,value,symname);
	}
}