/* * 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]; }
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); }
/* * 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); }