Fix Yet Another 16 byte stack alignment bug. Thankfully, this one is
solved by a simple 'make world'. The signalcontext function was going to the trouble of generating an even 16 byte alignment, but in fact it needed to be odd aligned to simulate the 8-byte return address having been pushed by the caller. This fixes yet another group of crashes in applications using libpthread. And yet again, it was my fault all along. While here, rename the duplicate internal ctx_wrapper() functions to makectx_wrapper() and sigctx_wrapper() so that traces aren't ambiguous.
This commit is contained in:
parent
220ee8be37
commit
3726033348
@ -36,7 +36,7 @@ typedef void (*func_t)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,
|
||||
uint64_t);
|
||||
|
||||
/* Prototypes */
|
||||
static void ctx_wrapper(ucontext_t *ucp, func_t func, uint64_t *args);
|
||||
static void makectx_wrapper(ucontext_t *ucp, func_t func, uint64_t *args);
|
||||
|
||||
__weak_reference(__makecontext, makecontext);
|
||||
|
||||
@ -91,11 +91,11 @@ __makecontext(ucontext_t *ucp, void (*start)(void), int argc, ...)
|
||||
ucp->uc_mcontext.mc_rbp = (register_t)sp;
|
||||
ucp->uc_mcontext.mc_rbx = (register_t)sp;
|
||||
ucp->uc_mcontext.mc_rsp = (register_t)sp;
|
||||
ucp->uc_mcontext.mc_rip = (register_t)ctx_wrapper;
|
||||
ucp->uc_mcontext.mc_rip = (register_t)makectx_wrapper;
|
||||
}
|
||||
|
||||
static void
|
||||
ctx_wrapper(ucontext_t *ucp, func_t func, uint64_t *args)
|
||||
makectx_wrapper(ucontext_t *ucp, func_t func, uint64_t *args)
|
||||
{
|
||||
(*func)(args[0], args[1], args[2], args[3], args[4], args[5]);
|
||||
if (ucp->uc_link == NULL)
|
||||
|
@ -36,7 +36,7 @@ __FBSDID("$FreeBSD$");
|
||||
typedef void (*handler_t)(uint64_t, uint64_t, uint64_t);
|
||||
|
||||
/* Prototypes */
|
||||
static void ctx_wrapper(ucontext_t *ucp, handler_t func, uint64_t *args);
|
||||
static void sigctx_wrapper(ucontext_t *ucp, handler_t func, uint64_t *args);
|
||||
|
||||
__weak_reference(__signalcontext, signalcontext);
|
||||
|
||||
@ -54,8 +54,9 @@ __signalcontext(ucontext_t *ucp, int sig, __sighandler_t *func)
|
||||
|
||||
/*
|
||||
* Build a signal frame and copy the arguments of signal handler
|
||||
* 'func' onto the stack. We only need 3 arguments, but we
|
||||
* create room for 4 so that we are 16-byte aligned.
|
||||
* 'func' onto the stack and do the funky stack alignment.
|
||||
* This means that we need an 8-byte-odd alignment since the ABI expects
|
||||
* the return address to be pushed, thus breaking the 16 byte alignment.
|
||||
*/
|
||||
sp = (ucp->uc_mcontext.mc_rsp - sizeof(ucontext_t)) & ~15UL;
|
||||
sig_uc = (ucontext_t *)sp;
|
||||
@ -64,12 +65,11 @@ __signalcontext(ucontext_t *ucp, int sig, __sighandler_t *func)
|
||||
sig_si = (siginfo_t *)sp;
|
||||
bzero(sig_si, sizeof(*sig_si));
|
||||
sig_si->si_signo = sig;
|
||||
sp -= 4 * sizeof(uint64_t);
|
||||
sp -= 3 * sizeof(uint64_t);
|
||||
args = (uint64_t *)sp;
|
||||
args[0] = sig;
|
||||
args[1] = (intptr_t)sig_si;
|
||||
args[2] = (intptr_t)sig_uc;
|
||||
args[3] = 0;
|
||||
sp -= 16;
|
||||
|
||||
/*
|
||||
@ -86,12 +86,12 @@ __signalcontext(ucontext_t *ucp, int sig, __sighandler_t *func)
|
||||
ucp->uc_mcontext.mc_rbp = (register_t)sp;
|
||||
ucp->uc_mcontext.mc_rbx = (register_t)sp;
|
||||
ucp->uc_mcontext.mc_rsp = (register_t)sp;
|
||||
ucp->uc_mcontext.mc_rip = (register_t)ctx_wrapper;
|
||||
ucp->uc_mcontext.mc_rip = (register_t)sigctx_wrapper;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
ctx_wrapper(ucontext_t *ucp, handler_t func, uint64_t *args)
|
||||
sigctx_wrapper(ucontext_t *ucp, handler_t func, uint64_t *args)
|
||||
{
|
||||
|
||||
(*func)(args[0], args[1], args[2]);
|
||||
|
Loading…
Reference in New Issue
Block a user