From 2f7dfe5d206aa9341f2242ffd4e9f8373d3f8f5f Mon Sep 17 00:00:00 2001 From: kettenis Date: Sat, 27 Dec 2014 13:17:51 +0000 Subject: [PATCH] Static PIE support for alpha. This adds alpha-specific first-pass GOT relocation code to boot.h. The assembly code is pure magic. The numeric register names don't make it easier to understand (or compare with the equivalent ld.so code). Unfortunately the assembler only understands a few symbolic register names. Renames the crt0.o entry point to __start. Our compiler was already using __start and the linker will soon follow. ok kurt@ --- lib/csu/alpha/md_init.h | 50 ++++++++++++++++++++++++++++++++++++----- lib/csu/boot.h | 38 +++++++++++++++++++++++++++++-- 2 files changed, 80 insertions(+), 8 deletions(-) diff --git a/lib/csu/alpha/md_init.h b/lib/csu/alpha/md_init.h index 04a726860ab..9526e212566 100644 --- a/lib/csu/alpha/md_init.h +++ b/lib/csu/alpha/md_init.h @@ -1,4 +1,4 @@ -/* $OpenBSD: md_init.h,v 1.2 2013/12/03 06:21:40 guenther Exp $ */ +/* $OpenBSD: md_init.h,v 1.3 2014/12/27 13:17:52 kettenis Exp $ */ /*- * Copyright (c) 2001 Ross Harvey * All rights reserved. @@ -62,14 +62,52 @@ " ret \n" \ " .previous") -/* XXX this should not be necessary: ld should use __start */ + #define MD_CRT0_START \ __asm ( \ - ".globl _start \n" \ - ".type _start@function \n" \ - "_start = __start") + " .globl __start \n" \ + " .type __start@function \n" \ + "__start = ___start") + +#define MD_RCRT0_START \ + __asm ( \ + " .globl __start \n" \ + " .type __start@function \n" \ + "__start: \n" \ + " .set noreorder \n" \ + " br $27, L1 \n" \ + "L1: \n" \ + " ldgp $gp, 0($27) \n" \ + " mov $16, $9 \n" \ + " br $11, L2 \n" \ + "L2: ldiq $12, L2 \n" \ + " subq $11, $12, $11 \n" \ + " mov $11, $17 \n" \ + " lda $6, _DYNAMIC \n" \ + " addq $11, $6, $16 \n" \ + " bsr $26, _reloc_alpha_got \n" \ + " lda $sp, -80($sp) \n" \ + " mov $9, $16 \n" \ + " lda $11, 0($sp) \n" \ + " mov $11, $17 \n" \ + " mov 0, $18 \n" \ + " jsr $26, _dl_boot_bind \n" \ + " ldgp $gp, 0($26) \n" \ + " mov $9, $16 \n" \ + " mov 0, $17 \n" \ + " jsr $26, ___start \n" \ + ".globl _dl_exit \n" \ + ".type _dl_exit@function \n" \ + "_dl_exit: \n" \ + " lda $0, 1 \n" \ + " callsys \n" \ + " ret \n" \ + ".globl _dl_printf \n" \ + ".type _dl_printf@function \n" \ + "_dl_printf: \n" \ + " ret") -#define MD_START __start +#define MD_START ___start #define MD_START_ARGS char **sp, void (*cleanup)(void) #define MD_START_SETUP \ char **argv, **envp; \ diff --git a/lib/csu/boot.h b/lib/csu/boot.h index f7c8c5f9f21..4120d54adb4 100644 --- a/lib/csu/boot.h +++ b/lib/csu/boot.h @@ -1,4 +1,4 @@ -/* $OpenBSD: boot.h,v 1.7 2014/12/25 21:38:45 kurt Exp $ */ +/* $OpenBSD: boot.h,v 1.8 2014/12/27 13:17:51 kettenis Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -54,6 +54,7 @@ #include "../../lib/csu/os-note-elf.h" #ifdef RCRT0 + /* * Local decls. */ @@ -282,7 +283,7 @@ _dl_boot_bind(const long sp, long *dl_data, Elf_Dyn *dynamicp) else pagesize = 4096; -#if defined(__sparc64__) +#if defined(__alpha__) || defined(__sparc64__) start = ELF_TRUNC((Elf_Addr)__plt_start, pagesize); size = ELF_ROUND((Elf_Addr)__plt_end - start, pagesize); mprotect((void *)start, size, PROT_READ); @@ -292,4 +293,37 @@ _dl_boot_bind(const long sp, long *dl_data, Elf_Dyn *dynamicp) size = ELF_ROUND((Elf_Addr)__got_end - start, pagesize); mprotect((void *)start, size, GOT_PERMS); } + +#ifdef __alpha__ + +void _reloc_alpha_got(Elf_Dyn *dynp, Elf_Addr relocbase); + +void +_reloc_alpha_got(Elf_Dyn *dynp, Elf_Addr relocbase) +{ + const Elf_RelA *rela = 0, *relalim; + Elf_Addr relasz = 0; + Elf_Addr *where; + + for (; dynp->d_tag != DT_NULL; dynp++) { + switch (dynp->d_tag) { + case DT_RELA: + rela = (const Elf_RelA *)(relocbase + dynp->d_un.d_ptr); + break; + case DT_RELASZ: + relasz = dynp->d_un.d_val; + break; + } + } + relalim = (const Elf_RelA *)((caddr_t)rela + relasz); + for (; rela < relalim; rela++) { + if (ELF64_R_TYPE(rela->r_info) != RELOC_RELATIVE) + continue; + where = (Elf_Addr *)(relocbase + rela->r_offset); + *where += (Elf_Addr)relocbase; + } +} + +#endif + #endif /* RCRT0 */ -- 2.20.1