[LLVMdev] Darwin vs exceptions
Dale Johannesen
dalej at apple.com
Sun Dec 9 10:48:49 PST 2007
On Dec 9, 2007, at 2:34 AM, Duncan Sands wrote:
> Hi Dale,
>
>>> this is the bit I don't understand. Why does it go
>>> into a loop? How can the unwinder possibly know that
>>> the original code did not have a catch-all, since we
>>> tell it which catches there are and we say: there is
>>> a catch-all!
>>
>> The unwinder works by doing a stack crawl to find a handler. Since
>> we're telling it every eh-selector is a catch-all handler, it finds
>> one immediately (that is not there)
>
> I'm not sure what you mean: there is a handler: it just rethrows
> the exception. This is not very interesting of course, but it's
> still a handler. Or do you mean something different when you talk
> of a handler?
I'm following the notation in comments in the unwinding code
(gcc/unwind*, especially unwind.inc, and libstdc++/libsupc++/eh*,
especially eh_personality.cc). "handler" is used consistently to mean
something that actually handles the thrown exception, a catch-block
for that thrown type. Code that just calls destructors and resumes is
a "cleanup", and is handled differently in the tables and code.
Linux's unwinder uses the same code, doesn't it? I bet if you make
the same
change in uw_identify_context that we have you would have the same
problem.
>> and caches where it thinks it
>> is. That code (cleanup or whatever) is executed and ends by reaching
>> Unwind_Resume, which tries to resume at where it thinks the handler
>> is.
>
> I also don't understand this: why is Unwind_Resume looking at where
> the exception's handler is?
I don't know the 'why' of any of this; I didn't write it, nor did
anybody at Apple.
> The handler used for the caught exception
> should be irrelevant to it. It sounds like the unwinder thinks that
> the Unwind_Resume is in the same eh region as the original throwing
> call.
Yes, exactly, and when you're using CFAs rather than IPs to identify
it, it is.
The code in question is in Unwind_RaiseException_Phase2, reached from
Unwind_Resume:
/* Identify when we've reached the designated handler
context. */
match_handler = (uw_identify_context (context) == exc->private_2
? _UA_HANDLER_FRAME : 0);
>> Which is back at the same code from which we reached
>> Unwind_Resume. This worked OK when we were caching the IP because
>> the IP of the throw and Unwind_Resume call were different, but when
>> caching the CFA they are the same, which confuses Unwind_Resume.
>
> How is catch-all then rethrow supposed to work then?
It isn't. Catch-all (corresponding to "catch(...)" ) ends the
unwinding.
> Are you sure
> that this isn't simply a bug in where labels are placed etc, the
> frame info or the exception table setup etc?
Yes, comparing gcc and llvm output has made me quite sure of that.
>> (This is darwin's unwinder but I think the patch I quoted is the only
>> relevant change to generic gcc code.
>> Could be wrong.)
>>
>>>>> - lang_eh_catch_all = return_null_tree;
>>>>> +/* lang_eh_catch_all = return_null_tree;*/
>>>
>>>> Ok, cool :) Duncan, Anton, what do you guys think about this?
>>>
>>> This is wrong - it breaks the semantics of invoke and causes
>>> eh to not work properly in some cases (see my email to Dale).
>>
>> Well, it works a lot better on Darwin than what's there now. I
>> believe telling the unwinder there is a cleanup is sufficient to get
>> control always transferred to the secondary label on the invoke.
>
> Are you saying that the Darwin unwinder doesn't have the special
> cleanup logic? If so you could indeed push a cleanup rather than
> a catch-all on Darwin.
What "special cleanup logic"?
>> Could you point me to an example that should fail?
>
> Sure - run the testsuite on linux with -enable-correct-eh-support
> changed to -enable-eh in Makefile.programs. Then apply your patch,
> run again and analyse the failures. I will do this and send you
> a reduced example (I used to have some but I don't remember what
> I did with them).
>
> Ciao,
>
> Duncan.
More information about the llvm-dev
mailing list