[LLVMdev] Darwin vs exceptions
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
change in uw_identify_context that we have you would have the same
>> 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
> 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
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
/* Identify when we've reached the designated handler
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
> 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).
More information about the llvm-dev