[newlib-cygwin] Rearrange makecontext and add lots of comments

Corinna Vinschen corinna@sourceware.org
Sat Jul 18 10:35:00 GMT 2015


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=877b02be0823cf9227e33ef1a2e227680fa3b275

commit 877b02be0823cf9227e33ef1a2e227680fa3b275
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Sat Jul 18 12:35:23 2015 +0200

    Rearrange makecontext and add lots of comments
    
            * exceptions.cc (makecontext): Rearrange order of initialization and
            document at great length.
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 winsup/cygwin/ChangeLog     |  5 +++++
 winsup/cygwin/exceptions.cc | 49 ++++++++++++++++++++++++++++++++++-----------
 2 files changed, 42 insertions(+), 12 deletions(-)

diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index eb89f67..7b54e10 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,10 @@
 2015-07-17  Corinna Vinschen  <corinna@vinschen.de>
 
+	* exceptions.cc (makecontext): Rearrange order of initialization and
+	document at great length.
+
+2015-07-17  Corinna Vinschen  <corinna@vinschen.de>
+
 	* exceptions.cc (__unwind_single_frame): Define empty macro on i686.
 	(_cygtls::call_signal_handler): Try to make sure signal context makes
 	sense in case we're generating context here.  Add comment to explain.
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index d69dbf7..0025be6 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -2030,22 +2030,31 @@ makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
   uintptr_t *sp;
   va_list ap;
 
-  sp = (uintptr_t *) ((uintptr_t) ucp->uc_stack.ss_sp
-				+ ucp->uc_stack.ss_size);
+  /* Initialize sp to the top of the stack. */
+  sp = (uintptr_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
+  /* Subtract slots required for arguments and the pointer to uc_link. */
   sp -= (argc + 1);
+  /* Align. */
   sp = (uintptr_t *) ((uintptr_t) sp & ~0xf);
+  /* Subtract one slot for setting the return address. */
   --sp;
+  /* Set return address to the trampolin function __cont_link_context. */
   sp[0] = (uintptr_t) __cont_link_context;
-  sp[argc + 1] = (uintptr_t) ucp->uc_link;
-#ifdef __x86_64__
-  ucp->uc_mcontext.rip = (uint64_t) func;
-  ucp->uc_mcontext.rbx = (uint64_t) (sp + argc + 1);
-  ucp->uc_mcontext.rsp = (uint64_t) sp;
-#else
-  ucp->uc_mcontext.eip = (uint32_t) func;
-  ucp->uc_mcontext.ebx = (uint32_t) (sp + argc + 1);
-  ucp->uc_mcontext.esp = (uint32_t) sp;
-#endif
+  /* Fetch arguments and store them on the stack.
+
+     x86_64 only:
+
+     - Store first four args in the AMD64 ABI arg registers.
+
+     - Note that the stack is not short by these four register args.  The
+       reason is the shadow space for these regs required by the AMD64 ABI.
+
+     - The definition of makecontext only allows for "int" sized arguments to
+       func, 32 bit, likely for historical reasons.  However, the argument
+       slots on x86_64 are 64 bit anyway, so we can fetch and store the args
+       as 64 bit values, and func can request 64 bit args without violating
+       the definition.  This potentially allows porting 32 bit applications
+       providing pointer values to func without additional porting effort. */
   va_start (ap, argc);
   for (int i = 0; i < argc; ++i)
 #ifdef __x86_64__
@@ -2071,4 +2080,20 @@ makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
     sp[i + 1] = va_arg (ap, uintptr_t);
 #endif
   va_end (ap);
+  /* Store pointer to uc_link at the top of the stack. */
+  sp[argc + 1] = (uintptr_t) ucp->uc_link;
+  /* Last but not least set the register in the context at ucp so that a
+     subsequent setcontext or swapcontext picks up the right values:
+     - Set rip/eip to the target function.
+     - Set rsp/esp to the just computed stack pointer value.
+     - Set rbx/ebx to the address of the pointer to uc_link. */
+#ifdef __x86_64__
+  ucp->uc_mcontext.rip = (uint64_t) func;
+  ucp->uc_mcontext.rsp = (uint64_t) sp;
+  ucp->uc_mcontext.rbx = (uint64_t) (sp + argc + 1);
+#else
+  ucp->uc_mcontext.eip = (uint32_t) func;
+  ucp->uc_mcontext.esp = (uint32_t) sp;
+  ucp->uc_mcontext.ebx = (uint32_t) (sp + argc + 1);
+#endif
 }



More information about the Cygwin-cvs mailing list