Carlo Kok Carlo Kok - 1 month ago 11
C Question

How to properly call rtlunwind from within an x86_64 windows exception handler

I'm trying to implement a win64 exception personality and can't find much documentation on the subject.

I've already got a working win32 version but the win64 one crashes on

rtlunwind
(access violation) in the "catch" part of a win64 exception handler, to unwind to the catch handler frame and continuation:

int ExceptionHandler(EXCEPTION_RECORD arec, uint64_t EstablisherFrame, PCONTEXT context, PDISPATCHER_CONTEXT dispatcher)
{
if (0 == (arec->ExceptionFlags & ( rtl.EXCEPTION_UNWINDING | rtl.EXCEPTION_EXIT_UNWIND)))
{
// check if this is a catch supported
rtl.RtlUnwindEx(EstablisherFrame, NULL, arec, NULL, context, dispatcher->HistoryTable);
// call catch & jump to continuation
}
}


Basically, I'm trying to find the parameters to
RtlUnwind
/
RtlUnwindEx
for a given catch.

Can anyone point me to information on what I can try or a sample implementation of seh for win64?

Answer

turns out this can be done by passing a new exception object to rtlUnwind with a CallCatch method as first info parameter, with STATUS_UNWIND_CONSOLIDATE as code. This will unwind the whole thing (retriggering the personality for any cleanup/finally)

 EXCEPTION_RECORD EH;
  EH.ExceptionCode = STATUS_UNWIND_CONSOLIDATE;
  EH.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
  EH.NumberParameters = 4;
  EH.ExceptionInformation[0] = (ULONG)CallCatch;
  EH.ExceptionInformation[1] = EstFrame;
  EH.ExceptionInformation[2] = dispatcher->ImageBase + aHandler->Handler;
  EH.ExceptionInformation[3] = aCatch->TryLow;
rtl.RtlUnwindEx(estFrame, dispatcher->ControlPc, @EH, NULL, Context, dispatcher->HistoryTable);

Call catch should take a function with EXCEPTION_RECORD* as parameter, call the actual catch and returning the continuation address for this catch.