diff options
author | Philip Guenther <guenther@cvs.openbsd.org> | 2019-10-05 20:49:49 +0000 |
---|---|---|
committer | Philip Guenther <guenther@cvs.openbsd.org> | 2019-10-05 20:49:49 +0000 |
commit | 80066f1b127d4f890d8716bf8213ecd1beaa052c (patch) | |
tree | db18e423b64d9ef576fc79d752f8f0f09b8b53f6 | |
parent | 810bdf5e8e0f154b58a614d4671f9b841e1f10e1 (diff) |
Tighten handling of pure relative DIR32 relocations and those referencing
sections; despite being a RELA arch, ld.so was making assumptions about
the initialization of the targeted location.
Add the relative relocation optimization, handling relocations
covered by the DT_RELACOUNT value in a tight loop.
ok mpi@ deraadt@
-rw-r--r-- | libexec/ld.so/hppa/rtld_machine.c | 23 |
1 files changed, 12 insertions, 11 deletions
diff --git a/libexec/ld.so/hppa/rtld_machine.c b/libexec/ld.so/hppa/rtld_machine.c index c7be3288356..4bc60aef068 100644 --- a/libexec/ld.so/hppa/rtld_machine.c +++ b/libexec/ld.so/hppa/rtld_machine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtld_machine.c,v 1.39 2019/08/06 04:01:42 guenther Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.40 2019/10/05 20:49:48 guenther Exp $ */ /* * Copyright (c) 2004 Michael Shalayeff @@ -105,10 +105,12 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz) { Elf_RelA *rela; Elf_Addr loff; + int num_relative; int i, numrela, fails = 0; loff = object->obj_base; numrela = object->Dyn.info[relasz] / sizeof(Elf_RelA); + num_relative = rel == DT_RELA ? object->relacount : 0; rela = (Elf_RelA *)(object->Dyn.info[rel]); #ifdef DEBUG @@ -153,7 +155,12 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz) if (object->obj_type == OBJTYPE_EXE) _hppa_dl_set_dp(object->dyn.pltgot); - for (i = 0; i < numrela; i++, rela++) { + /* tight loop for leading relative relocs */ + for (i = 0; i < num_relative; i++, rela++) { + Elf_Addr *where = (Elf_Addr *)(rela->r_offset + loff); + *where = rela->r_addend + loff; + } + for (; i < numrela; i++, rela++) { struct sym_res sr; const Elf_Sym *sym; Elf_Addr *pt; @@ -199,16 +206,10 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz) #endif } else { /* - * XXX should objects ever get their - * sections loaded nonsequential this - * would have to get a section number - * (ELF_R_SYM(rela->r_info))-1 and then: - * *pt = sect->addr + rela->r_addend; + * Either a relative relocation (symbol 0) + * or a relocation against a local section */ - if (ELF_R_SYM(rela->r_info)) - *pt += loff; - else - *pt += loff + rela->r_addend; + *pt = loff + sym->st_value + rela->r_addend; #ifdef DEBUG DL_DEB(("[%x]DIR32: %s @ 0x%x\n", i, object->load_name, *pt)); |