summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKurt Miller <kurt@cvs.openbsd.org>2014-12-26 13:52:02 +0000
committerKurt Miller <kurt@cvs.openbsd.org>2014-12-26 13:52:02 +0000
commit5702505e2e0db38792c1d194969f502336e85296 (patch)
tree702872d91ca6af6d59aac966a2199ea479891e7e
parentb1c5433101e97703831a018cdbf79fefebb56ad6 (diff)
Self-relocation code for powerpc.
-rw-r--r--lib/csu/powerpc/md_init.h100
1 files changed, 99 insertions, 1 deletions
diff --git a/lib/csu/powerpc/md_init.h b/lib/csu/powerpc/md_init.h
index 3fab44b9a98..8625ce57cf1 100644
--- a/lib/csu/powerpc/md_init.h
+++ b/lib/csu/powerpc/md_init.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: md_init.h,v 1.2 2013/12/03 06:21:41 guenther Exp $ */
+/* $OpenBSD: md_init.h,v 1.3 2014/12/26 13:52:01 kurt Exp $ */
/*-
* Copyright (c) 2001 Ross Harvey
@@ -148,3 +148,101 @@ __asm( \
" mr %r6, %r22 \n" \
" b ___start \n" \
)
+
+#define MD_RCRT0_START \
+__asm( \
+" .text \n" \
+" .section \".text\" \n" \
+" .align 2 \n" \
+" .globl _start \n" \
+" .type _start, @function \n" \
+" .globl __start \n" \
+" .type __start, @function \n" \
+"_start: \n" \
+"__start: \n" \
+" mr %r19, %r1 # save stack in r19 \n" \
+" stwu 1, (-16 -((9+3)*4))(%r1) # allocate dl_data \n" \
+" \n" \
+" # move argument registers to saved registers for startup flush \n" \
+" mr %r20, %r3 # argc \n" \
+" mr %r21, %r4 # argv \n" \
+" mr %r22, %r5 # envp \n" \
+" mflr %r27 /* save off old link register */ \n" \
+" stw %r27, 4(%r19) # save in normal location \n" \
+" bl 1f \n" \
+" # this instruction never gets executed but can be used \n" \
+" # to find the virtual address where the page is loaded. \n" \
+" bl _GLOBAL_OFFSET_TABLE_@local-4 \n" \
+" bl _DYNAMIC@local \n" \
+"1: \n" \
+" mflr %r6 # this stores where we are (+4) \n" \
+" lwz %r18, 0(%r6) # load the instruction at offset_sym \n" \
+" # it contains an offset to the location \n" \
+" # of the GOT. \n" \
+" \n" \
+" rlwinm %r18,%r18,0,8,30 # mask off offset portion of the instr. \n" \
+" \n" \
+" /* \n" \
+" * these adds effectively calculate the value the \n" \
+" * bl _GLOBAL_OFFSET_TABLE_@local-4 \n" \
+" * operation that would be below would calculate. \n" \
+" */ \n" \
+" add %r28, %r18, %r6 \n" \
+" \n" \
+" /* mprotect GOT-4 for correct execution of blrl instruction */ \n" \
+" li %r0, " STR(SYS_mprotect) " \n" \
+" mr %r3, %r28 \n" \
+" li %r4, 4 \n" \
+" li %r5, 7 /* (PROT_READ|PROT_WRITE|PROT_EXEC) */ \n" \
+" sc \n" \
+" \n" \
+" li %r0, 0 \n" \
+" # flush the blrl instruction out of the data cache \n" \
+" dcbf %r6, %r18 \n" \
+" sync \n" \
+" isync \n" \
+" # make certain that the got table addr is not in the icache \n" \
+" icbi %r6, %r18 \n" \
+" sync \n" \
+" isync \n" \
+" \n" \
+" /* This calculates the address of _DYNAMIC the same way \n" \
+" * that the GLOBAL_OFFSET_TABLE was calculated. \n" \
+" */ \n" \
+" lwz %r18, 4(%r6) \n" \
+" rlwinm %r18,%r18,0,8,30 # mask off offset portion of the instr. \n" \
+" add %r8, %r18, %r6 # address of _DYNAMIC (arg6 for _dl_boot) \n" \
+" addi %r18, %r8, 4 # correction. \n" \
+" lwz %r4, 4(%r28) # load addr of _DYNAMIC according to got. \n" \
+" sub %r4, %r18, %r4 # determine load offset \n" \
+" \n" \
+" subi %r3, %r21, 4 # Get stack pointer (arg0 for _dl_boot). \n" \
+" addi %r4, %r1, 8 # dl_data \n" \
+" mr %r5, %r18 # dynamicp \n" \
+" \n" \
+" bl _dl_boot_bind@local \n" \
+" \n" \
+" mtlr %r27 \n" \
+" # move argument registers back from saved registers \n" \
+" mr %r3, %r20 \n" \
+" mr %r4, %r21 \n" \
+" mr %r5, %r22 \n" \
+" li %r6, 0 \n" \
+" b ___start \n" \
+" \n" \
+" .text \n" \
+" .align 2 \n" \
+" .globl _dl_exit \n" \
+" .type _dl_exit, @function \n" \
+"_dl_exit: \n" \
+" li %r0, " STR(SYS_exit) " \n" \
+" sc \n" \
+" blr \n" \
+" \n" \
+" .text \n" \
+" .align 2 \n" \
+" .globl _dl_printf \n" \
+" .type _dl_printf, @function \n" \
+"_dl_printf: \n" \
+" blr \n" \
+)