summaryrefslogtreecommitdiff
path: root/lib/csu
diff options
context:
space:
mode:
authorKurt Miller <kurt@cvs.openbsd.org>2009-01-14 19:45:21 +0000
committerKurt Miller <kurt@cvs.openbsd.org>2009-01-14 19:45:21 +0000
commit2f738540d708321613a90a4fdc5e4d1c0f866f94 (patch)
tree6ffca79df729cbdccd6c9a7f61b5ab62b6aa517d /lib/csu
parentfc4492de942fe8fcf823c8952e382e6dac728492 (diff)
Re-enable pie support on macppc (still off by default but usable
again). Due to the way executable sections are loaded by the kernel, a one page .got section with the blrl instruction may be in the data cache and not flushed causing random crashes upon process startup. Flush the data cache before ___start() jumps there. Also mprotect the .got section to be read/exec instead of read/write/exec. ld.so knows how to cope and static binaries don't write to .got. written by and okay drahn@
Diffstat (limited to 'lib/csu')
-rw-r--r--lib/csu/powerpc/Makefile14
-rw-r--r--lib/csu/powerpc/crt0.c74
2 files changed, 76 insertions, 12 deletions
diff --git a/lib/csu/powerpc/Makefile b/lib/csu/powerpc/Makefile
index d1ff5d85084..acdea1b84d6 100644
--- a/lib/csu/powerpc/Makefile
+++ b/lib/csu/powerpc/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.18 2008/11/21 19:19:13 otto Exp $
+# $OpenBSD: Makefile,v 1.19 2009/01/14 19:45:20 kurt Exp $
# from: @(#)Makefile 8.1 (Berkeley) 6/1/93
CFLAGS+= -DLIBC_SCCS
@@ -14,8 +14,8 @@ CFLAGS+= -I${ELFDIR} -I${.CURDIR}
all: ${OBJS}
crt0.o: crt0.c
- @echo ${COMPILE.c} -DCRT0 ${.CURDIR}/crt0.c -o ${.TARGET}
- @${COMPILE.c} -DCRT0 ${.CURDIR}/crt0.c -o ${.TARGET}.o
+ @echo ${COMPILE.c} -fpie -DCRT0 ${.CURDIR}/crt0.c -o ${.TARGET}
+ @${COMPILE.c} -fpie -DCRT0 ${.CURDIR}/crt0.c -o ${.TARGET}.o
@${LD} -x -r -o ${.TARGET} ${.TARGET}.o
@rm -f ${.TARGET}.o
@@ -26,8 +26,8 @@ gcrt0.o: crt0.c
@rm -f ${.TARGET}.o
crtbegin.o: crtbegin.c
- @echo ${COMPILE.c} ${ELFDIR}/crtbegin.c -o ${.TARGET}
- @${COMPILE.c} ${ELFDIR}/crtbegin.c -o ${.TARGET}.o
+ @echo ${COMPILE.c} -fpie ${ELFDIR}/crtbegin.c -o ${.TARGET}
+ @${COMPILE.c} -fpie ${ELFDIR}/crtbegin.c -o ${.TARGET}.o
@${LD} -x -r -o ${.TARGET} ${.TARGET}.o
@rm -f ${.TARGET}.o
@@ -38,8 +38,8 @@ crtbeginS.o: crtbeginS.c
@rm -f ${.TARGET}.o
crtend.o: crtend.c
- @echo ${COMPILE.c} ${ELFDIR}/crtend.c -o ${.TARGET}
- @${COMPILE.c} ${ELFDIR}/crtend.c -o ${.TARGET}.o
+ @echo ${COMPILE.c} -fpie ${ELFDIR}/crtend.c -o ${.TARGET}
+ @${COMPILE.c} -fpie ${ELFDIR}/crtend.c -o ${.TARGET}.o
@${LD} -x -r -o ${.TARGET} ${.TARGET}.o
@rm -f ${.TARGET}.o
diff --git a/lib/csu/powerpc/crt0.c b/lib/csu/powerpc/crt0.c
index 901ba23dbc0..2d2f9104114 100644
--- a/lib/csu/powerpc/crt0.c
+++ b/lib/csu/powerpc/crt0.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: crt0.c,v 1.3 2003/08/25 17:59:42 drahn Exp $ */
+/* $OpenBSD: crt0.c,v 1.4 2009/01/14 19:45:20 kurt Exp $ */
/* $NetBSD: crt0.c,v 1.1 1996/09/12 16:59:02 cgd Exp $ */
/*
* Copyright (c) 1995 Christopher G. Demetriou
@@ -32,6 +32,7 @@
*/
#include <sys/param.h>
#include <stdlib.h>
+#include <sys/syscall.h>
char **environ;
char * __progname = "";
@@ -46,11 +47,74 @@ extern unsigned char _etext, _eprol;
static inline char * _strrchr(const char *p, char ch);
-__asm(".globl __start");
-__asm(".type __start@function");
-__asm("__start = _start");
+#define STR(x) __STRING(x)
+__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"
+" # move argument registers to saved registers for startup flush \n"
+" mr %r26, %r3 \n"
+" mr %r25, %r4 \n"
+" mr %r24, %r5 \n"
+" mr %r23, %r6 \n"
+" mr %r22, %r7 \n"
+" mflr %r27 /* save off old link register */ \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"
+"1: \n"
+" mflr %r5 # this stores where we are (+4) \n"
+" lwz %r18, 0(%r5) # 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 the 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 calulate. \n"
+" */ \n"
+" add %r28, %r18, %r5 \n"
+" mr %r6, %r5 # save offset for later use \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, 5 /* (PROT_READ|PROT_EXEC) */ \n"
+" sc \n"
+" \n"
+" mr %r5, %r6 \n"
+" \n"
+" li %r0, 0 \n"
+" # flush the blrl instruction out of the data cache \n"
+" dcbf %r5, %r18 \n"
+" sync \n"
+" isync \n"
+" # make certain that the got table addr is not in the icache \n"
+" icbi %r5, %r18 \n"
+" sync \n"
+" isync \n"
+" mtlr %r27 \n"
+" # move argument registers back from saved registers \n"
+" mr %r3, %r26 \n"
+" mr %r4, %r25 \n"
+" mr %r5, %r24 \n"
+" mr %r6, %r23 \n"
+" mr %r7, %r22 \n"
+" b ___start \n"
+);
+
void
-_start(int argc, char **argv, char **envp, void *aux, void (*cleanup)(void))
+___start(int argc, char **argv, char **envp, void *aux, void (*cleanup)(void))
{
char *s;