libphobos: Select the appropriate exception handler in getClassInfo

This is analogous to __gdc_personality, which ignores in-flight
exceptions that we haven't collided with yet.

libphobos/ChangeLog:

	* libdruntime/gcc/deh.d (ExceptionHeader.getClassInfo): Move to...
	(getClassInfo): ...here as free function.  Add lsda parameter.
	(scanLSDA): Pass lsda to actionTableLookup.
	(actionTableLookup): Add lsda parameter, pass to getClassInfo.
	(__gdc_personality): Remove currentCfa variable.
This commit is contained in:
Iain Buclaw 2021-09-25 23:18:53 +02:00
parent ed3ec7343b
commit 8088a33df5
1 changed files with 44 additions and 30 deletions

View File

@ -279,26 +279,6 @@ struct ExceptionHeader
}
}
/**
* Look at the chain of inflight exceptions and pick the class type that'll
* be looked for in catch clauses.
*/
static ClassInfo getClassInfo(_Unwind_Exception* unwindHeader) @nogc
{
ExceptionHeader* eh = toExceptionHeader(unwindHeader);
// The first thrown Exception at the top of the stack takes precedence
// over others that are inflight, unless an Error was thrown, in which
// case, we search for error handlers instead.
Throwable ehobject = eh.object;
for (ExceptionHeader* ehn = eh.next; ehn; ehn = ehn.next)
{
Error e = cast(Error)ehobject;
if (e is null || (cast(Error)ehn.object) !is null)
ehobject = ehn.object;
}
return ehobject.classinfo;
}
/**
* Convert from pointer to unwindHeader to pointer to ExceptionHeader
* that it is embedded inside of.
@ -666,7 +646,7 @@ _Unwind_Reason_Code scanLSDA(const(ubyte)* lsda, _Unwind_Exception_Class excepti
{
// Otherwise we have a catch handler or exception specification.
handler = actionTableLookup(actions, unwindHeader, actionRecord,
exceptionClass, TTypeBase,
lsda, exceptionClass, TTypeBase,
TType, TTypeEncoding,
saw_handler, saw_cleanup);
}
@ -694,7 +674,8 @@ _Unwind_Reason_Code scanLSDA(const(ubyte)* lsda, _Unwind_Exception_Class excepti
* Look up and return the handler index of the classType in Action Table.
*/
int actionTableLookup(_Unwind_Action actions, _Unwind_Exception* unwindHeader,
const(ubyte)* actionRecord, _Unwind_Exception_Class exceptionClass,
const(ubyte)* actionRecord, const(ubyte)* lsda,
_Unwind_Exception_Class exceptionClass,
_Unwind_Ptr TTypeBase, const(ubyte)* TType,
ubyte TTypeEncoding,
out bool saw_handler, out bool saw_cleanup)
@ -702,7 +683,7 @@ int actionTableLookup(_Unwind_Action actions, _Unwind_Exception* unwindHeader,
ClassInfo thrownType;
if (isGdcExceptionClass(exceptionClass))
{
thrownType = ExceptionHeader.getClassInfo(unwindHeader);
thrownType = getClassInfo(unwindHeader, lsda);
}
while (1)
@ -778,6 +759,41 @@ int actionTableLookup(_Unwind_Action actions, _Unwind_Exception* unwindHeader,
return 0;
}
/**
* Look at the chain of inflight exceptions and pick the class type that'll
* be looked for in catch clauses.
*/
ClassInfo getClassInfo(_Unwind_Exception* unwindHeader,
const(ubyte)* currentLsd) @nogc
{
ExceptionHeader* eh = ExceptionHeader.toExceptionHeader(unwindHeader);
// The first thrown Exception at the top of the stack takes precedence
// over others that are inflight, unless an Error was thrown, in which
// case, we search for error handlers instead.
Throwable ehobject = eh.object;
for (ExceptionHeader* ehn = eh.next; ehn; ehn = ehn.next)
{
const(ubyte)* nextLsd = void;
_Unwind_Ptr nextLandingPad = void;
_Unwind_Word nextCfa = void;
int nextHandler = void;
ExceptionHeader.restore(&ehn.unwindHeader, nextHandler, nextLsd, nextLandingPad, nextCfa);
// Don't combine when the exceptions are from different functions.
if (currentLsd != nextLsd)
break;
Error e = cast(Error)ehobject;
if (e is null || (cast(Error)ehn.object) !is null)
{
currentLsd = nextLsd;
ehobject = ehn.object;
}
}
return ehobject.classinfo;
}
/**
* Called when the personality function has found neither a cleanup or handler.
* To support ARM EABI personality routines, that must also unwind the stack.
@ -934,16 +950,15 @@ private _Unwind_Reason_Code __gdc_personality(_Unwind_Action actions,
// current object onto the end of the prevous object.
ExceptionHeader* eh = ExceptionHeader.toExceptionHeader(unwindHeader);
auto currentLsd = lsda;
auto currentCfa = cfa;
bool bypassed = false;
while (eh.next)
{
ExceptionHeader* ehn = eh.next;
const(ubyte)* nextLsd;
_Unwind_Ptr nextLandingPad;
_Unwind_Word nextCfa;
int nextHandler;
const(ubyte)* nextLsd = void;
_Unwind_Ptr nextLandingPad = void;
_Unwind_Word nextCfa = void;
int nextHandler = void;
ExceptionHeader.restore(&ehn.unwindHeader, nextHandler, nextLsd, nextLandingPad, nextCfa);
@ -952,14 +967,13 @@ private _Unwind_Reason_Code __gdc_personality(_Unwind_Action actions,
{
// We found an Error, bypass the exception chain.
currentLsd = nextLsd;
currentCfa = nextCfa;
eh = ehn;
bypassed = true;
continue;
}
// Don't combine when the exceptions are from different functions.
if (currentLsd != nextLsd && currentCfa != nextCfa)
if (currentLsd != nextLsd)
break;
// Add our object onto the end of the existing chain.