summaryrefslogtreecommitdiff
path: root/libexec/ld.so
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2021-11-12 22:28:14 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2021-11-12 22:28:14 +0000
commite55df61ad48c5e61339082366dff6ae12ba106fa (patch)
treecec1553c97c11f0f72684719f4503212637a03cd /libexec/ld.so
parent39ef127bdaa3d16dcc1361575fc0f7d8a21268d2 (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.c36
-rw-r--r--libexec/ld.so/resolve.c4
-rw-r--r--libexec/ld.so/resolve.h7
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