diff options
author | Philip Guenther <guenther@cvs.openbsd.org> | 2021-11-12 22:28:14 +0000 |
---|---|---|
committer | Philip Guenther <guenther@cvs.openbsd.org> | 2021-11-12 22:28:14 +0000 |
commit | e55df61ad48c5e61339082366dff6ae12ba106fa (patch) | |
tree | cec1553c97c11f0f72684719f4503212637a03cd /libexec/ld.so | |
parent | 39ef127bdaa3d16dcc1361575fc0f7d8a21268d2 (diff) |
Add support for RELR relocations in the executable and share objects.
This doesn't affect ld.so's self-reloc, which still requires DT_REL/DT_RELA
ok kettenis@
Diffstat (limited to 'libexec/ld.so')
-rw-r--r-- | libexec/ld.so/loader.c | 36 | ||||
-rw-r--r-- | libexec/ld.so/resolve.c | 4 | ||||
-rw-r--r-- | libexec/ld.so/resolve.h | 7 |
3 files changed, 43 insertions, 4 deletions
diff --git a/libexec/ld.so/loader.c b/libexec/ld.so/loader.c index db66346e41c..2063098a8b0 100644 --- a/libexec/ld.so/loader.c +++ b/libexec/ld.so/loader.c @@ -1,4 +1,4 @@ -/* $OpenBSD: loader.c,v 1.192 2021/05/25 17:01:36 kn Exp $ */ +/* $OpenBSD: loader.c,v 1.193 2021/11/12 22:28:13 guenther Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -61,6 +61,7 @@ void _dl_call_init_recurse(elf_object_t *object, int initfirst); void _dl_clean_boot(void); static inline void unprotect_if_textrel(elf_object_t *_object); static inline void reprotect_if_textrel(elf_object_t *_object); +static void _dl_rreloc(elf_object_t *_object); int _dl_pagesz __relro = 4096; int _dl_bindnow __relro = 0; @@ -721,6 +722,7 @@ _dl_rtld(elf_object_t *object) * Do relocation information first, then GOT. */ unprotect_if_textrel(object); + _dl_rreloc(object); fails =_dl_md_reloc(object, DT_REL, DT_RELSZ); fails += _dl_md_reloc(object, DT_RELA, DT_RELASZ); reprotect_if_textrel(object); @@ -947,3 +949,35 @@ reprotect_if_textrel(elf_object_t *object) } } } + +static void +_dl_rreloc(elf_object_t *object) +{ + const Elf_Relr *reloc, *rend; + Elf_Addr loff = object->obj_base; + + reloc = object->dyn.relr; + rend = (const Elf_Relr *)((char *)reloc + object->dyn.relrsz); + + while (reloc < rend) { + Elf_Addr *where; + + where = (Elf_Addr *)(*reloc + loff); + *where++ += loff; + + for (reloc++; reloc < rend && (*reloc & 1); reloc++) { + Elf_Addr bits = *reloc >> 1; + + Elf_Addr *here = where; + while (bits != 0) { + if (bits & 1) { + *here += loff; + } + bits >>= 1; + here++; + } + where += (8 * sizeof *reloc) - 1; + } + } +} + diff --git a/libexec/ld.so/resolve.c b/libexec/ld.so/resolve.c index 4d0928b4f2e..2879c331c3a 100644 --- a/libexec/ld.so/resolve.c +++ b/libexec/ld.so/resolve.c @@ -1,4 +1,4 @@ -/* $OpenBSD: resolve.c,v 1.95 2021/06/02 07:29:03 semarie Exp $ */ +/* $OpenBSD: resolve.c,v 1.96 2021/11/12 22:28:13 guenther Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -368,6 +368,8 @@ _dl_finalize_object(const char *objname, Elf_Dyn *dynp, Elf_Phdr *phdrp, object->Dyn.info[DT_FINI_ARRAY] += obase; if (object->Dyn.info[DT_PREINIT_ARRAY]) object->Dyn.info[DT_PREINIT_ARRAY] += obase; + if (object->Dyn.info[DT_RELR]) + object->Dyn.info[DT_RELR] += obase; if (gnu_hash) { Elf_Word *hashtab = (Elf_Word *)(gnu_hash + obase); diff --git a/libexec/ld.so/resolve.h b/libexec/ld.so/resolve.h index 7c14005a658..6b0d36b292c 100644 --- a/libexec/ld.so/resolve.h +++ b/libexec/ld.so/resolve.h @@ -1,4 +1,4 @@ -/* $OpenBSD: resolve.h,v 1.98 2021/06/02 07:29:03 semarie Exp $ */ +/* $OpenBSD: resolve.h,v 1.99 2021/11/12 22:28:13 guenther Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -47,7 +47,7 @@ #endif /* Number of low tags that are used saved internally (0 .. DT_NUM-1) */ -#define DT_NUM (DT_PREINIT_ARRAYSZ + 1) +#define DT_NUM (DT_RELR + 1) struct load_list { struct load_list *next; @@ -132,6 +132,9 @@ struct elf_object { Elf_Addr encoding; initarrayfunc **preinit_array; Elf_Addr preinit_arraysz; + Elf_Addr unassigned; + Elf_Addr relrsz; + Elf_Relr *relr; } u; } Dyn; #define dyn Dyn.u |