From 3a0aa55040e0c50335ee074019fe207f8c4bcc18 Mon Sep 17 00:00:00 2001 From: Antoine Leca Date: Fri, 1 Feb 2013 09:39:47 +0000 Subject: [PATCH] libc: make MINIX assembly code position-independent While here, simplify ucontext.S . makes libc link without the messy DT_TEXTREL warning. Change-Id: I4656d9068eab5ed2fa1e391242883d5dd9d93644 --- lib/libc/arch/i386/sys-minix/__sigreturn.S | 6 ++ lib/libc/arch/i386/sys-minix/ucontext.S | 119 +++++++-------------- 2 files changed, 47 insertions(+), 78 deletions(-) diff --git a/lib/libc/arch/i386/sys-minix/__sigreturn.S b/lib/libc/arch/i386/sys-minix/__sigreturn.S index 01182b058..094440aee 100644 --- a/lib/libc/arch/i386/sys-minix/__sigreturn.S +++ b/lib/libc/arch/i386/sys-minix/__sigreturn.S @@ -6,4 +6,10 @@ IMPORT(_sigreturn) ENTRY(__sigreturn) addl $16, %esp +#ifndef PIC jmp _C_LABEL(_sigreturn) +#else + PIC_PROLOGUE /* push %ebx, but we do not care */ + pop %eax /* special knowledge of how PIC works: discard pushed EBX */ + jmp PIC_PLT(_C_LABEL(_sigreturn)) +#endif /* PIC */ diff --git a/lib/libc/arch/i386/sys-minix/ucontext.S b/lib/libc/arch/i386/sys-minix/ucontext.S index 3c73c0970..48a6fff99 100644 --- a/lib/libc/arch/i386/sys-minix/ucontext.S +++ b/lib/libc/arch/i386/sys-minix/ucontext.S @@ -1,26 +1,11 @@ #include #include -#ifdef __ACK__ -.text -begtext: -#ifdef __ACK__ -.rom -#else -.data -#endif -begrom: -.data -begdata: -.bss -begbss: -#endif - - IMPORT(getuctx) IMPORT(setuctx) IMPORT(resumecontext) + .globl _C_LABEL(__errno) /* MCF_MAGIC value from */ #define MCF_MAGIC 0xc0ffee @@ -43,59 +28,41 @@ ENTRY(getcontext) * saving its signal mask, then we can skip the context switch to * PM and kernel altogether and only save general-purpose registers. */ - mov (%esp), %ecx /* Save return address: - * When setcontext or swapcontext is called, - * we jump to this address and continue - * running. */ - mov 4(%esp), %edx /* edx = ucp */ /* Check null pointer */ cmp $0, %edx /* edx == NULL? */ jne 3f /* Not null, continue */ - movl $EFAULT, (_C_LABEL(errno)) + PIC_PROLOGUE + call PIC_PLT(_C_LABEL(__errno)) + PIC_EPILOGUE + movl $EFAULT, (%eax) xor %eax, %eax dec %eax /* return -1 */ ret 3: /* Check flags */ - push %ecx /* save ecx */ - push %ebx /* save ebx */ - lea UC_FLAGS(%edx), %ebx /* ebx = &(ucp->uc_flags) */ - mov (%ebx), %ecx /* ecx = ucp->uc_flags */ - mov $UCF_IGNFPU, %eax - or $UCF_IGNSIGM, %eax - cmp %eax, %ecx /* is UCF_IGNFPU or UCF_IGNSIGM set? */ - pop %ebx /* restore ebx */ - pop %ecx /* restore ecx */ - jz 1f /* Both are set, skip getuctx */ - -0: - push %ecx /* Save ecx */ + mov UC_FLAGS(%edx), %eax /* eax = ucp->uc_flags */ + xor $[UCF_IGNFPU|UCF_IGNSIGM], %eax /* toggle both flags */ + jz 5f /* Both were set, skip getuctx */ + PIC_PROLOGUE push %edx - call _C_LABEL(getuctx) /* getuctx(ucp) */ + call PIC_PLT(_C_LABEL(getuctx)) /* getuctx(ucp) */ pop %edx /* clean up stack and restore edx */ - pop %ecx /* Restore ecx */ + PIC_EPILOGUE -1: +5: /* Save the context */ - mov 4(%esp), %edx /* edx = ucp */ - pop %eax /* retaddr */ - mov %eax, PC(%edx) /* Save real RTA in mcp struct */ + pop PC(%edx) /* Save real RTA in mcp struct */ mov %esp, SP(%edx) /* Save stack pointer (now pointing to ucp) */ - /* Save GP registers */ + /* Save GP registers (except EAX and EDX) */ mov %ebp, BP(%edx) /* Save EBP */ mov %esi, SI(%edx) /* Save ESI */ mov %edi, DI(%edx) /* Save EDI */ mov %ebx, BX(%edx) /* Save EBX */ mov %ecx, CX(%edx) /* Save ECX */ movl $MCF_MAGIC, MAGIC(%edx) /* Set magic value */ - push %eax /* Restore retaddr */ - xor %eax, %eax /* Return 0 */ - -2: - add $4, %esp /* Remove stale (setcontext) RTA */ - jmp *%ecx /* Restore return address */ + jmp *PC(%edx) /* Return return address */ /* int setcontext(const ucontext_t *ucp) @@ -115,52 +82,43 @@ ENTRY(setcontext) /* Check null pointer */ cmp $0, %edx /* edx == NULL? */ jnz 3f /* Not null, continue */ - movl $EFAULT, (_C_LABEL(errno)) + movl $EFAULT, %edx +0: push %edx /* preserve errno */ + PIC_PROLOGUE + call PIC_PLT(_C_LABEL(__errno)) + PIC_EPILOGUE + pop %edx + movl %edx, (%eax) xor %eax, %eax dec %eax /* return -1 */ ret 3: /* Check flags */ - push %ebx /* save ebx */ - lea MAGIC(%edx), %ebx /* ebx = &(ucp->mc_context.mc_magic) */ - mov (%ebx), %ecx /* ecx = ucp->mc_context.mc_magic */ - pop %ebx /* restore ebx */ - cmp $MCF_MAGIC, %ecx /* is the magic value set (is context valid)?*/ + cmpl $MCF_MAGIC, MAGIC(%edx) /* is the magic value set (is context valid)?*/ jz 4f /* is set, proceed */ - movl $EINVAL, (_C_LABEL(errno)) /* not set, return error code */ - xor %eax, %eax - dec %eax /* return -1 */ - ret + movl $EINVAL, %edx /* not set, return error code */ + jmp 0b -4: push %ebx /* save ebx */ - lea UC_FLAGS(%edx), %ebx /* ebx = &(ucp->uc_flags) */ - mov (%ebx), %ecx /* ecx = ucp->uc_flags */ - pop %ebx /* restore ebx */ - mov $UCF_IGNFPU, %eax - or $UCF_IGNSIGM, %eax - cmp %eax, %ecx /* Are UCF_IGNFPU and UCF_IGNSIGM flags set? */ - jz 1f /* Both are set, so don't bother restoring FPU +4: mov UC_FLAGS(%edx), %eax /* eax = ucp->uc_flags */ + xor $[UCF_IGNFPU|UCF_IGNSIGM], %eax /* toggle both flags */ + jz 5f /* Both are set, so don't bother restoring FPU * state and signal mask */ -0: push %ecx /* Save ecx */ + PIC_PROLOGUE push %edx - call _C_LABEL(setuctx) /* setuctx(ucp) */ + call PIC_PLT(_C_LABEL(setuctx)) /* setuctx(ucp) */ pop %edx /* Clean up stack and restore edx */ - pop %ecx /* Restore ecx */ + PIC_EPILOGUE -1: /* Restore the registers */ - mov 4(%esp), %edx /* edx = ucp */ +5: /* Restore the registers (except EAX and EDX) */ mov CX(%edx), %ecx /* Restore ECX */ mov BX(%edx), %ebx /* Restore EBX */ mov DI(%edx), %edi /* Restore EDI */ mov SI(%edx), %esi /* Restore ESI */ mov BP(%edx), %ebp /* Restore EBP */ mov SP(%edx), %esp /* Restore stack pointer */ - -2: - jmp *PC(%edx) /* Push RTA onto stack so we can return to it */ - + jmp *PC(%edx) /* Return to RTA */ /* void ctx_start((void *func)(int arg1, ..., argn), arg1, ..., argn, * ucontext_t *ucp) @@ -168,7 +126,11 @@ ENTRY(setcontext) * to ucp on the stack. By setting ESP to ESI, we effectively 'remove' all * arguments to `func' from the stack. Finally, a call to resumecontext * will start the next context in the linked list (or exit the program if - * there is no context). */ + * there is no context). + * + * Since PIC needs the EBX register, which is pushed on the stack by + * PIC_PROLOGUE, we need an extra of salsa here. + */ ENTRY(ctx_start) /* 0(esp) -> func * 4(esp) -> arg1 @@ -178,9 +140,10 @@ ENTRY(ctx_start) pop %eax /* eax = func */ call *%eax /* func(arg1, ..., argn) */ - mov %esi, %esp /* Clean up stack */ + PIC_PROLOGUE /* may push %ebx, but we do not care */ + mov %esi, %esp /* Clean up stack, keep %ebx = &GOT */ /* ucp is now at the top of the stack again */ - call _C_LABEL(resumecontext) /* resumecontext(ucp) */ + call PIC_PLT(_C_LABEL(resumecontext)) /* resumecontext(ucp) */ ret /* never reached */