summaryrefslogtreecommitdiff
path: root/libexec/ld.so/amd64
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2019-11-26 02:50:12 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2019-11-26 02:50:12 +0000
commit591bc5b9808e2a86a256f9091aaef196a7ec0b2d (patch)
treee7dc633f5963fa9ebdff170d42dedc81332c53ab /libexec/ld.so/amd64
parent2af6bf258bc66d293733484b8e990300e385ba76 (diff)
Make aarch64, amd64, arm, and i386 more like sparc64: move non-lazy
relocation from _dl_md_reloc() to _dl_md_reloc_all_plt() which has the minimal code to do it. Also, avoid division on PLTRELSZ; just use it to offset to the end. ok kettenis@
Diffstat (limited to 'libexec/ld.so/amd64')
-rw-r--r--libexec/ld.so/amd64/rtld_machine.c86
1 files changed, 50 insertions, 36 deletions
diff --git a/libexec/ld.so/amd64/rtld_machine.c b/libexec/ld.so/amd64/rtld_machine.c
index 06b6d7c4ef0..ba85847aad5 100644
--- a/libexec/ld.so/amd64/rtld_machine.c
+++ b/libexec/ld.so/amd64/rtld_machine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld_machine.c,v 1.35 2019/10/23 19:55:09 guenther Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.36 2019/11/26 02:50:11 guenther Exp $ */
/*
* Copyright (c) 2002,2004 Dale Rahn
@@ -166,8 +166,6 @@ static const Elf_Addr reloc_target_bitmask[] = {
};
#define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t])
-void _dl_reloc_plt(Elf_Addr *where, Elf_Addr value);
-
int
_dl_md_reloc(elf_object_t *object, int rel, int relsz)
{
@@ -211,7 +209,7 @@ _dl_md_reloc(elf_object_t *object, int rel, int relsz)
if (type == R_TYPE(NONE))
continue;
- if (type == R_TYPE(JUMP_SLOT) && rel != DT_JMPREL)
+ if (type == R_TYPE(JUMP_SLOT))
continue;
where = (Elf_Addr *)(rels->r_offset + loff);
@@ -237,9 +235,8 @@ _dl_md_reloc(elf_object_t *object, int rel, int relsz)
struct sym_res sr;
sr = _dl_find_symbol(symn,
- SYM_SEARCH_ALL|SYM_WARNNOTFOUND|
- ((type == R_TYPE(JUMP_SLOT))?
- SYM_PLT:SYM_NOTPLT), sym, object);
+ SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_NOTPLT,
+ sym, object);
if (sr.sym == NULL) {
resolve_failed:
if (ELF_ST_BIND(sym->st_info) !=
@@ -254,11 +251,6 @@ resolve_failed:
}
}
- if (type == R_TYPE(JUMP_SLOT)) {
- _dl_reloc_plt(where, value);
- continue;
- }
-
if (type == R_TYPE(COPY)) {
void *dstaddr = where;
const void *srcaddr;
@@ -299,12 +291,6 @@ resolve_failed:
return fails;
}
-void
-_dl_reloc_plt(Elf_Addr *where, Elf_Addr value)
-{
- *where = value;
-}
-
/*
* Resolve a symbol at run-time.
*/
@@ -353,14 +339,41 @@ _dl_bind(elf_object_t *object, int index)
return buf.newval;
}
+static int
+_dl_md_reloc_all_plt(elf_object_t *object, const Elf_RelA *reloc,
+ const Elf_RelA *rend)
+{
+ for (; reloc < rend; reloc++) {
+ const Elf_Sym *sym;
+ const char *symn;
+ Elf_Addr *where;
+ struct sym_res sr;
+
+ sym = object->dyn.symtab;
+ sym += ELF_R_SYM(reloc->r_info);
+ symn = object->dyn.strtab + sym->st_name;
+
+ sr = _dl_find_symbol(symn,
+ SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, sym, object);
+ if (sr.sym == NULL) {
+ if (ELF_ST_BIND(sym->st_info) != STB_WEAK)
+ return 1;
+ continue;
+ }
+
+ where = (Elf_Addr *)(reloc->r_offset + object->obj_base);
+ *where = sr.obj->obj_base + sr.sym->st_value;
+ }
+
+ return 0;
+}
+
int
_dl_md_reloc_got(elf_object_t *object, int lazy)
{
extern void _dl_bind_start(void); /* XXX */
- int fails = 0;
- Elf_Addr *pltgot = (Elf_Addr *)object->Dyn.info[DT_PLTGOT];
- int i, num;
- Elf_RelA *rel;
+ Elf_Addr *pltgot = (Elf_Addr *)object->Dyn.info[DT_PLTGOT];
+ const Elf_RelA *reloc, *rend;
if (pltgot == NULL)
return 0; /* it is possible to have no PLT/GOT relocations */
@@ -371,20 +384,21 @@ _dl_md_reloc_got(elf_object_t *object, int lazy)
if (object->traced)
lazy = 1;
- if (__predict_false(!lazy)) {
- fails = _dl_md_reloc(object, DT_JMPREL, DT_PLTRELSZ);
- } else {
- pltgot[1] = (Elf_Addr)object;
- pltgot[2] = (Elf_Addr)&_dl_bind_start;
-
- rel = (Elf_RelA *)(object->Dyn.info[DT_JMPREL]);
- num = (object->Dyn.info[DT_PLTRELSZ]);
- for (i = 0; i < num/sizeof(Elf_RelA); i++, rel++) {
- Elf_Addr *where;
- where = (Elf_Addr *)(rel->r_offset + object->obj_base);
- *where += object->obj_base;
- }
+ reloc = (Elf_RelA *)(object->Dyn.info[DT_JMPREL]);
+ rend = (Elf_RelA *)((char *)reloc + object->Dyn.info[DT_PLTRELSZ]);
+
+ if (!lazy)
+ return _dl_md_reloc_all_plt(object, reloc, rend);
+
+ /* Lazy */
+ pltgot[1] = (Elf_Addr)object;
+ pltgot[2] = (Elf_Addr)&_dl_bind_start;
+
+ for (; reloc < rend; reloc++) {
+ Elf_Addr *where;
+ where = (Elf_Addr *)(reloc->r_offset + object->obj_base);
+ *where += object->obj_base;
}
- return fails;
+ return 0;
}