summaryrefslogtreecommitdiff
path: root/libexec/ld.so/m68k/rtld_machine.c
diff options
context:
space:
mode:
Diffstat (limited to 'libexec/ld.so/m68k/rtld_machine.c')
-rw-r--r--libexec/ld.so/m68k/rtld_machine.c41
1 files changed, 33 insertions, 8 deletions
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: