mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-28 12:05:47 +08:00
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>
This commit is contained in:
parent
b2df1577c7
commit
877b02be08
@ -1,3 +1,8 @@
|
|||||||
|
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>
|
2015-07-17 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* exceptions.cc (__unwind_single_frame): Define empty macro on i686.
|
* exceptions.cc (__unwind_single_frame): Define empty macro on i686.
|
||||||
|
@ -2030,22 +2030,31 @@ makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
|
|||||||
uintptr_t *sp;
|
uintptr_t *sp;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
sp = (uintptr_t *) ((uintptr_t) ucp->uc_stack.ss_sp
|
/* Initialize sp to the top of the stack. */
|
||||||
+ ucp->uc_stack.ss_size);
|
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);
|
sp -= (argc + 1);
|
||||||
|
/* Align. */
|
||||||
sp = (uintptr_t *) ((uintptr_t) sp & ~0xf);
|
sp = (uintptr_t *) ((uintptr_t) sp & ~0xf);
|
||||||
|
/* Subtract one slot for setting the return address. */
|
||||||
--sp;
|
--sp;
|
||||||
|
/* Set return address to the trampolin function __cont_link_context. */
|
||||||
sp[0] = (uintptr_t) __cont_link_context;
|
sp[0] = (uintptr_t) __cont_link_context;
|
||||||
sp[argc + 1] = (uintptr_t) ucp->uc_link;
|
/* Fetch arguments and store them on the stack.
|
||||||
#ifdef __x86_64__
|
|
||||||
ucp->uc_mcontext.rip = (uint64_t) func;
|
x86_64 only:
|
||||||
ucp->uc_mcontext.rbx = (uint64_t) (sp + argc + 1);
|
|
||||||
ucp->uc_mcontext.rsp = (uint64_t) sp;
|
- Store first four args in the AMD64 ABI arg registers.
|
||||||
#else
|
|
||||||
ucp->uc_mcontext.eip = (uint32_t) func;
|
- Note that the stack is not short by these four register args. The
|
||||||
ucp->uc_mcontext.ebx = (uint32_t) (sp + argc + 1);
|
reason is the shadow space for these regs required by the AMD64 ABI.
|
||||||
ucp->uc_mcontext.esp = (uint32_t) sp;
|
|
||||||
#endif
|
- 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);
|
va_start (ap, argc);
|
||||||
for (int i = 0; i < argc; ++i)
|
for (int i = 0; i < argc; ++i)
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
@ -2071,4 +2080,20 @@ makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
|
|||||||
sp[i + 1] = va_arg (ap, uintptr_t);
|
sp[i + 1] = va_arg (ap, uintptr_t);
|
||||||
#endif
|
#endif
|
||||||
va_end (ap);
|
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
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user