Reuse __unwind_single_frame where appropriate
* exceptions.cc (__unwind_single_frame): Move up in file to be accessible from other places. Move comment to getcontext. (stack_info::walk): Call __unwind_single_frame in 64 bit case. Fix preceeding comment. (myfault_altstack_handler): Call __unwind_single_frame. (getcontext): Give comment from __unwind_single_frame a new home. (swapcontext): Fix comment. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
parent
1020bb292a
commit
b3ccf998cc
|
@ -1,3 +1,13 @@
|
||||||
|
2015-07-17 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* exceptions.cc (__unwind_single_frame): Move up in file to be
|
||||||
|
accessible from other places. Move comment to getcontext.
|
||||||
|
(stack_info::walk): Call __unwind_single_frame in 64 bit case. Fix
|
||||||
|
preceeding comment.
|
||||||
|
(myfault_altstack_handler): Call __unwind_single_frame.
|
||||||
|
(getcontext): Give comment from __unwind_single_frame a new home.
|
||||||
|
(swapcontext): Fix comment.
|
||||||
|
|
||||||
2015-07-17 Corinna Vinschen <corinna@vinschen.de>
|
2015-07-17 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* common.din (getcontext): Export.
|
* common.din (getcontext): Export.
|
||||||
|
|
|
@ -280,17 +280,36 @@ stack_info::init (PUINT_PTR framep, bool wantargs, PCONTEXT ctx)
|
||||||
|
|
||||||
extern "C" void _cygwin_exit_return ();
|
extern "C" void _cygwin_exit_return ();
|
||||||
|
|
||||||
/* Walk the stack by looking at successive stored 'bp' frames.
|
#ifdef __x86_64__
|
||||||
|
static inline void
|
||||||
|
__unwind_single_frame (PCONTEXT ctx)
|
||||||
|
{
|
||||||
|
PRUNTIME_FUNCTION f;
|
||||||
|
ULONG64 imagebase;
|
||||||
|
UNWIND_HISTORY_TABLE hist;
|
||||||
|
DWORD64 establisher;
|
||||||
|
PVOID hdl;
|
||||||
|
|
||||||
|
f = RtlLookupFunctionEntry (ctx->Rip, &imagebase, &hist);
|
||||||
|
if (f)
|
||||||
|
RtlVirtualUnwind (0, imagebase, ctx->Rip, f, ctx, &hdl, &establisher,
|
||||||
|
NULL);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ctx->Rip = *(ULONG_PTR *) ctx->Rsp;
|
||||||
|
ctx->Rsp += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Walk the stack.
|
||||||
|
|
||||||
|
On 32 bit we're doing this by looking at successive stored 'ebp' frames.
|
||||||
This is not foolproof. */
|
This is not foolproof. */
|
||||||
int
|
int
|
||||||
stack_info::walk ()
|
stack_info::walk ()
|
||||||
{
|
{
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
PRUNTIME_FUNCTION f;
|
|
||||||
ULONG64 imagebase;
|
|
||||||
DWORD64 establisher;
|
|
||||||
PVOID hdl;
|
|
||||||
|
|
||||||
if (!c.Rip)
|
if (!c.Rip)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -306,15 +325,7 @@ stack_info::walk ()
|
||||||
sigstackptr--;
|
sigstackptr--;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
__unwind_single_frame (&c);
|
||||||
f = RtlLookupFunctionEntry (c.Rip, &imagebase, &hist);
|
|
||||||
if (f)
|
|
||||||
RtlVirtualUnwind (0, imagebase, c.Rip, f, &c, &hdl, &establisher, NULL);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
c.Rip = *(ULONG_PTR *) c.Rsp;
|
|
||||||
c.Rsp += 8;
|
|
||||||
}
|
|
||||||
if (needargs && c.Rip)
|
if (needargs && c.Rip)
|
||||||
{
|
{
|
||||||
PULONG_PTR p = (PULONG_PTR) c.Rsp;
|
PULONG_PTR p = (PULONG_PTR) c.Rsp;
|
||||||
|
@ -605,28 +616,13 @@ myfault_altstack_handler (EXCEPTION_POINTERS *exc)
|
||||||
|
|
||||||
if (me.andreas)
|
if (me.andreas)
|
||||||
{
|
{
|
||||||
PRUNTIME_FUNCTION f;
|
|
||||||
ULONG64 imagebase;
|
|
||||||
UNWIND_HISTORY_TABLE hist;
|
|
||||||
DWORD64 establisher;
|
|
||||||
PVOID hdl;
|
|
||||||
CONTEXT *c = exc->ContextRecord;
|
CONTEXT *c = exc->ContextRecord;
|
||||||
|
|
||||||
/* Unwind the stack manually and call RtlRestoreContext. This
|
/* Unwind the stack manually and call RtlRestoreContext. This
|
||||||
is necessary because RtlUnwindEx checks the stack for validity,
|
is necessary because RtlUnwindEx checks the stack for validity,
|
||||||
which, as outlined above, fails for the alternate stack. */
|
which, as outlined above, fails for the alternate stack. */
|
||||||
while (c->Rsp < me.andreas->frame)
|
while (c->Rsp < me.andreas->frame)
|
||||||
{
|
__unwind_single_frame (c);
|
||||||
f = RtlLookupFunctionEntry (c->Rip, &imagebase, &hist);
|
|
||||||
if (f)
|
|
||||||
RtlVirtualUnwind (0, imagebase, c->Rip, f, c, &hdl, &establisher,
|
|
||||||
NULL);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
c->Rip = *(ULONG_PTR *) c->Rsp;
|
|
||||||
c->Rsp += 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c->Rip = me.andreas->ret;
|
c->Rip = me.andreas->ret;
|
||||||
RtlRestoreContext (c, NULL);
|
RtlRestoreContext (c, NULL);
|
||||||
}
|
}
|
||||||
|
@ -1865,33 +1861,6 @@ _cygtls::signal_debugger (siginfo_t& si)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __x86_64__
|
|
||||||
static inline void
|
|
||||||
__unwind_single_frame (PCONTEXT ctx)
|
|
||||||
{
|
|
||||||
/* Amazing, but true: On 32 bit, RtlCaptureContext returns the context
|
|
||||||
matching the caller of getcontext, so all we have to do is call it.
|
|
||||||
On 64 bit, RtlCaptureContext returns the exact context of its own
|
|
||||||
caller, so we have to unwind virtually by a single frame to get the
|
|
||||||
context of the caller of getcontext. */
|
|
||||||
PRUNTIME_FUNCTION f;
|
|
||||||
ULONG64 imagebase;
|
|
||||||
UNWIND_HISTORY_TABLE hist;
|
|
||||||
DWORD64 establisher;
|
|
||||||
PVOID hdl;
|
|
||||||
|
|
||||||
f = RtlLookupFunctionEntry (ctx->Rip, &imagebase, &hist);
|
|
||||||
if (f)
|
|
||||||
RtlVirtualUnwind (0, imagebase, ctx->Rip, f, ctx, &hdl, &establisher,
|
|
||||||
NULL);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ctx->Rip = *(ULONG_PTR *) ctx->Rsp;
|
|
||||||
ctx->Rsp += 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern "C" int
|
extern "C" int
|
||||||
setcontext (const ucontext_t *ucp)
|
setcontext (const ucontext_t *ucp)
|
||||||
{
|
{
|
||||||
|
@ -1917,6 +1886,11 @@ getcontext (ucontext_t *ucp)
|
||||||
PCONTEXT ctx = (PCONTEXT) &ucp->uc_mcontext;
|
PCONTEXT ctx = (PCONTEXT) &ucp->uc_mcontext;
|
||||||
ctx->ContextFlags = CONTEXT_FULL;
|
ctx->ContextFlags = CONTEXT_FULL;
|
||||||
RtlCaptureContext (ctx);
|
RtlCaptureContext (ctx);
|
||||||
|
/* Amazing, but true: On 32 bit, RtlCaptureContext returns the context
|
||||||
|
matching the caller of getcontext, so all we have to do is call it.
|
||||||
|
On 64 bit, RtlCaptureContext returns the exact context of its own
|
||||||
|
caller, so we have to unwind virtually by a single frame to get the
|
||||||
|
context of the caller of getcontext. */
|
||||||
__unwind_single_frame (ctx);
|
__unwind_single_frame (ctx);
|
||||||
/* Successful getcontext is supposed to return 0. If we don't set rax to 0
|
/* Successful getcontext is supposed to return 0. If we don't set rax to 0
|
||||||
here, there's a chance that code like this:
|
here, there's a chance that code like this:
|
||||||
|
@ -1937,8 +1911,8 @@ swapcontext (ucontext_t *oucp, const ucontext_t *ucp)
|
||||||
PCONTEXT ctx = (PCONTEXT) &oucp->uc_mcontext;
|
PCONTEXT ctx = (PCONTEXT) &oucp->uc_mcontext;
|
||||||
ctx->ContextFlags = CONTEXT_FULL;
|
ctx->ContextFlags = CONTEXT_FULL;
|
||||||
RtlCaptureContext (ctx);
|
RtlCaptureContext (ctx);
|
||||||
|
/* See comments in getcontext. */
|
||||||
__unwind_single_frame (ctx);
|
__unwind_single_frame (ctx);
|
||||||
/* See above. */
|
|
||||||
oucp->uc_mcontext.rax = 0;
|
oucp->uc_mcontext.rax = 0;
|
||||||
oucp->uc_sigmask = oucp->uc_mcontext.oldmask = _my_tls.sigmask;
|
oucp->uc_sigmask = oucp->uc_mcontext.oldmask = _my_tls.sigmask;
|
||||||
return setcontext (ucp);
|
return setcontext (ucp);
|
||||||
|
|
Loading…
Reference in New Issue