summaryrefslogtreecommitdiff
path: root/libexec/ld.so/arm
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2013-05-08 20:55:16 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2013-05-08 20:55:16 +0000
commit35485e4cec2e872efd51189781427d610c1e3323 (patch)
tree8b0326fe8e024e1c98601bec23cbe837f1a66d6b /libexec/ld.so/arm
parent2b2ce0877dff0ffb0f8ebc8c28b18bae5e9836a3 (diff)
Implement symbol caching and RELACOUNT/RELCOUNT optimizations.
Much assistance and testing by miod ok miod@
Diffstat (limited to 'libexec/ld.so/arm')
-rw-r--r--libexec/ld.so/arm/rtld_machine.c32
1 files changed, 29 insertions, 3 deletions
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;
}
}