Wrong wording in 1.3 "Throwing an exception."
Jim Dehnert
dehnert at baalbek.engr.sgi.com
Thu Oct 5 03:18:36 UTC 2000
> From: Christophe de Dinechin <ddd at cup.hp.com>
>
> The current wording doesn't match the C++ standard:
>
> > If the unwinder encounters an unexpected error during phase 2,
> > the unwind runtime may have modified the stack, e.g. popped
> > frames from it, or landing pad code may have caused stack corruption.
> > As a result, the unwind library probably could not find a return address,
> > and the caller of _Unwind_RaiseException could make no assumptions about
> > the state of its stack. Rather than attempt to return, therefore, the unwind
> > library should use the exception_cleanup entry in the exception,
> > and then call abort().
>
> What C++ mandates in that case is calling terminate(), not abort(), and that's a
> decision that only the C++ runtime can make (it may be different for other
> languages).
>
> What's more, the justification doesn't apply very well on IA-64. There is
> only one return address for _RaiseException, and it is not on the stack
> but in a local register (br0). Therefore, _RaiseException has very good
> chances of being able to return to the C++ runtime, and from there, we
> move only downwards in the calls tack (terminate() which typically calls
> abort() itself).
>
> So the paragraph above should indicate that we return _URC_FATAL_PHASE2_ERROR.
Well, I was about ready to do this, when I got worried. I know we
talked about this last week, and agreed as above, but I'd like to get
confirmation from more people than were present that we're not opening
an implementation can of worms.
As Christophe points out, the objection that a return address might be
hard to find is at least overstated. But the bigger problem is that
the caller of _Unwind_RaiseException must assume a garbaged stack, and
likely has garbage in its registers, including GP and an unknown
stacked register state, which might make it difficult to find
terminate() to call it. So the problem isn't really difficulty
for the unwind runtime, but for its caller. This call (to
_Unwind_RaiseException) will happen in many places in compiled code, so
I would think that if we're not careful, we could place some nasty, and
not very useful, constraints on compilers. Who has thought about the
implications of this, and what do you think?
There are several potential specifications we can make:
1) Unwinder returns _URC_FATAL_PHASE2_ERROR.
a) Nothing further specified.
b) Require that caller call terminate() with no further help.
c) Require that the unwinder also return valid GP for caller
(and perhaps other registers). (Remember that we've been
modifying the context during phase 2 unwinding, so this
probably requires extra work in the unwinder.)
2) Unwinder calls abort().
3) Unwinder may do either (1) or (2).
4) Unwinder behavior is completely undefined.
Biases, anyone?
Jim
- Jim Dehnert dehnert at sgi.com
(650)933-4272
More information about the cxx-abi-dev
mailing list