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");