summaryrefslogtreecommitdiff
path: root/libexec
diff options
context:
space:
mode:
Diffstat (limited to 'libexec')
-rw-r--r--libexec/ld.so/alpha/rtld_machine.c43
-rw-r--r--libexec/ld.so/amd64/rtld_machine.c32
-rw-r--r--libexec/ld.so/arm/rtld_machine.c32
-rw-r--r--libexec/ld.so/i386/rtld_machine.c32
-rw-r--r--libexec/ld.so/m68k/rtld_machine.c41
-rw-r--r--libexec/ld.so/m88k/rtld_machine.c19
-rw-r--r--libexec/ld.so/mips64/rtld_machine.c36
-rw-r--r--libexec/ld.so/powerpc/rtld_machine.c82
-rw-r--r--libexec/ld.so/resolve.c6
-rw-r--r--libexec/ld.so/resolve.h5
-rw-r--r--libexec/ld.so/sh/rtld_machine.c32
-rw-r--r--libexec/ld.so/sparc/rtld_machine.c32
-rw-r--r--libexec/ld.so/sparc64/rtld_machine.c32
13 files changed, 350 insertions, 74 deletions
diff --git a/libexec/ld.so/alpha/rtld_machine.c b/libexec/ld.so/alpha/rtld_machine.c
index 394bf99507a..37480b01f54 100644
--- a/libexec/ld.so/alpha/rtld_machine.c
+++ b/libexec/ld.so/alpha/rtld_machine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld_machine.c,v 1.47 2012/12/05 23:20:06 deraadt Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.48 2013/05/08 20:55:14 guenther Exp $ */
/*
* Copyright (c) 1999 Dale Rahn
@@ -47,18 +47,27 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
{
long i;
long numrela;
+ long relrel;
int fails = 0;
Elf64_Addr loff;
+ Elf64_Addr prev_value = 0;
+ const Elf_Sym *prev_sym = NULL;
Elf64_Rela *relas;
struct load_list *llist;
loff = object->obj_base;
numrela = object->Dyn.info[relasz] / sizeof(Elf64_Rela);
+ relrel = rel == DT_RELA ? object->relacount : 0;
relas = (Elf64_Rela *)(object->Dyn.info[rel]);
if (relas == NULL)
return(0);
+ if (relrel > numrela) {
+ _dl_printf("relacount > numrel: %ld > %ld\n", relrel, numrela);
+ _dl_exit(20);
+ }
+
/*
* unprotect some segments if we need it.
* XXX - we unprotect way to much. only the text can have cow
@@ -73,7 +82,29 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
}
}
- for (i = 0; i < numrela; i++, relas++) {
+ /* tight loop for leading RELATIVE relocs */
+ for (i = 0; i < relrel; i++, relas++) {
+ Elf_Addr *r_addr;
+
+#ifdef DEBUG
+ if (ELF64_R_TYPE(relas->r_info) != R_TYPE(RELATIVE)) {
+ _dl_printf("RELACOUNT wrong\n");
+ _dl_exit(20);
+ }
+#endif
+
+ r_addr = (Elf64_Addr *)(relas->r_offset + loff);
+
+ /* Handle unaligned RELATIVE relocs */
+ if ((((Elf_Addr)r_addr) & 0x7) != 0) {
+ Elf_Addr tmp;
+ _dl_bcopy(r_addr, &tmp, sizeof(Elf_Addr));
+ tmp += loff;
+ _dl_bcopy(&tmp, r_addr, sizeof(Elf_Addr));
+ } else
+ *r_addr += loff;
+ }
+ for (; i < numrela; i++, relas++) {
Elf64_Addr *r_addr;
Elf64_Addr ooff;
const Elf64_Sym *sym, *this;
@@ -126,13 +157,19 @@ _dl_printf("unaligned RELATIVE: %p type: %d %s 0x%lx -> 0x%lx\n", r_addr,
*r_addr = ooff + this->st_value + relas->r_addend;
break;
case R_TYPE(GLOB_DAT):
+ if (sym == prev_sym) {
+ *r_addr = prev_value + relas->r_addend;
+ break;
+ }
ooff = _dl_find_symbol_bysym(object,
ELF64_R_SYM(relas->r_info), &this,
SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_NOTPLT,
sym, NULL);
if (this == NULL)
goto resolve_failed;
- *r_addr = ooff + this->st_value + relas->r_addend;
+ prev_sym = sym;
+ prev_value = ooff + this->st_value;
+ *r_addr = prev_value + relas->r_addend;
break;
case R_TYPE(NONE):
break;
diff --git a/libexec/ld.so/amd64/rtld_machine.c b/libexec/ld.so/amd64/rtld_machine.c
index c2e25a2ff81..0e717e68106 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.18 2013/03/18 04:22:31 guenther Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.19 2013/05/08 20:55:14 guenther Exp $ */
/*
* Copyright (c) 2002,2004 Dale Rahn
@@ -172,17 +172,26 @@ _dl_md_reloc(elf_object_t *object, int rel, int relsz)
{
long i;
long numrel;
+ long relrel;
int fails = 0;
Elf_Addr loff;
+ Elf_Addr prev_value = 0;
+ const Elf_Sym *prev_sym = NULL;
Elf_RelA *rels;
struct load_list *llist;
loff = object->obj_base;
numrel = object->Dyn.info[relsz] / sizeof(Elf_RelA);
+ relrel = rel == DT_RELA ? object->relacount : 0;
rels = (Elf_RelA *)(object->Dyn.info[rel]);
if (rels == NULL)
return(0);
+ if (relrel > numrel) {
+ _dl_printf("relacount > numrel: %ld > %ld\n", relrel, numrel);
+ _dl_exit(20);
+ }
+
/*
* unprotect some segments if we need it.
*/
@@ -194,7 +203,20 @@ _dl_md_reloc(elf_object_t *object, int rel, int relsz)
}
}
- for (i = 0; i < numrel; i++, rels++) {
+ /* tight loop for leading RELATIVE relocs */
+ for (i = 0; i < relrel; i++, rels++) {
+ Elf_Addr *where;
+
+#ifdef DEBUG
+ if (ELF_R_TYPE(rels->r_info) != R_TYPE(RELATIVE)) {
+ _dl_printf("RELACOUNT wrong\n");
+ _dl_exit(20);
+ }
+#endif
+ where = (Elf_Addr *)(rels->r_offset + loff);
+ *where = rels->r_addend + loff;
+ }
+ for (; i < numrel; i++, rels++) {
Elf_Addr *where, value, ooff, mask;
Elf_Word type;
const Elf_Sym *sym, *this;
@@ -230,6 +252,8 @@ _dl_md_reloc(elf_object_t *object, int rel, int relsz)
if (sym->st_shndx != SHN_UNDEF &&
ELF_ST_BIND(sym->st_info) == STB_LOCAL) {
value += loff;
+ } else if (sym == prev_sym) {
+ value += prev_value;
} else {
this = NULL;
ooff = _dl_find_symbol_bysym(object,
@@ -245,7 +269,9 @@ resolve_failed:
fails++;
continue;
}
- value += (Elf_Addr)(ooff + this->st_value);
+ prev_sym = sym;
+ prev_value = (Elf_Addr)(ooff + this->st_value);
+ value += prev_value;
}
}
diff --git a/libexec/ld.so/arm/rtld_machine.c b/libexec/ld.so/arm/rtld_machine.c
index 6385a2f7911..258845d6b9a 100644
--- a/libexec/ld.so/arm/rtld_machine.c
+++ b/libexec/ld.so/arm/rtld_machine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld_machine.c,v 1.16 2011/04/06 11:36:25 miod Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.17 2013/05/08 20:55:14 guenther Exp $ */
/*
* Copyright (c) 2004 Dale Rahn
@@ -161,18 +161,27 @@ _dl_md_reloc(elf_object_t *object, int rel, int relsz)
{
long i;
long numrel;
+ long relrel;
int fails = 0;
Elf_Addr loff;
+ Elf_Addr prev_value = 0;
+ const Elf_Sym *prev_sym = NULL;
Elf_Rel *rels;
struct load_list *llist;
loff = object->obj_base;
numrel = object->Dyn.info[relsz] / sizeof(Elf_Rel);
+ relrel = rel == DT_REL ? object->relcount : 0;
rels = (Elf_Rel *)(object->Dyn.info[rel]);
if (rels == NULL)
return(0);
+ if (relrel > numrel) {
+ _dl_printf("relcount > numrel: %ld > %ld\n", relrel, numrel);
+ _dl_exit(20);
+ }
+
/*
* unprotect some segments if we need it.
*/
@@ -186,7 +195,20 @@ _dl_md_reloc(elf_object_t *object, int rel, int relsz)
}
}
- for (i = 0; i < numrel; i++, rels++) {
+ /* tight loop for leading RELATIVE relocs */
+ for (i = 0; i < relrel; i++, rels++) {
+ Elf_Addr *where;
+
+#ifdef DEBUG
+ if (ELF_R_TYPE(rels->r_info) != R_TYPE(RELATIVE)) {
+ _dl_printf("RELCOUNT wrong\n");
+ _dl_exit(20);
+ }
+#endif
+ where = (Elf_Addr *)(rels->r_offset + loff);
+ *where += loff;
+ }
+ for (; i < numrel; i++, rels++) {
Elf_Addr *where, value, ooff, mask;
Elf_Word type;
const Elf_Sym *sym, *this;
@@ -225,6 +247,8 @@ _dl_md_reloc(elf_object_t *object, int rel, int relsz)
if (sym->st_shndx != SHN_UNDEF &&
ELF_ST_BIND(sym->st_info) == STB_LOCAL) {
value += loff;
+ } else if (sym == prev_sym) {
+ value += prev_value;
} else {
this = NULL;
ooff = _dl_find_symbol_bysym(object,
@@ -240,7 +264,9 @@ resolve_failed:
fails++;
continue;
}
- value += (Elf_Addr)(ooff + this->st_value);
+ prev_sym = sym;
+ prev_value = (Elf_Addr)(ooff + this->st_value);
+ value += prev_value;
}
}
diff --git a/libexec/ld.so/i386/rtld_machine.c b/libexec/ld.so/i386/rtld_machine.c
index 06b6002dca0..078553b9223 100644
--- a/libexec/ld.so/i386/rtld_machine.c
+++ b/libexec/ld.so/i386/rtld_machine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld_machine.c,v 1.26 2012/12/05 23:20:06 deraadt Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.27 2013/05/08 20:55:14 guenther Exp $ */
/*
* Copyright (c) 2002 Dale Rahn
@@ -170,17 +170,26 @@ _dl_md_reloc(elf_object_t *object, int rel, int relsz)
{
long i;
long numrel;
+ long relrel;
int fails = 0;
Elf_Addr loff;
+ Elf_Addr prev_value = 0;
+ const Elf_Sym *prev_sym = NULL;
Elf_Rel *rels;
struct load_list *llist;
loff = object->obj_base;
numrel = object->Dyn.info[relsz] / sizeof(Elf32_Rel);
+ relrel = rel == DT_REL ? object->relcount : 0;
rels = (Elf32_Rel *)(object->Dyn.info[rel]);
if (rels == NULL)
return(0);
+ if (relrel > numrel) {
+ _dl_printf("relcount > numrel: %ld > %ld\n", relrel, numrel);
+ _dl_exit(20);
+ }
+
/*
* unprotect some segments if we need it.
*/
@@ -192,7 +201,20 @@ _dl_md_reloc(elf_object_t *object, int rel, int relsz)
}
}
- for (i = 0; i < numrel; i++, rels++) {
+ /* tight loop for leading RELATIVE relocs */
+ for (i = 0; i < relrel; i++, rels++) {
+ Elf_Addr *where;
+
+#ifdef DEBUG
+ if (ELF_R_TYPE(rels->r_info) != R_TYPE(RELATIVE)) {
+ _dl_printf("RELCOUNT wrong\n");
+ _dl_exit(20);
+ }
+#endif
+ where = (Elf_Addr *)(rels->r_offset + loff);
+ *where += loff;
+ }
+ for (; i < numrel; i++, rels++) {
Elf_Addr *where, value, ooff, mask;
Elf_Word type;
const Elf_Sym *sym, *this;
@@ -223,6 +245,8 @@ _dl_md_reloc(elf_object_t *object, int rel, int relsz)
if (sym->st_shndx != SHN_UNDEF &&
ELF_ST_BIND(sym->st_info) == STB_LOCAL) {
value += loff;
+ } else if (sym == prev_sym) {
+ value += prev_value;
} else {
this = NULL;
ooff = _dl_find_symbol_bysym(object,
@@ -238,7 +262,9 @@ resolve_failed:
fails++;
continue;
}
- value += (Elf_Addr)(ooff + this->st_value);
+ prev_sym = sym;
+ prev_value = (Elf_Addr)(ooff + this->st_value);
+ value += prev_value;
}
}
diff --git a/libexec/ld.so/m68k/rtld_machine.c b/libexec/ld.so/m68k/rtld_machine.c
index f8c3abf2594..58b443cb494 100644
--- a/libexec/ld.so/m68k/rtld_machine.c
+++ b/libexec/ld.so/m68k/rtld_machine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld_machine.c,v 1.1 2013/01/23 19:15:58 miod Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.2 2013/05/08 20:55:14 guenther Exp $ */
/*
* Copyright (c) 2013 Miodrag Vallat.
@@ -61,6 +61,7 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
{
int i;
int numrela;
+ int relrel;
int fails = 0;
struct load_list *llist;
Elf32_Addr loff;
@@ -68,6 +69,7 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
loff = object->obj_base;
numrela = object->Dyn.info[relasz] / sizeof(Elf32_Rela);
+ relrel = rel == DT_RELA ? object->relacount : 0;
relas = (Elf32_Rela *)(object->Dyn.info[rel]);
#ifdef DL_PRINTF_DEBUG
@@ -78,6 +80,11 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
if (relas == NULL)
return(0);
+ if (relrel > numrela) {
+ _dl_printf("relacount > numrela: %ld > %ld\n", relrel, numrela);
+ _dl_exit(20);
+ }
+
/*
* Change protection of all write protected segments in the object
* so we can do relocations such as PC32. After relocation,
@@ -93,12 +100,27 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
}
}
- for (i = 0; i < numrela; i++, relas++) {
+ /* tight loop for leading RELATIVE relocs */
+ for (i = 0; i < relrel; i++, relas++) {
+ Elf32_Addr *r_addr;
+
+#ifdef DEBUG
+ if (ELF_R_TYPE(relas->r_info) != R_68K_RELATIVE) {
+ _dl_printf("RELACOUNT wrong\n");
+ _dl_exit(20);
+ }
+#endif
+ r_addr = (Elf32_Addr *)(relas->r_offset + loff);
+ *r_addr = relas->r_addend + loff;
+ }
+ for (; i < numrela; i++, relas++) {
Elf32_Addr *r_addr = (Elf32_Addr *)(relas->r_offset + loff);
Elf32_Addr ooff, addend, newval;
const Elf32_Sym *sym, *this;
const char *symn;
int type;
+ Elf32_Addr prev_value = 0, prev_ooff = 0;
+ const Elf32_Sym *prev_sym = NULL;
type = ELF32_R_TYPE(relas->r_info);
@@ -143,11 +165,11 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
continue;
}
- ooff = 0;
- this = NULL;
if (ELF32_R_SYM(relas->r_info) &&
!(ELF32_ST_BIND(sym->st_info) == STB_LOCAL &&
- ELF32_ST_TYPE (sym->st_info) == STT_NOTYPE)) {
+ ELF32_ST_TYPE (sym->st_info) == STT_NOTYPE) &&
+ sym != prev_sym) {
+ this = NULL;
ooff = _dl_find_symbol_bysym(object,
ELF32_R_SYM(relas->r_info), &this,
SYM_SEARCH_ALL|SYM_WARNNOTFOUND|
@@ -159,6 +181,9 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
fails++;
continue;
}
+ prev_sym = sym;
+ prev_value = this->st_value;
+ prev_ooff = ooff;
}
if (ELF32_ST_BIND(sym->st_info) == STB_LOCAL &&
@@ -166,18 +191,18 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
ELF32_ST_TYPE(sym->st_info) == STT_NOTYPE))
addend = relas->r_addend;
else
- addend = this->st_value + relas->r_addend;
+ addend = prev_value + relas->r_addend;
switch (type) {
case R_68K_PC32:
- newval = ooff + addend;
+ newval = prev_ooff + addend;
newval -= (Elf_Addr)r_addr;
*r_addr = newval;
break;
case R_68K_32:
case R_68K_GLOB_DAT:
case R_68K_JMP_SLOT:
- newval = ooff + addend;
+ newval = prev_ooff + addend;
*r_addr = newval;
break;
case R_68K_RELATIVE:
diff --git a/libexec/ld.so/m88k/rtld_machine.c b/libexec/ld.so/m88k/rtld_machine.c
index f8e70e790f8..8ef9d44c31c 100644
--- a/libexec/ld.so/m88k/rtld_machine.c
+++ b/libexec/ld.so/m88k/rtld_machine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld_machine.c,v 1.5 2013/04/20 18:40:42 miod Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.6 2013/05/08 20:55:14 guenther Exp $ */
/*
* Copyright (c) 2013 Miodrag Vallat.
@@ -100,6 +100,8 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
const Elf32_Sym *sym, *this;
const char *symn;
int type;
+ Elf32_Addr prev_value = 0, prev_ooff = 0;
+ const Elf32_Sym *prev_sym = NULL;
type = ELF32_R_TYPE(relas->r_info);
@@ -144,11 +146,11 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
continue;
}
- ooff = 0;
- this = NULL;
if (ELF32_R_SYM(relas->r_info) &&
!(ELF32_ST_BIND(sym->st_info) == STB_LOCAL &&
- ELF32_ST_TYPE (sym->st_info) == STT_NOTYPE)) {
+ ELF32_ST_TYPE (sym->st_info) == STT_NOTYPE) &&
+ sym != prev_sym) {
+ this = NULL;
ooff = _dl_find_symbol_bysym(object,
ELF32_R_SYM(relas->r_info), &this,
SYM_SEARCH_ALL | SYM_WARNNOTFOUND |
@@ -160,12 +162,15 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
fails++;
continue;
}
+ prev_sym = sym;
+ prev_value = this->st_value;
+ prev_ooff = ooff;
}
if (type == RELOC_GOTP_ENT) {
_dl_md_reloc_gotp_ent((Elf_Addr)r_addr,
relas->r_addend + loff,
- ooff + this->st_value);
+ prev_ooff + prev_value);
continue;
}
@@ -174,11 +179,11 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
ELF32_ST_TYPE(sym->st_info) == STT_NOTYPE))
addend = relas->r_addend;
else
- addend = this->st_value + relas->r_addend;
+ addend = prev_value + relas->r_addend;
switch (type) {
case RELOC_32:
- newval = ooff + addend;
+ newval = prev_ooff + addend;
*r_addr = newval;
break;
case RELOC_BBASED_32:
diff --git a/libexec/ld.so/mips64/rtld_machine.c b/libexec/ld.so/mips64/rtld_machine.c
index 5acd2e8b4cb..905fe5ecf30 100644
--- a/libexec/ld.so/mips64/rtld_machine.c
+++ b/libexec/ld.so/mips64/rtld_machine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld_machine.c,v 1.14 2010/09/11 11:13:20 kettenis Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.15 2013/05/08 20:55:14 guenther Exp $ */
/*
* Copyright (c) 1998-2004 Opsycon AB, Sweden.
@@ -50,6 +50,8 @@ _dl_md_reloc(elf_object_t *object, int rel, int relsz)
Elf64_Addr got_start, got_end;
Elf64_Rel *relocs;
const Elf64_Sym *sym, *this;
+ Elf64_Addr prev_value = 0;
+ const Elf64_Sym *prev_sym = NULL;
loff = object->obj_base;
numrel = object->Dyn.info[relsz] / sizeof(Elf64_Rel);
@@ -102,17 +104,23 @@ _dl_md_reloc(elf_object_t *object, int rel, int relsz)
type = ELF64_R_TYPE(relocs->r_info);
this = NULL;
- if (ELF64_R_SYM(relocs->r_info) &&
- !(ELF64_ST_BIND(sym->st_info) == STB_LOCAL &&
- ELF64_ST_TYPE (sym->st_info) == STT_NOTYPE)) {
- ooff = _dl_find_symbol(symn, &this,
- SYM_SEARCH_ALL | SYM_WARNNOTFOUND | SYM_PLT,
- sym, object, NULL);
-
- if (this == NULL) {
- if (ELF_ST_BIND(sym->st_info) != STB_WEAK)
- fails++;
- continue;
+ if (ELF64_R_SYM(relocs->r_info)) {
+ if (sym == prev_sym)
+ this = sym; /* XXX non-NULL */
+ else if (!(ELF64_ST_BIND(sym->st_info) == STB_LOCAL &&
+ ELF64_ST_TYPE (sym->st_info) == STT_NOTYPE)) {
+ ooff = _dl_find_symbol(symn, &this,
+ SYM_SEARCH_ALL | SYM_WARNNOTFOUND | SYM_PLT,
+ sym, object, NULL);
+
+ if (this == NULL) {
+ if (ELF_ST_BIND(sym->st_info) !=
+ STB_WEAK)
+ fails++;
+ continue;
+ }
+ prev_sym = sym;
+ prev_value = this->st_value + ooff;
}
}
@@ -134,10 +142,10 @@ _dl_md_reloc(elf_object_t *object, int rel, int relsz)
}
} else if (this && ((long)r_addr & 7)) {
_dl_bcopy((char *)r_addr, &robj, sizeof(robj));
- robj += this->st_value + ooff;
+ robj += prev_value;
_dl_bcopy(&robj, (char *)r_addr, sizeof(robj));
} else if (this) {
- *(u_int64_t *)r_addr += this->st_value + ooff;
+ *(u_int64_t *)r_addr += prev_value;
}
break;
diff --git a/libexec/ld.so/powerpc/rtld_machine.c b/libexec/ld.so/powerpc/rtld_machine.c
index 1981f7faedd..28245910a21 100644
--- a/libexec/ld.so/powerpc/rtld_machine.c
+++ b/libexec/ld.so/powerpc/rtld_machine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld_machine.c,v 1.48 2011/04/06 11:36:25 miod Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.49 2013/05/08 20:55:14 guenther Exp $ */
/*
* Copyright (c) 1999 Dale Rahn
@@ -77,6 +77,7 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
{
int i;
int numrela;
+ long relrel;
int fails = 0;
struct load_list *llist;
Elf32_Addr loff;
@@ -86,11 +87,11 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
Elf32_Addr *pltcall;
Elf32_Addr *plttable;
Elf32_Addr *pltinfo;
-
Elf32_Addr *first_rela;
loff = object->obj_base;
numrela = object->Dyn.info[relasz] / sizeof(Elf32_Rela);
+ relrel = rel == DT_RELA ? object->relacount : 0;
relas = (Elf32_Rela *)(object->Dyn.info[rel]);
#ifdef DL_PRINTF_DEBUG
@@ -101,6 +102,11 @@ _dl_printf("object relocation size %x, numrela %x\n",
if (relas == NULL)
return(0);
+ if (relrel > numrela) {
+ _dl_printf("relcount > numrel: %ld > %ld\n", relrel, numrela);
+ _dl_exit(20);
+ }
+
pltresolve = NULL;
pltcall = NULL;
plttable = NULL;
@@ -168,13 +174,36 @@ _dl_printf("object relocation size %x, numrela %x\n",
}
}
+ /* tight loop for leading RELATIVE relocs */
+ for (i = 0; i < relrel; i++, relas++) {
+ Elf_Addr *r_addr;
+#ifdef DEBUG
+ const Elf32_Sym *sym;
- for (i = 0; i < numrela; i++, relas++) {
+ if (ELF32_R_TYPE(relas->r_info) != RELOC_RELATIVE) {
+ _dl_printf("RELCOUNT wrong\n");
+ _dl_exit(20);
+ }
+ sym = object->dyn.symtab;
+ sym += ELF32_R_SYM(relas->r_info);
+ if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL ||
+ (ELF32_ST_TYPE(sym->st_info) != STT_SECTION &&
+ ELF32_ST_TYPE(sym->st_info) != STT_NOTYPE)) {
+ _dl_printf("RELATIVE relocation against symbol\n");
+ _dl_exit(20);
+ }
+#endif
+ r_addr = (Elf_Addr *)(relas->r_offset + loff);
+ *r_addr = loff + relas->r_addend;
+ }
+ for (; i < numrela; i++, relas++) {
Elf32_Addr *r_addr = (Elf32_Addr *)(relas->r_offset + loff);
Elf32_Addr ooff;
const Elf32_Sym *sym, *this;
const char *symn;
int type;
+ Elf32_Addr prev_value = 0, prev_ooff = 0;
+ const Elf32_Sym *prev_sym = NULL;
if (ELF32_R_SYM(relas->r_info) == 0xffffff)
continue;
@@ -193,16 +222,25 @@ _dl_printf("object relocation size %x, numrela %x\n",
if (ELF32_R_SYM(relas->r_info) &&
!(ELF32_ST_BIND(sym->st_info) == STB_LOCAL &&
ELF32_ST_TYPE (sym->st_info) == STT_NOTYPE)) {
- ooff = _dl_find_symbol_bysym(object,
- ELF32_R_SYM(relas->r_info), &this,
- SYM_SEARCH_ALL|SYM_WARNNOTFOUND|
- ((type == RELOC_JMP_SLOT) ? SYM_PLT:SYM_NOTPLT),
- sym, NULL);
-
- if (this == NULL) {
- if (ELF_ST_BIND(sym->st_info) != STB_WEAK)
- fails++;
- continue;
+ if (sym == prev_sym) {
+ this = sym; /* XXX any non-NULL */
+ ooff = prev_ooff;
+ } else {
+ ooff = _dl_find_symbol_bysym(object,
+ ELF32_R_SYM(relas->r_info), &this,
+ SYM_SEARCH_ALL|SYM_WARNNOTFOUND|
+ ((type == RELOC_JMP_SLOT) ?
+ SYM_PLT:SYM_NOTPLT), sym, NULL);
+
+ if (this == NULL) {
+ if (ELF_ST_BIND(sym->st_info) !=
+ STB_WEAK)
+ fails++;
+ continue;
+ }
+ prev_sym = sym;
+ prev_value = this->st_value;
+ prev_ooff = ooff;
}
}
@@ -214,7 +252,7 @@ _dl_printf("object relocation size %x, numrela %x\n",
ELF32_ST_TYPE(sym->st_info) == STT_NOTYPE) ) {
*r_addr = ooff + relas->r_addend;
} else {
- *r_addr = ooff + this->st_value +
+ *r_addr = ooff + prev_value +
relas->r_addend;
}
break;
@@ -231,13 +269,13 @@ _dl_printf("rel1 r_addr %x val %x loff %x ooff %x addend %x\n", r_addr,
#endif
} else {
- *r_addr = loff + this->st_value +
+ *r_addr = loff + prev_value +
relas->r_addend;
}
break;
case RELOC_JMP_SLOT:
{
- Elf32_Addr target = ooff + this->st_value +
+ Elf32_Addr target = ooff + prev_value +
relas->r_addend;
Elf32_Addr val = target - (Elf32_Addr)r_addr;
@@ -246,7 +284,7 @@ _dl_printf("rel1 r_addr %x val %x loff %x ooff %x addend %x\n", r_addr,
#ifdef DL_PRINTF_DEBUG
_dl_printf(" ooff %x, sym val %x, addend %x"
" r_addr %x symn [%s] -> %x\n",
- ooff, this->st_value, relas->r_addend,
+ ooff, prev_value, relas->r_addend,
r_addr, symn, val);
#endif
/* if offset is > RELOC_24 deal with it */
@@ -264,7 +302,7 @@ _dl_printf(" ooff %x, sym val %x, addend %x"
}
_dl_dcbf(&r_addr[0]);
_dl_dcbf(&r_addr[2]);
- val= ooff + this->st_value +
+ val= ooff + prev_value +
relas->r_addend;
#ifdef DL_PRINTF_DEBUG
_dl_printf(" symn [%s] val 0x%x\n", symn, val);
@@ -281,13 +319,13 @@ _dl_printf(" symn [%s] val 0x%x\n", symn, val);
break;
case RELOC_GLOB_DAT:
- *r_addr = ooff + this->st_value + relas->r_addend;
+ *r_addr = ooff + prev_value + relas->r_addend;
break;
#if 1
/* should not be supported ??? */
case RELOC_REL24:
{
- Elf32_Addr val = ooff + this->st_value +
+ Elf32_Addr val = ooff + prev_value +
relas->r_addend - (Elf32_Addr)r_addr;
if (!B24_VALID_RANGE(val)){
/* invalid offset */
@@ -342,7 +380,7 @@ _dl_printf(" symn [%s] val 0x%x\n", symn, val);
case RELOC_REL14:
case RELOC_REL14_NTAKEN:
{
- Elf32_Addr val = ooff + this->st_value +
+ Elf32_Addr val = ooff + prev_value +
relas->r_addend - (Elf32_Addr)r_addr;
if (((val & 0xffff8000) != 0) &&
((val & 0xffff8000) != 0xffff8000)) {
@@ -364,7 +402,7 @@ _dl_printf(" symn [%s] val 0x%x\n", symn, val);
#ifdef DL_PRINTF_DEBUG
_dl_printf("copy r_addr %x, sym %x [%s] size %d val %x\n",
r_addr, sym, symn, sym->st_size,
- (ooff + this->st_value+
+ (ooff + prev_value+
relas->r_addend));
#endif
/*
diff --git a/libexec/ld.so/resolve.c b/libexec/ld.so/resolve.c
index 8a232c88a32..c6f551f9406 100644
--- a/libexec/ld.so/resolve.c
+++ b/libexec/ld.so/resolve.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: resolve.c,v 1.61 2013/04/05 12:58:03 kurt Exp $ */
+/* $OpenBSD: resolve.c,v 1.62 2013/05/08 20:55:14 guenther Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -264,6 +264,10 @@ _dl_finalize_object(const char *objname, Elf_Dyn *dynp, Elf_Phdr *phdrp,
object->obj_flags |= DF_1_NOW;
if (dynp->d_tag == DT_FLAGS_1)
object->obj_flags |= dynp->d_un.d_val;
+ if (dynp->d_tag == DT_RELACOUNT)
+ object->relacount = dynp->d_un.d_val;
+ if (dynp->d_tag == DT_RELCOUNT)
+ object->relcount = dynp->d_un.d_val;
dynp++;
}
DL_DEB((" flags %s = 0x%x\n", objname, object->obj_flags ));
diff --git a/libexec/ld.so/resolve.h b/libexec/ld.so/resolve.h
index 3ebfe7061d5..8a482e53b93 100644
--- a/libexec/ld.so/resolve.h
+++ b/libexec/ld.so/resolve.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: resolve.h,v 1.67 2013/04/05 12:58:03 kurt Exp $ */
+/* $OpenBSD: resolve.h,v 1.68 2013/05/08 20:55:14 guenther Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -98,6 +98,9 @@ struct elf_object {
} Dyn;
#define dyn Dyn.u
+ Elf_Addr relacount; /* DT_RELACOUNT */
+ Elf_Addr relcount; /* DT_RELCOUNT */
+
int status;
#define STAT_RELOC_DONE 0x01
#define STAT_GOT_DONE 0x02
diff --git a/libexec/ld.so/sh/rtld_machine.c b/libexec/ld.so/sh/rtld_machine.c
index d41e4ba3866..77bce195695 100644
--- a/libexec/ld.so/sh/rtld_machine.c
+++ b/libexec/ld.so/sh/rtld_machine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld_machine.c,v 1.17 2013/03/29 22:57:07 miod Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.18 2013/05/08 20:55:14 guenther Exp $ */
/*
* Copyright (c) 2004 Dale Rahn
@@ -599,18 +599,27 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
{
long i;
long numrela;
+ long relrel;
int fails = 0;
Elf_Addr loff;
+ Elf_Addr prev_value = 0;
+ const Elf_Sym *prev_sym = NULL;
Elf_RelA *rels;
struct load_list *llist;
loff = object->obj_base;
numrela = object->Dyn.info[relasz] / sizeof(Elf_RelA);
+ relrel = rel == DT_RELA ? object->relacount : 0;
rels = (Elf_RelA *)(object->Dyn.info[rel]);
if (rels == NULL)
return(0);
+ if (relrel > numrela) {
+ _dl_printf("relacount > numrel: %ld > %ld\n", relrel, numrela);
+ _dl_exit(20);
+ }
+
/*
* unprotect some segments if we need it.
*/
@@ -624,7 +633,20 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
}
}
- for (i = 0; i < numrela; i++, rels++) {
+ /* tight loop for leading RELATIVE relocs */
+ for (i = 0; i < relrel; i++, rels++) {
+ Elf_Addr *where;
+
+#ifdef DEBUG
+ if (ELF_R_TYPE(rels->r_info) != R_TYPE(RELATIVE)) {
+ _dl_printf("RELACOUNT wrong\n");
+ _dl_exit(20);
+ }
+#endif
+ where = (Elf_Addr *)(rels->r_offset + loff);
+ *where = rels->r_addend + loff;
+ }
+ for (; i < numrela; i++, rels++) {
Elf_Addr *where, value, ooff, mask;
Elf_Word type;
const Elf_Sym *sym, *this;
@@ -664,6 +686,8 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
if (sym->st_shndx != SHN_UNDEF &&
ELF_ST_BIND(sym->st_info) == STB_LOCAL) {
value += loff;
+ } else if (sym == prev_sym) {
+ value += prev_value;
} else {
this = NULL;
#if 1
@@ -687,7 +711,9 @@ resolve_failed:
fails++;
continue;
}
- value += (Elf_Addr)(ooff + this->st_value);
+ prev_sym = sym;
+ prev_value = (Elf_Addr)(ooff + this->st_value);
+ value += prev_value;
}
}
diff --git a/libexec/ld.so/sparc/rtld_machine.c b/libexec/ld.so/sparc/rtld_machine.c
index a38e5f34fb4..3bb96859171 100644
--- a/libexec/ld.so/sparc/rtld_machine.c
+++ b/libexec/ld.so/sparc/rtld_machine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld_machine.c,v 1.34 2012/12/05 23:20:07 deraadt Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.35 2013/05/08 20:55:14 guenther Exp $ */
/*
* Copyright (c) 1999 Dale Rahn
@@ -178,18 +178,27 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
{
long i;
long numrela;
+ long relrel;
int fails = 0;
Elf_Addr loff;
+ Elf_Addr prev_value = 0;
+ const Elf_Sym *prev_sym = NULL;
Elf_RelA *relas;
struct load_list *llist;
loff = object->obj_base;
numrela = object->Dyn.info[relasz] / sizeof(Elf_RelA);
+ relrel = rel == DT_RELA ? object->relacount : 0;
relas = (Elf_RelA *)(object->Dyn.info[rel]);
if (relas == NULL)
return(0);
+ if (relrel > numrela) {
+ _dl_printf("relacount > numrela: %ld > %ld\n", relrel, numrela);
+ _dl_exit(20);
+ }
+
/*
* unprotect some segments if we need it.
*/
@@ -201,7 +210,20 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
}
}
- for (i = 0; i < numrela; i++, relas++) {
+ /* tight loop for leading RELATIVE relocs */
+ for (i = 0; i < relrel; i++, relas++) {
+ Elf_Addr *where;
+
+#ifdef DEBUG
+ if (ELF_R_TYPE(relas->r_info) != R_TYPE(RELATIVE)) {
+ _dl_printf("RELACOUNT wrong\n");
+ _dl_exit(20);
+ }
+#endif
+ where = (Elf_Addr *)(relas->r_offset + loff);
+ *where = relas->r_addend + loff;
+ }
+ for (; i < numrela; i++, relas++) {
Elf_Addr *where, ooff;
Elf_Word type, value, mask;
const Elf_Sym *sym, *this;
@@ -237,6 +259,8 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
if (sym->st_shndx != SHN_UNDEF &&
ELF_ST_BIND(sym->st_info) == STB_LOCAL) {
value += loff;
+ } else if (sym == prev_sym) {
+ value += prev_value;
} else {
this = NULL;
ooff = _dl_find_symbol_bysym(object,
@@ -252,7 +276,9 @@ resolve_failed:
fails++;
continue;
}
- value += (Elf_Addr)(ooff + this->st_value);
+ prev_sym = sym;
+ prev_value = (Elf_Addr)(ooff + this->st_value);
+ value += prev_value;
}
}
diff --git a/libexec/ld.so/sparc64/rtld_machine.c b/libexec/ld.so/sparc64/rtld_machine.c
index 772fbadb15f..d11eacf9a2d 100644
--- a/libexec/ld.so/sparc64/rtld_machine.c
+++ b/libexec/ld.so/sparc64/rtld_machine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld_machine.c,v 1.48 2013/01/31 06:26:27 guenther Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.49 2013/05/08 20:55:15 guenther Exp $ */
/*
* Copyright (c) 1999 Dale Rahn
@@ -205,18 +205,27 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
{
long i;
long numrela;
+ long relrel;
int fails = 0;
Elf_Addr loff;
+ Elf_Addr prev_value = 0;
+ const Elf_Sym *prev_sym = NULL;
Elf_RelA *relas;
struct load_list *llist;
loff = object->obj_base;
numrela = object->Dyn.info[relasz] / sizeof(Elf64_Rela);
+ relrel = rel == DT_RELA ? object->relacount : 0;
relas = (Elf64_Rela *)(object->Dyn.info[rel]);
if (relas == NULL)
return(0);
+ if (relrel > numrela) {
+ _dl_printf("relacount > numrel: %ld > %ld\n", relrel, numrela);
+ _dl_exit(20);
+ }
+
/*
* unprotect some segments if we need it.
*/
@@ -228,7 +237,20 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
}
}
- for (i = 0; i < numrela; i++, relas++) {
+ /* tight loop for leading RELATIVE relocs */
+ for (i = 0; i < relrel; i++, relas++) {
+ Elf_Addr *where;
+
+#ifdef DEBUG
+ if (ELF_R_TYPE(relas->r_info) != R_TYPE(RELATIVE)) {
+ _dl_printf("RELACOUNT wrong\n");
+ _dl_exit(20);
+ }
+#endif
+ where = (Elf_Addr *)(relas->r_offset + loff);
+ *where = relas->r_addend + loff;
+ }
+ for (; i < numrela; i++, relas++) {
Elf_Addr *where, value, ooff, mask;
Elf_Word type;
const Elf_Sym *sym, *this;
@@ -259,6 +281,8 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
if (sym->st_shndx != SHN_UNDEF &&
ELF_ST_BIND(sym->st_info) == STB_LOCAL) {
value += loff;
+ } else if (sym == prev_sym) {
+ value += prev_value;
} else {
this = NULL;
ooff = _dl_find_symbol_bysym(object,
@@ -274,7 +298,9 @@ resolve_failed:
fails++;
continue;
}
- value += (Elf_Addr)(ooff + this->st_value);
+ prev_sym = sym;
+ prev_value = (Elf_Addr)(ooff + this->st_value);
+ value += prev_value;
}
}