/*
 * Resolve a symbol at run-time.
 */
uint64_t
_dl_bind(elf_object_t *object, int reloff)
{
	const elf_object_t *sobj;
	const Elf_Sym *sym, *this;
	Elf_Addr *addr, ooff;
	const char *symn;
	Elf_Addr value;
	Elf_RelA *rela;
	sigset_t savedmask;

	rela = (Elf_RelA *)object->dyn.jmprel + reloff;

	sym = object->dyn.symtab;
	sym += ELF_R_SYM(rela->r_info);
	symn = object->dyn.strtab + sym->st_name;

	addr = (Elf_Addr *)(object->obj_base + rela->r_offset);
	this = NULL;
	ooff = _dl_find_symbol(symn, &this,
	    SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, sym, object, &sobj);
	if (this == NULL) {
		_dl_printf("lazy binding failed!\n");
		*(volatile int *)0 = 0;		/* XXX */
	}
	DL_DEB(("%s: %s\n", symn, sobj->load_name));

	value = ooff + this->st_value + rela->r_addend;

	if (sobj->traced && _dl_trace_plt(sobj, symn))
		return ((uint64_t)value << 32) | (Elf_Addr)sobj->dyn.pltgot;

	/* if PLT+GOT is protected, allow the write */
	if (object->got_size != 0) {
		_dl_thread_bind_lock(0, &savedmask);
		/* mprotect the actual modified region, not the whole plt */
		_dl_mprotect((void*)addr, sizeof (Elf_Addr) * 2,
		    PROT_READ|PROT_WRITE|PROT_EXEC);
	}

	addr[0] = value;
	addr[1] = (Elf_Addr)sobj->dyn.pltgot;

	/* if PLT is (to be protected, change back to RO */
	if (object->got_size != 0) {
		/* mprotect the actual modified region, not the whole plt */
		_dl_mprotect((void*)addr, sizeof (Elf_Addr) * 3,
		    PROT_READ|PROT_EXEC);
		_dl_thread_bind_lock(1, &savedmask);
	}

	return ((uint64_t)addr[0] << 32) | addr[1];
}
Exemple #2
0
Elf_Addr
_dl_bind(elf_object_t *object, int reloff)
{
	Elf_RelA *rel;
	Elf_Addr *r_addr, ooff, value;
	const Elf_Sym *sym, *this;
	const char *symn;
	const elf_object_t *sobj;
	sigset_t savedmask;

	rel = (Elf_RelA *)(object->Dyn.info[DT_JMPREL] + reloff);

	sym = object->dyn.symtab;
	sym += ELF_R_SYM(rel->r_info);
	symn = object->dyn.strtab + sym->st_name;

	r_addr = (Elf_Addr *)(object->obj_base + rel->r_offset);
	this = NULL;
	ooff = _dl_find_symbol(symn, &this,
	    SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, sym, object, &sobj);
	if (this == NULL) {
		_dl_printf("lazy binding failed!\n");
		*(volatile int *)0 = 0;		/* XXX */
	}

	value = ooff + this->st_value + rel->r_addend;

	if (sobj->traced && _dl_trace_plt(sobj, symn))
		return value;

	/* if GOT is protected, allow the write */
	if (object->got_size != 0)  {
		_dl_thread_bind_lock(0, &savedmask);
		_dl_mprotect((void*)object->got_start, object->got_size,
		    PROT_READ|PROT_WRITE);
	}

	*r_addr = value;

	/* put the GOT back to RO */
	if (object->got_size != 0) {
		_dl_mprotect((void*)object->got_start, object->got_size,
		    PROT_READ);
		_dl_thread_bind_lock(1, &savedmask);
	}

	return (value);
}
Exemple #3
0
/*
 * Resolve a symbol at run-time.
 */
Elf_Addr
_dl_bind(elf_object_t *object, int index)
{
	Elf_RelA *rel;
	const Elf_Sym *sym, *this;
	const char *symn;
	const elf_object_t *sobj;
	Elf_Addr ooff;
	int64_t cookie = pcookie;
	struct {
		struct __kbind param;
		Elf_Addr newval;
	} buf;

	rel = (Elf_RelA *)(object->Dyn.info[DT_JMPREL]) + index;

	sym = object->dyn.symtab;
	sym += ELF_R_SYM(rel->r_info);
	symn = object->dyn.strtab + sym->st_name;

	this = NULL;
	ooff = _dl_find_symbol(symn, &this,
	    SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, sym, object, &sobj);
	if (this == NULL) {
		_dl_printf("lazy binding failed!\n");
		*(volatile int *)0 = 0;		/* XXX */
	}

	buf.newval = ooff + this->st_value + rel->r_addend;

	if (__predict_false(sobj->traced) && _dl_trace_plt(sobj, symn))
		return (buf.newval);

	buf.param.kb_addr = (Elf_Word *)(object->obj_base + rel->r_offset);
	buf.param.kb_size = sizeof(Elf_Addr);

	/* directly code the syscall, so that it's actually inline here */
	{
		register long syscall_num __asm("rax") = SYS_kbind;
		register void *arg1 __asm("rdi") = &buf;
		register long  arg2 __asm("rsi") = sizeof(buf);
		register long  arg3 __asm("rdx") = cookie;

		__asm volatile("syscall" : "+r" (syscall_num), "+r" (arg3) :
		    "r" (arg1), "r" (arg2) : "cc", "rcx", "r11", "memory");
	}
	return (buf.newval);
}