/* * Resolve a symbol at run-time. */ Elf_Addr _dl_bind(elf_object_t *object, int reloff) { Elf_RelA *rela; Elf_Addr *addr, ooff; const Elf_Sym *sym, *this; const char *symn; sigset_t savedmask; rela = (Elf_RelA *)(object->Dyn.info[DT_JMPREL] + reloff); addr = (Elf_Addr *)(object->obj_base + rela->r_offset); if (object->plt_size != 0 && !(*addr >= object->plt_start && *addr < (object->plt_start + object->plt_size ))) { /* something is broken, relocation has already occurred */ #if 0 DL_DEB(("*addr doesn't point into plt %p obj %s\n", *addr, object->load_name)); #endif return *addr; } sym = object->dyn.symtab; sym += ELF64_R_SYM(rela->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, NULL); if (this == NULL) { _dl_printf("lazy binding failed!\n"); *((int *)0) = 0; /* XXX */ } /* if PLT is protected, allow the write */ if (object->plt_size != 0) { _dl_thread_bind_lock(0, &savedmask); _dl_mprotect(addr, sizeof(Elf_Addr), PROT_READ|PROT_WRITE); } *addr = ooff + this->st_value + rela->r_addend; /* if PLT is (to be protected, change back to RO/X */ if (object->plt_size != 0) { _dl_mprotect(addr, sizeof(Elf_Addr), PROT_READ); _dl_thread_bind_lock(1, &savedmask); } return *addr; }
/* * 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); }
Elf_Addr _dl_bind(elf_object_t *object, int symidx) { Elf_Addr *gotp = object->dyn.pltgot; Elf_Addr *addr, ooff; const Elf_Sym *sym, *this; const char *symn; sigset_t savedmask; int n; sym = object->dyn.symtab; sym += symidx; symn = object->dyn.strtab + sym->st_name; n = object->Dyn.info[DT_MIPS_LOCAL_GOTNO - DT_LOPROC + DT_NUM] - object->Dyn.info[DT_MIPS_GOTSYM - DT_LOPROC + DT_NUM]; this = NULL; ooff = _dl_find_symbol(symn, &this, SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, sym, object, NULL); if (this == NULL) { _dl_printf("lazy binding failed\n"); *((int *)0) = 0; /* XXX */ } addr = &gotp[n + symidx]; /* if GOT is protected, allow the write */ if (object->got_size != 0) { _dl_thread_bind_lock(0, &savedmask); _dl_mprotect(addr, sizeof(Elf_Addr), PROT_READ|PROT_WRITE); } *addr = ooff + this->st_value; /* if GOT is (to be protected, change back to RO */ if (object->got_size != 0) { _dl_mprotect(addr, sizeof (Elf_Addr), PROT_READ); _dl_thread_bind_lock(1, &savedmask); } return *addr; }