Static PIE support for alpha.
authorkettenis <kettenis@openbsd.org>
Sat, 27 Dec 2014 13:17:51 +0000 (13:17 +0000)
committerkettenis <kettenis@openbsd.org>
Sat, 27 Dec 2014 13:17:51 +0000 (13:17 +0000)
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
lib/csu/boot.h

index 04a7268..9526e21 100644 (file)
@@ -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.
        "       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;                    \
index f7c8c5f..4120d54 100644 (file)
@@ -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 */