Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/csu/common Add static PIE support for i386 and AMD64.



details:   https://anonhg.NetBSD.org/src/rev/ad36d5a1c14d
branches:  trunk
changeset: 991411:ad36d5a1c14d
user:      joerg <joerg%NetBSD.org@localhost>
date:      Thu Jul 12 21:36:45 2018 +0000

description:
Add static PIE support for i386 and AMD64.

The basic glue works with mininal changes for other architectures as
well, but those require linker changes first to avoid leaking dynamic
relocations into the binary.

diffstat:

 lib/csu/common/crt0-common.c |  96 +++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 94 insertions(+), 2 deletions(-)

diffs (122 lines):

diff -r 0a6c9d53f385 -r ad36d5a1c14d lib/csu/common/crt0-common.c
--- a/lib/csu/common/crt0-common.c      Thu Jul 12 21:35:12 2018 +0000
+++ b/lib/csu/common/crt0-common.c      Thu Jul 12 21:36:45 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: crt0-common.c,v 1.17 2018/07/12 21:35:12 joerg Exp $ */
+/* $NetBSD: crt0-common.c,v 1.18 2018/07/12 21:36:45 joerg Exp $ */
 
 /*
  * Copyright (c) 1998 Christos Zoulas
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: crt0-common.c,v 1.17 2018/07/12 21:35:12 joerg Exp $");
+__RCSID("$NetBSD: crt0-common.c,v 1.18 2018/07/12 21:36:45 joerg Exp $");
 
 #include <sys/types.h>
 #include <sys/exec.h>
@@ -192,11 +192,103 @@
 }
 #endif
 
+#if defined(__x86_64__) || defined(__i386__)
+#  define HAS_RELOCATE_SELF
+#  if defined(__x86_64__)
+#  define RELA
+#  define REL_TAG DT_RELA
+#  define RELSZ_TAG DT_RELASZ
+#  define REL_TYPE Elf_Rela
+#  else
+#  define REL_TAG DT_REL
+#  define RELSZ_TAG DT_RELSZ
+#  define REL_TYPE Elf_Rel
+#  endif
+
+#include <elf.h>
+
+static void relocate_self(struct ps_strings *) __noinline;
+
+static void
+relocate_self(struct ps_strings *ps_strings)
+{
+       AuxInfo *aux = (AuxInfo *)(ps_strings->ps_argvstr + ps_strings->ps_nargvstr +
+           ps_strings->ps_nenvstr + 2);
+       uintptr_t relocbase;
+       const Elf_Phdr *phdr;
+       Elf_Half phnum;
+
+       for (; aux->a_type != AT_NULL; ++aux) {
+               switch (aux->a_type) {
+               case AT_BASE:
+                       if (aux->a_v)
+                               return;
+                       break;
+               case AT_PHDR:
+                       phdr = (void *)aux->a_v;
+                       break;
+               case AT_PHNUM:
+                       phnum = (Elf_Half)aux->a_v;
+                       break;
+               }
+       }
+       const Elf_Phdr *phlimit = phdr + phnum, *dynphdr;
+
+       for (; phdr < phlimit; ++phdr) {
+               if (phdr->p_type == PT_DYNAMIC)
+                       dynphdr = phdr;
+               if (phdr->p_type == PT_PHDR)
+                       relocbase = (uintptr_t)phdr - phdr->p_vaddr;
+       }
+       Elf_Dyn *dynp = (Elf_Dyn *)((uint8_t *)dynphdr->p_vaddr + relocbase);
+
+       const REL_TYPE *relocs = 0, *relocslim;
+       Elf_Addr relocssz = 0;
+
+       for (; dynp->d_tag != DT_NULL; dynp++) {
+               switch (dynp->d_tag) {
+               case REL_TAG:
+                       relocs =
+                           (const REL_TYPE *)(relocbase + dynp->d_un.d_ptr);
+                       break;
+               case RELSZ_TAG:
+                       relocssz = dynp->d_un.d_val;
+                       break;
+               }
+       }
+       relocslim = (const REL_TYPE *)((const uint8_t *)relocs + relocssz);
+       for (; relocs < relocslim; ++relocs) {
+               Elf_Addr *where;
+
+               where = (Elf_Addr *)(relocbase + relocs->r_offset);
+
+               switch (ELF_R_TYPE(relocs->r_info)) {
+               case R_TYPE(RELATIVE):  /* word64 B + A */
+#ifdef RELA
+                       *where = (Elf_Addr)(relocbase + relocs->r_addend);
+#else
+                       *where += (Elf_Addr)relocbase;
+#endif
+                       break;
+#ifdef IFUNC_RELOCATION
+               case IFUNC_RELOCATION:
+                       break;
+#endif
+               default:
+                       abort();
+               }
+       }
+}
+#endif
+
 void
 ___start(void (*cleanup)(void),                        /* from shared loader */
     const Obj_Entry *obj,                      /* from shared loader */
     struct ps_strings *ps_strings)
 {
+#if defined(HAS_RELOCATE_SELF)
+       relocate_self(ps_strings);
+#endif
 
        if (ps_strings == NULL)
                _FATAL("ps_strings missing\n");



Home | Main Index | Thread Index | Old Index