summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2015-07-18 12:35:23 +0200
committerCorinna Vinschen <corinna@vinschen.de>2015-07-18 12:35:23 +0200
commit877b02be0823cf9227e33ef1a2e227680fa3b275 (patch)
tree6c7b124037553b9d8f698a8802cec44e9a1e3952 /winsup/cygwin
parentb2df1577c7b62d9f6f9c06f41037e9bd09f2174d (diff)
downloadcygnal-877b02be0823cf9227e33ef1a2e227680fa3b275.tar.gz
cygnal-877b02be0823cf9227e33ef1a2e227680fa3b275.tar.bz2
cygnal-877b02be0823cf9227e33ef1a2e227680fa3b275.zip
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>
Diffstat (limited to 'winsup/cygwin')
-rw-r--r--winsup/cygwin/ChangeLog5
-rw-r--r--winsup/cygwin/exceptions.cc49
2 files changed, 42 insertions, 12 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index eb89f6745..7b54e10d0 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 d69dbf799..0025be6b1 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
}