diff options
author | Natanael Copa <ncopa@alpinelinux.org> | 2012-10-29 14:39:41 +0000 |
---|---|---|
committer | Natanael Copa <ncopa@alpinelinux.org> | 2012-10-29 14:41:53 +0000 |
commit | 405da0cba760d6d2da58f4a97b40ca692345d28c (patch) | |
tree | bffbabe179eeba373da4fd8366d3408c339a2914 /main/libc0.9.32/0002-libc-sysdeps-add-get-make-set-swap-context-for-x86_6.patch | |
parent | 489f458711debccbba103b1e738b45d6043d0982 (diff) | |
download | aports-405da0cba760d6d2da58f4a97b40ca692345d28c.tar.bz2 aports-405da0cba760d6d2da58f4a97b40ca692345d28c.tar.xz |
main/libc0.9.32: add ucontext support
fixes #1450
Diffstat (limited to 'main/libc0.9.32/0002-libc-sysdeps-add-get-make-set-swap-context-for-x86_6.patch')
-rw-r--r-- | main/libc0.9.32/0002-libc-sysdeps-add-get-make-set-swap-context-for-x86_6.patch | 633 |
1 files changed, 633 insertions, 0 deletions
diff --git a/main/libc0.9.32/0002-libc-sysdeps-add-get-make-set-swap-context-for-x86_6.patch b/main/libc0.9.32/0002-libc-sysdeps-add-get-make-set-swap-context-for-x86_6.patch new file mode 100644 index 0000000000..ded1b2e893 --- /dev/null +++ b/main/libc0.9.32/0002-libc-sysdeps-add-get-make-set-swap-context-for-x86_6.patch @@ -0,0 +1,633 @@ +From f231ba278e7820f5b73cde16f17f227118d9bafc Mon Sep 17 00:00:00 2001 +From: Natanael Copa <ncopa@alpinelinux.org> +Date: Mon, 29 Oct 2012 14:33:26 +0000 +Subject: [PATCH 2/2] libc/sysdeps: add {get,make,set,swap}context for x86_64 + +--- + libc/sysdeps/linux/x86_64/Makefile.arch | 39 +++++++++ + libc/sysdeps/linux/x86_64/__start_context.S | 49 +++++++++++ + libc/sysdeps/linux/x86_64/getcontext.S | 88 ++++++++++++++++++++ + libc/sysdeps/linux/x86_64/makecontext.c | 121 ++++++++++++++++++++++++++++ + libc/sysdeps/linux/x86_64/setcontext.S | 103 +++++++++++++++++++++++ + libc/sysdeps/linux/x86_64/swapcontext.S | 121 ++++++++++++++++++++++++++++ + libc/sysdeps/linux/x86_64/ucontext_i.sym | 37 +++++++++ + 7 files changed, 558 insertions(+) + create mode 100644 libc/sysdeps/linux/x86_64/__start_context.S + create mode 100644 libc/sysdeps/linux/x86_64/getcontext.S + create mode 100644 libc/sysdeps/linux/x86_64/makecontext.c + create mode 100644 libc/sysdeps/linux/x86_64/setcontext.S + create mode 100644 libc/sysdeps/linux/x86_64/swapcontext.S + create mode 100644 libc/sysdeps/linux/x86_64/ucontext_i.sym + +diff --git a/libc/sysdeps/linux/x86_64/Makefile.arch b/libc/sysdeps/linux/x86_64/Makefile.arch +index 3243d86..bcf8096 100644 +--- a/libc/sysdeps/linux/x86_64/Makefile.arch ++++ b/libc/sysdeps/linux/x86_64/Makefile.arch +@@ -10,6 +10,9 @@ CSRC := brk.c __syscall_error.c sigaction.c mmap.c + SSRC := \ + __longjmp.S setjmp.S syscall.S bsd-setjmp.S bsd-_setjmp.S + ++LIBC_ARCH_DIR := $(top_srcdir)/libc/sysdeps/linux/$(TARGET_ARCH) ++LIBC_ARCH_OUT := $(top_builddir)/libc/sysdeps/linux/$(TARGET_ARCH) ++ + ifneq ($(UCLIBC_HAS_THREADS_NATIVE),y) + SSRC += vfork.S clone.S + endif +@@ -20,3 +23,39 @@ ifeq ($(UCLIBC_HAS_TLS),y) + SSRC += sched_getcpu.S + endif + endif ++ ++ifeq ($(UCLIBC_SUSV4_LEGACY),y) ++CSRC += makecontext.c ++ ++SSRC += setcontext.S getcontext.S swapcontext.S __start_context.S ++ ++ASFLAGS-setcontext.S := -D_LIBC_REENTRANT ++ASFLAGS-getcontext.S := -D_LIBC_REENTRANT ++ASFLAGS-swapcontext.S := -D_LIBC_REENTRANT ++ ++ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) ++#Needed to use the correct SYSCALL_ERROR_HANDLER ++ASFLAGS-setcontext.S += -DUSE___THREAD ++ASFLAGS-getcontext.S += -DUSE___THREAD ++ASFLAGS-swapcontext.S += -DUSE___THREAD ++endif ++ ++pregen-headers-$(UCLIBC_SUSV4_LEGACY) += $(LIBC_ARCH_OUT)/ucontext_i.h ++ ++headers_clean-y += libc_arch_headers_clean ++ ++CFLAGS-ucontext_i.c = -S ++ ++$(LIBC_ARCH_OUT)/ucontext_i.c: $(LIBC_ARCH_DIR)/ucontext_i.sym ++ $(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ ++ ++$(LIBC_ARCH_OUT)/ucontext_i.s: $(LIBC_ARCH_OUT)/ucontext_i.c ++ $(compile.c) ++ ++$(LIBC_ARCH_OUT)/ucontext_i.h: $(LIBC_ARCH_OUT)/ucontext_i.s ++ $(do_sed) -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*$\/#define \1 \2/p" $< > $@ ++ ++libc_arch_headers_clean: ++ $(do_rm) $(addprefix $(LIBC_ARCH_OUT)/ucontext_i., c h s) ++endif ++ +diff --git a/libc/sysdeps/linux/x86_64/__start_context.S b/libc/sysdeps/linux/x86_64/__start_context.S +new file mode 100644 +index 0000000..9f2ee23 +--- /dev/null ++++ b/libc/sysdeps/linux/x86_64/__start_context.S +@@ -0,0 +1,49 @@ ++/* Copyright (C) 2002-2012 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Andreas Jaeger <aj@suse.de>, 2002. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <sysdep.h> ++ ++/* This is the helper code which gets called if a function which is ++ registered with 'makecontext' returns. In this case we have to ++ install the context listed in the uc_link element of the context ++ 'makecontext' manipulated at the time of the 'makecontext' call. ++ If the pointer is NULL the process must terminate. */ ++ ++ ++ENTRY(__start_context) ++ /* This removes the parameters passed to the function given to ++ 'makecontext' from the stack. RBX contains the address ++ on the stack pointer for the next context. */ ++ movq %rbx, %rsp ++ ++ popq %rdi /* This is the next context. */ ++ cfi_adjust_cfa_offset(-8) ++ testq %rdi, %rdi ++ je 2f /* If it is zero exit. */ ++ ++ call JUMPTARGET(__setcontext) ++ /* If this returns (which can happen if the syscall fails) we'll ++ exit the program with the return error value (-1). */ ++ movq %rax,%rdi ++ ++2: ++ call HIDDEN_JUMPTARGET(exit) ++ /* The 'exit' call should never return. In case it does cause ++ the process to terminate. */ ++ hlt ++END(__start_context) +diff --git a/libc/sysdeps/linux/x86_64/getcontext.S b/libc/sysdeps/linux/x86_64/getcontext.S +new file mode 100644 +index 0000000..dcebc4f +--- /dev/null ++++ b/libc/sysdeps/linux/x86_64/getcontext.S +@@ -0,0 +1,88 @@ ++/* Save current context. ++ Copyright (C) 2002-2012 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Andreas Jaeger <aj@suse.de>, 2002. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <sysdep.h> ++ ++#include "ucontext_i.h" ++ ++/* int __getcontext (ucontext_t *ucp) ++ ++ Saves the machine context in UCP such that when it is activated, ++ it appears as if __getcontext() returned again. ++ ++ This implementation is intended to be used for *synchronous* context ++ switches only. Therefore, it does not have to save anything ++ other than the PRESERVED state. */ ++ ++ ++ENTRY(__getcontext) ++ /* Save the preserved registers, the registers used for passing ++ args, and the return address. */ ++ movq %rbx, oRBX(%rdi) ++ movq %rbp, oRBP(%rdi) ++ movq %r12, oR12(%rdi) ++ movq %r13, oR13(%rdi) ++ movq %r14, oR14(%rdi) ++ movq %r15, oR15(%rdi) ++ ++ movq %rdi, oRDI(%rdi) ++ movq %rsi, oRSI(%rdi) ++ movq %rdx, oRDX(%rdi) ++ movq %rcx, oRCX(%rdi) ++ movq %r8, oR8(%rdi) ++ movq %r9, oR9(%rdi) ++ ++ movq (%rsp), %rcx ++ movq %rcx, oRIP(%rdi) ++ leaq 8(%rsp), %rcx /* Exclude the return address. */ ++ movq %rcx, oRSP(%rdi) ++ ++ /* We have separate floating-point register content memory on the ++ stack. We use the __fpregs_mem block in the context. Set the ++ links up correctly. */ ++ ++ leaq oFPREGSMEM(%rdi), %rcx ++ movq %rcx, oFPREGS(%rdi) ++ /* Save the floating-point environment. */ ++ fnstenv (%rcx) ++ fldenv (%rcx) ++ stmxcsr oMXCSR(%rdi) ++ ++ /* Save the current signal mask with ++ rt_sigprocmask (SIG_BLOCK, NULL, set,_NSIG/8). */ ++ leaq oSIGMASK(%rdi), %rdx ++ xorl %esi,%esi ++#if SIG_BLOCK == 0 ++ xorl %edi, %edi ++#else ++ movl $SIG_BLOCK, %edi ++#endif ++ movl $_NSIG8,%r10d ++ movl $__NR_rt_sigprocmask, %eax ++ syscall ++ cmpq $-4095, %rax /* Check %rax for error. */ ++ jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */ ++ ++ /* All done, return 0 for success. */ ++ xorl %eax, %eax ++L(pseudo_end): ++ ret ++PSEUDO_END(__getcontext) ++ ++weak_alias (__getcontext, getcontext) +diff --git a/libc/sysdeps/linux/x86_64/makecontext.c b/libc/sysdeps/linux/x86_64/makecontext.c +new file mode 100644 +index 0000000..5473031 +--- /dev/null ++++ b/libc/sysdeps/linux/x86_64/makecontext.c +@@ -0,0 +1,121 @@ ++/* Create new context. ++ Copyright (C) 2002, 2004, 2005, 2008 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Andreas Jaeger <aj@suse.de>, 2002. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <sysdep.h> ++#include <stdarg.h> ++#include <stdint.h> ++#include <ucontext.h> ++ ++#include "ucontext_i.h" ++ ++/* This implementation can handle any ARGC value but only ++ normal integer parameters. ++ makecontext sets up a stack and the registers for the ++ user context. The stack looks like this: ++ +-----------------------+ ++ | next context | ++ +-----------------------+ ++ | parameter 7-n | ++ +-----------------------+ ++ | trampoline address | ++ %rsp -> +-----------------------+ ++ ++ The registers are set up like this: ++ %rdi,%rsi,%rdx,%rcx,%r8,%r9: parameter 1 to 6 ++ %rbx : address of next context ++ %rsp : stack pointer. ++*/ ++ ++/* XXX: This implementation currently only handles integer arguments. ++ To handle long int and pointer arguments the va_arg arguments needs ++ to be changed to long and also the stdlib/tst-setcontext.c file needs ++ to be changed to pass long arguments to makecontext. */ ++ ++ ++void ++__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...) ++{ ++ extern void __start_context (void); ++ greg_t *sp; ++ unsigned int idx_uc_link; ++ va_list ap; ++ int i; ++ ++ /* Generate room on stack for parameter if needed and uc_link. */ ++ sp = (greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp ++ + ucp->uc_stack.ss_size); ++ sp -= (argc > 6 ? argc - 6 : 0) + 1; ++ /* Align stack and make space for trampoline address. */ ++ sp = (greg_t *) ((((uintptr_t) sp) & -16L) - 8); ++ ++ idx_uc_link = (argc > 6 ? argc - 6 : 0) + 1; ++ ++ /* Setup context ucp. */ ++ /* Address to jump to. */ ++ ucp->uc_mcontext.gregs[REG_RIP] = (uintptr_t) func; ++ /* Setup rbx.*/ ++ ucp->uc_mcontext.gregs[REG_RBX] = (uintptr_t) &sp[idx_uc_link]; ++ ucp->uc_mcontext.gregs[REG_RSP] = (uintptr_t) sp; ++ ++ /* Setup stack. */ ++ sp[0] = (uintptr_t) &__start_context; ++ sp[idx_uc_link] = (uintptr_t) ucp->uc_link; ++ ++ va_start (ap, argc); ++ /* Handle arguments. ++ ++ The standard says the parameters must all be int values. This is ++ an historic accident and would be done differently today. For ++ x86-64 all integer values are passed as 64-bit values and ++ therefore extending the API to copy 64-bit values instead of ++ 32-bit ints makes sense. It does not break existing ++ functionality and it does not violate the standard which says ++ that passing non-int values means undefined behavior. */ ++ for (i = 0; i < argc; ++i) ++ switch (i) ++ { ++ case 0: ++ ucp->uc_mcontext.gregs[REG_RDI] = va_arg (ap, greg_t); ++ break; ++ case 1: ++ ucp->uc_mcontext.gregs[REG_RSI] = va_arg (ap, greg_t); ++ break; ++ case 2: ++ ucp->uc_mcontext.gregs[REG_RDX] = va_arg (ap, greg_t); ++ break; ++ case 3: ++ ucp->uc_mcontext.gregs[REG_RCX] = va_arg (ap, greg_t); ++ break; ++ case 4: ++ ucp->uc_mcontext.gregs[REG_R8] = va_arg (ap, greg_t); ++ break; ++ case 5: ++ ucp->uc_mcontext.gregs[REG_R9] = va_arg (ap, greg_t); ++ break; ++ default: ++ /* Put value on stack. */ ++ sp[i - 5] = va_arg (ap, greg_t); ++ break; ++ } ++ va_end (ap); ++ ++} ++ ++ ++weak_alias (__makecontext, makecontext) +diff --git a/libc/sysdeps/linux/x86_64/setcontext.S b/libc/sysdeps/linux/x86_64/setcontext.S +new file mode 100644 +index 0000000..561ab9f +--- /dev/null ++++ b/libc/sysdeps/linux/x86_64/setcontext.S +@@ -0,0 +1,103 @@ ++/* Install given context. ++ Copyright (C) 2002-2012 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Andreas Jaeger <aj@suse.de>, 2002. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <sysdep.h> ++ ++#include "ucontext_i.h" ++ ++ ++/* int __setcontext (const ucontext_t *ucp) ++ ++ Restores the machine context in UCP and thereby resumes execution ++ in that context. ++ ++ This implementation is intended to be used for *synchronous* context ++ switches only. Therefore, it does not have to restore anything ++ other than the PRESERVED state. */ ++ ++ENTRY(__setcontext) ++ /* Save argument since syscall will destroy it. */ ++ pushq %rdi ++ cfi_adjust_cfa_offset(8) ++ ++ /* Set the signal mask with ++ rt_sigprocmask (SIG_SETMASK, mask, NULL, _NSIG/8). */ ++ leaq oSIGMASK(%rdi), %rsi ++ xorl %edx, %edx ++ movl $SIG_SETMASK, %edi ++ movl $_NSIG8,%r10d ++ movl $__NR_rt_sigprocmask, %eax ++ syscall ++ popq %rdi /* Reload %rdi, adjust stack. */ ++ cfi_adjust_cfa_offset(-8) ++ cmpq $-4095, %rax /* Check %rax for error. */ ++ jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */ ++ ++ /* Restore the floating-point context. Not the registers, only the ++ rest. */ ++ movq oFPREGS(%rdi), %rcx ++ fldenv (%rcx) ++ ldmxcsr oMXCSR(%rdi) ++ ++ ++ /* Load the new stack pointer, the preserved registers and ++ registers used for passing args. */ ++ cfi_def_cfa(%rdi, 0) ++ cfi_offset(%rbx,oRBX) ++ cfi_offset(%rbp,oRBP) ++ cfi_offset(%r12,oR12) ++ cfi_offset(%r13,oR13) ++ cfi_offset(%r14,oR14) ++ cfi_offset(%r15,oR15) ++ cfi_offset(%rsp,oRSP) ++ cfi_offset(%rip,oRIP) ++ ++ movq oRSP(%rdi), %rsp ++ movq oRBX(%rdi), %rbx ++ movq oRBP(%rdi), %rbp ++ movq oR12(%rdi), %r12 ++ movq oR13(%rdi), %r13 ++ movq oR14(%rdi), %r14 ++ movq oR15(%rdi), %r15 ++ ++ /* The following ret should return to the address set with ++ getcontext. Therefore push the address on the stack. */ ++ movq oRIP(%rdi), %rcx ++ pushq %rcx ++ ++ movq oRSI(%rdi), %rsi ++ movq oRDX(%rdi), %rdx ++ movq oRCX(%rdi), %rcx ++ movq oR8(%rdi), %r8 ++ movq oR9(%rdi), %r9 ++ ++ /* Setup finally %rdi. */ ++ movq oRDI(%rdi), %rdi ++ ++ /* End FDE here, we fall into another context. */ ++ cfi_endproc ++ cfi_startproc ++ ++ /* Clear rax to indicate success. */ ++ xorl %eax, %eax ++L(pseudo_end): ++ ret ++PSEUDO_END(__setcontext) ++ ++weak_alias (__setcontext, setcontext) +diff --git a/libc/sysdeps/linux/x86_64/swapcontext.S b/libc/sysdeps/linux/x86_64/swapcontext.S +new file mode 100644 +index 0000000..6d2ebb8 +--- /dev/null ++++ b/libc/sysdeps/linux/x86_64/swapcontext.S +@@ -0,0 +1,121 @@ ++/* Save current context and install the given one. ++ Copyright (C) 2002-2012 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Andreas Jaeger <aj@suse.de>, 2002. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <sysdep.h> ++ ++#include "ucontext_i.h" ++ ++ ++/* int __swapcontext (ucontext_t *oucp, const ucontext_t *ucp); ++ ++ Saves the machine context in oucp such that when it is activated, ++ it appears as if __swapcontextt() returned again, restores the ++ machine context in ucp and thereby resumes execution in that ++ context. ++ ++ This implementation is intended to be used for *synchronous* context ++ switches only. Therefore, it does not have to save anything ++ other than the PRESERVED state. */ ++ ++ENTRY(__swapcontext) ++ /* Save the preserved registers, the registers used for passing args, ++ and the return address. */ ++ movq %rbx, oRBX(%rdi) ++ movq %rbp, oRBP(%rdi) ++ movq %r12, oR12(%rdi) ++ movq %r13, oR13(%rdi) ++ movq %r14, oR14(%rdi) ++ movq %r15, oR15(%rdi) ++ ++ movq %rdi, oRDI(%rdi) ++ movq %rsi, oRSI(%rdi) ++ movq %rdx, oRDX(%rdi) ++ movq %rcx, oRCX(%rdi) ++ movq %r8, oR8(%rdi) ++ movq %r9, oR9(%rdi) ++ ++ movq (%rsp), %rcx ++ movq %rcx, oRIP(%rdi) ++ leaq 8(%rsp), %rcx /* Exclude the return address. */ ++ movq %rcx, oRSP(%rdi) ++ ++ /* We have separate floating-point register content memory on the ++ stack. We use the __fpregs_mem block in the context. Set the ++ links up correctly. */ ++ leaq oFPREGSMEM(%rdi), %rcx ++ movq %rcx, oFPREGS(%rdi) ++ /* Save the floating-point environment. */ ++ fnstenv (%rcx) ++ stmxcsr oMXCSR(%rdi) ++ ++ ++ /* The syscall destroys some registers, save them. */ ++ movq %rsi, %r12 ++ ++ /* Save the current signal mask and install the new one with ++ rt_sigprocmask (SIG_BLOCK, newset, oldset,_NSIG/8). */ ++ leaq oSIGMASK(%rdi), %rdx ++ leaq oSIGMASK(%rsi), %rsi ++ movl $SIG_SETMASK, %edi ++ movl $_NSIG8,%r10d ++ movl $__NR_rt_sigprocmask, %eax ++ syscall ++ cmpq $-4095, %rax /* Check %rax for error. */ ++ jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */ ++ ++ /* Restore destroyed registers. */ ++ movq %r12, %rsi ++ ++ /* Restore the floating-point context. Not the registers, only the ++ rest. */ ++ movq oFPREGS(%rsi), %rcx ++ fldenv (%rcx) ++ ldmxcsr oMXCSR(%rsi) ++ ++ /* Load the new stack pointer and the preserved registers. */ ++ movq oRSP(%rsi), %rsp ++ movq oRBX(%rsi), %rbx ++ movq oRBP(%rsi), %rbp ++ movq oR12(%rsi), %r12 ++ movq oR13(%rsi), %r13 ++ movq oR14(%rsi), %r14 ++ movq oR15(%rsi), %r15 ++ ++ /* The following ret should return to the address set with ++ getcontext. Therefore push the address on the stack. */ ++ movq oRIP(%rsi), %rcx ++ pushq %rcx ++ ++ /* Setup registers used for passing args. */ ++ movq oRDI(%rsi), %rdi ++ movq oRDX(%rsi), %rdx ++ movq oRCX(%rsi), %rcx ++ movq oR8(%rsi), %r8 ++ movq oR9(%rsi), %r9 ++ ++ /* Setup finally %rsi. */ ++ movq oRSI(%rsi), %rsi ++ ++ /* Clear rax to indicate success. */ ++ xorl %eax, %eax ++L(pseudo_end): ++ ret ++PSEUDO_END(__swapcontext) ++ ++weak_alias (__swapcontext, swapcontext) +diff --git a/libc/sysdeps/linux/x86_64/ucontext_i.sym b/libc/sysdeps/linux/x86_64/ucontext_i.sym +new file mode 100644 +index 0000000..af3e0e5 +--- /dev/null ++++ b/libc/sysdeps/linux/x86_64/ucontext_i.sym +@@ -0,0 +1,37 @@ ++#include <stddef.h> ++#include <signal.h> ++#include <sys/ucontext.h> ++ ++-- ++ ++SIG_BLOCK ++SIG_SETMASK ++ ++_NSIG8 (_NSIG / 8) ++ ++#define ucontext(member) offsetof (ucontext_t, member) ++#define mcontext(member) ucontext (uc_mcontext.member) ++#define mreg(reg) mcontext (gregs[REG_##reg]) ++ ++oRBP mreg (RBP) ++oRSP mreg (RSP) ++oRBX mreg (RBX) ++oR8 mreg (R8) ++oR9 mreg (R9) ++oR10 mreg (R10) ++oR11 mreg (R11) ++oR12 mreg (R12) ++oR13 mreg (R13) ++oR14 mreg (R14) ++oR15 mreg (R15) ++oRDI mreg (RDI) ++oRSI mreg (RSI) ++oRDX mreg (RDX) ++oRAX mreg (RAX) ++oRCX mreg (RCX) ++oRIP mreg (RIP) ++oEFL mreg (EFL) ++oFPREGS mcontext (fpregs) ++oSIGMASK ucontext (uc_sigmask) ++oFPREGSMEM ucontext (__fpregs_mem) ++oMXCSR ucontext (__fpregs_mem.mxcsr) +-- +1.8.0 + |