libc: make MINIX assembly code position-independent
While here, simplify ucontext.S . makes libc link without the messy DT_TEXTREL warning. Change-Id: I4656d9068eab5ed2fa1e391242883d5dd9d93644
This commit is contained in:
parent
8e87bd84b4
commit
3a0aa55040
2 changed files with 47 additions and 78 deletions
|
@ -6,4 +6,10 @@
|
||||||
IMPORT(_sigreturn)
|
IMPORT(_sigreturn)
|
||||||
ENTRY(__sigreturn)
|
ENTRY(__sigreturn)
|
||||||
addl $16, %esp
|
addl $16, %esp
|
||||||
|
#ifndef PIC
|
||||||
jmp _C_LABEL(_sigreturn)
|
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 */
|
||||||
|
|
|
@ -1,26 +1,11 @@
|
||||||
#include <machine/asm.h>
|
#include <machine/asm.h>
|
||||||
#include <ucontextoffsets.h>
|
#include <ucontextoffsets.h>
|
||||||
|
|
||||||
#ifdef __ACK__
|
|
||||||
.text
|
|
||||||
begtext:
|
|
||||||
#ifdef __ACK__
|
|
||||||
.rom
|
|
||||||
#else
|
|
||||||
.data
|
|
||||||
#endif
|
|
||||||
begrom:
|
|
||||||
.data
|
|
||||||
begdata:
|
|
||||||
.bss
|
|
||||||
begbss:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
IMPORT(getuctx)
|
IMPORT(getuctx)
|
||||||
IMPORT(setuctx)
|
IMPORT(setuctx)
|
||||||
IMPORT(resumecontext)
|
IMPORT(resumecontext)
|
||||||
|
|
||||||
|
.globl _C_LABEL(__errno)
|
||||||
|
|
||||||
/* MCF_MAGIC value from <mcontext.h> */
|
/* MCF_MAGIC value from <mcontext.h> */
|
||||||
#define MCF_MAGIC 0xc0ffee
|
#define MCF_MAGIC 0xc0ffee
|
||||||
|
@ -43,59 +28,41 @@ ENTRY(getcontext)
|
||||||
* saving its signal mask, then we can skip the context switch to
|
* saving its signal mask, then we can skip the context switch to
|
||||||
* PM and kernel altogether and only save general-purpose registers. */
|
* 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 */
|
mov 4(%esp), %edx /* edx = ucp */
|
||||||
/* Check null pointer */
|
/* Check null pointer */
|
||||||
cmp $0, %edx /* edx == NULL? */
|
cmp $0, %edx /* edx == NULL? */
|
||||||
jne 3f /* Not null, continue */
|
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
|
xor %eax, %eax
|
||||||
dec %eax /* return -1 */
|
dec %eax /* return -1 */
|
||||||
ret
|
ret
|
||||||
|
|
||||||
3: /* Check flags */
|
3: /* Check flags */
|
||||||
push %ecx /* save ecx */
|
mov UC_FLAGS(%edx), %eax /* eax = ucp->uc_flags */
|
||||||
push %ebx /* save ebx */
|
xor $[UCF_IGNFPU|UCF_IGNSIGM], %eax /* toggle both flags */
|
||||||
lea UC_FLAGS(%edx), %ebx /* ebx = &(ucp->uc_flags) */
|
jz 5f /* Both were set, skip getuctx */
|
||||||
mov (%ebx), %ecx /* ecx = ucp->uc_flags */
|
PIC_PROLOGUE
|
||||||
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 */
|
|
||||||
push %edx
|
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 %edx /* clean up stack and restore edx */
|
||||||
pop %ecx /* Restore ecx */
|
PIC_EPILOGUE
|
||||||
|
|
||||||
1:
|
5:
|
||||||
/* Save the context */
|
/* Save the context */
|
||||||
mov 4(%esp), %edx /* edx = ucp */
|
pop PC(%edx) /* Save real RTA in mcp struct */
|
||||||
pop %eax /* retaddr */
|
|
||||||
mov %eax, PC(%edx) /* Save real RTA in mcp struct */
|
|
||||||
mov %esp, SP(%edx) /* Save stack pointer (now pointing to ucp) */
|
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 %ebp, BP(%edx) /* Save EBP */
|
||||||
mov %esi, SI(%edx) /* Save ESI */
|
mov %esi, SI(%edx) /* Save ESI */
|
||||||
mov %edi, DI(%edx) /* Save EDI */
|
mov %edi, DI(%edx) /* Save EDI */
|
||||||
mov %ebx, BX(%edx) /* Save EBX */
|
mov %ebx, BX(%edx) /* Save EBX */
|
||||||
mov %ecx, CX(%edx) /* Save ECX */
|
mov %ecx, CX(%edx) /* Save ECX */
|
||||||
movl $MCF_MAGIC, MAGIC(%edx) /* Set magic value */
|
movl $MCF_MAGIC, MAGIC(%edx) /* Set magic value */
|
||||||
push %eax /* Restore retaddr */
|
|
||||||
|
|
||||||
xor %eax, %eax /* Return 0 */
|
xor %eax, %eax /* Return 0 */
|
||||||
|
jmp *PC(%edx) /* Return return address */
|
||||||
2:
|
|
||||||
add $4, %esp /* Remove stale (setcontext) RTA */
|
|
||||||
jmp *%ecx /* Restore return address */
|
|
||||||
|
|
||||||
|
|
||||||
/* int setcontext(const ucontext_t *ucp)
|
/* int setcontext(const ucontext_t *ucp)
|
||||||
|
@ -115,52 +82,43 @@ ENTRY(setcontext)
|
||||||
/* Check null pointer */
|
/* Check null pointer */
|
||||||
cmp $0, %edx /* edx == NULL? */
|
cmp $0, %edx /* edx == NULL? */
|
||||||
jnz 3f /* Not null, continue */
|
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
|
xor %eax, %eax
|
||||||
dec %eax /* return -1 */
|
dec %eax /* return -1 */
|
||||||
ret
|
ret
|
||||||
|
|
||||||
3: /* Check flags */
|
3: /* Check flags */
|
||||||
push %ebx /* save ebx */
|
cmpl $MCF_MAGIC, MAGIC(%edx) /* is the magic value set (is context valid)?*/
|
||||||
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)?*/
|
|
||||||
jz 4f /* is set, proceed */
|
jz 4f /* is set, proceed */
|
||||||
movl $EINVAL, (_C_LABEL(errno)) /* not set, return error code */
|
movl $EINVAL, %edx /* not set, return error code */
|
||||||
xor %eax, %eax
|
jmp 0b
|
||||||
dec %eax /* return -1 */
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
4: push %ebx /* save ebx */
|
4: mov UC_FLAGS(%edx), %eax /* eax = ucp->uc_flags */
|
||||||
lea UC_FLAGS(%edx), %ebx /* ebx = &(ucp->uc_flags) */
|
xor $[UCF_IGNFPU|UCF_IGNSIGM], %eax /* toggle both flags */
|
||||||
mov (%ebx), %ecx /* ecx = ucp->uc_flags */
|
jz 5f /* Both are set, so don't bother restoring FPU
|
||||||
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
|
|
||||||
* state and signal mask */
|
* state and signal mask */
|
||||||
|
|
||||||
0: push %ecx /* Save ecx */
|
PIC_PROLOGUE
|
||||||
push %edx
|
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 %edx /* Clean up stack and restore edx */
|
||||||
pop %ecx /* Restore ecx */
|
PIC_EPILOGUE
|
||||||
|
|
||||||
1: /* Restore the registers */
|
5: /* Restore the registers (except EAX and EDX) */
|
||||||
mov 4(%esp), %edx /* edx = ucp */
|
|
||||||
mov CX(%edx), %ecx /* Restore ECX */
|
mov CX(%edx), %ecx /* Restore ECX */
|
||||||
mov BX(%edx), %ebx /* Restore EBX */
|
mov BX(%edx), %ebx /* Restore EBX */
|
||||||
mov DI(%edx), %edi /* Restore EDI */
|
mov DI(%edx), %edi /* Restore EDI */
|
||||||
mov SI(%edx), %esi /* Restore ESI */
|
mov SI(%edx), %esi /* Restore ESI */
|
||||||
mov BP(%edx), %ebp /* Restore EBP */
|
mov BP(%edx), %ebp /* Restore EBP */
|
||||||
mov SP(%edx), %esp /* Restore stack pointer */
|
mov SP(%edx), %esp /* Restore stack pointer */
|
||||||
|
jmp *PC(%edx) /* Return to RTA */
|
||||||
2:
|
|
||||||
jmp *PC(%edx) /* Push RTA onto stack so we can return to it */
|
|
||||||
|
|
||||||
|
|
||||||
/* void ctx_start((void *func)(int arg1, ..., argn), arg1, ..., argn,
|
/* void ctx_start((void *func)(int arg1, ..., argn), arg1, ..., argn,
|
||||||
* ucontext_t *ucp)
|
* ucontext_t *ucp)
|
||||||
|
@ -168,7 +126,11 @@ ENTRY(setcontext)
|
||||||
* to ucp on the stack. By setting ESP to ESI, we effectively 'remove' all
|
* 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
|
* 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
|
* 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)
|
ENTRY(ctx_start)
|
||||||
/* 0(esp) -> func
|
/* 0(esp) -> func
|
||||||
* 4(esp) -> arg1
|
* 4(esp) -> arg1
|
||||||
|
@ -178,9 +140,10 @@ ENTRY(ctx_start)
|
||||||
|
|
||||||
pop %eax /* eax = func */
|
pop %eax /* eax = func */
|
||||||
call *%eax /* func(arg1, ..., argn) */
|
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 */
|
/* 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 */
|
ret /* never reached */
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue