Module Name:    src
Committed By:   joerg
Date:           Thu Jul 12 21:36:46 UTC 2018

Modified Files:
        src/lib/csu/common: crt0-common.c

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.17 -r1.18 src/lib/csu/common/crt0-common.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/csu/common/crt0-common.c
diff -u src/lib/csu/common/crt0-common.c:1.17 src/lib/csu/common/crt0-common.c:1.18
--- src/lib/csu/common/crt0-common.c:1.17	Thu Jul 12 21:35:12 2018
+++ src/lib/csu/common/crt0-common.c	Thu Jul 12 21:36:45 2018
@@ -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 @@ fix_iplt(void)
 }
 #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");

Reply via email to