On Jul 27, 2011, at 11:10 AM, John McCall wrote:> >> 4) IIUC, llvm has inherited a bug from gcc where the debugger >> cannot let the user know an exception is >> going to be uncaught until after the stack has been unwound -- >> contrary to the design intentions of the >> unwind library that most exception implementations are based on >> (with a two phase unwind algorithm) -- >> which creates a problem for the debugger user. > > I don't see this as a compiler bug. I can't imagine any > personality function > design which would let debuggers interrupt or control unwinding > without > hooking libUnwind, short of requiring every single call to have an > associated landing pad which the personality always lands at, even if > there's nothing to do there. That will never, ever be acceptable.John, I'm not able to figure out what you're really trying to say here. I am suggesting that there be a unique function that libUnwind calls in the event it detects that an exception is going to go uncaught all the way out past main, and that the user be able to set a break-point on that function (it could be the existing function "terminate", or a new one created just for this one purpose), so that the stack can be examined before it gets unwound. I'm not sure what you mean by "hooking", "interrupting", or "controlling". I am just suggesting to be allowed to set a break-point on some unique function. I finally dug deeper into the issue and figured out this is actually a problem with DWARF encoding, or the way that type info is encoded by GCC into DWARF and decoded by __gcc_personality from DWARF. (there is a comment somewhere in the LLVM documentation that IIRC seems to imply the problem is with the Types parameters to llvm.eh.select, but that is incorrect, the problem is deeper than that, it is with the underlying DWARF tables). In short the problem is that there is an ambiguity between a cleanup handler having an Action Table entry that looks like .byte 1 ;; Type = 1 (ie #1 entry in Types Table) .byte 0 ;; Next = 0 (ie none, ie this is the list terminator for this try-statement) together with a corresponding Types Table entry #1 that looks like .long 0 ;; RTTI pointer == NULL and a user explicit try-catchall statement which also contains the exact same DWARF encoding. Instead a user explicit catch-all should have an explicit entry in the Types Table (perhaps "void" could be the "user explicit match anything" marker) rather than containing the NULL value. Right now "cleanups" look to __gcc_personality exactly like "user explicit catch-all", so there is no way for __gcc_personality to tell that something will not be caught (if an exception will only go through cleanups all the way out past main, it "looks" to __gcc_personality that it is actually being caught by "catch-all"s, so __gcc_personality currently cannot figure this out until after the stack is entirely unwound and the user is then SOL). Peter Lawrence. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20110728/ed81de44/attachment.html>
On Jul 28, 2011, at 8:41 AM, Peter Lawrence wrote:> In short the problem is that there is an ambiguity between a cleanup handler having > an Action Table entry that looks like > .byte 1 ;; Type = 1 (ie #1 entry in Types Table) > .byte 0 ;; Next = 0 (ie none, ie this is the list terminator for this try-statement) > together with a corresponding Types Table entry #1 that looks like > .long 0 ;; RTTI pointer == NULLThis is not a cleanup. In the LSDAs for GCC's family of personalities, cleanups by definition have a zero index into the types table. I think I see your confusion, though. LLVM-GCC and Clang used to share a bug where cleanups would sometimes be emitted as catch-alls as a workaround to a flaw in the inliner. I fixed this flaw (or to be specific, I worked around it to the best of my ability given the constraints of the broken eh.exception/eh.selector representation) sometime in June, but part of the fix requires the front-end to emit different code, and I've only updated Clang to do so because I can't touch dragonegg and LLVM-GCC is dead. AFAIK, GCC never had this bug. John.
John, I'm still not sure what you're talking about, I have included the assembly output from two compilations, one with a user explicit catch-all, one with only an implicit cleanup, the DWARF Action Table and Types Table are absolutely identical, as are the indexes used to reference the Action Table from the region maps. -Peter Lawrence. ------------------------------------------------------------------------ --------------------------------------- extern void foo(); extern void print(const char *) __attribute__((nothrow)); void bar () { try { foo(); } catch (...) { print("caught (...)\n"); } } .section __TEXT,__gcc_except_tab ... ;; CallSite Table .long Ltmp0-Leh_func_begin0 .long Ltmp1-Ltmp0 <--- this region covers the call to foo .long Ltmp2-Leh_func_begin0 .byte 1 <--- this is it's Action Table index ... ;; Action Table .byte 1 .byte 0 ;; Types Table .long 0 ------------------------------------------------------------------------ --------------------------------------- extern void foo(); extern void print(const char *) __attribute__((nothrow)); class Bob { public: Bob() __attribute__((nothrow)); ~Bob() __attribute__((nothrow)); }; void bar () { Bob A, B, C; foo(); //~Bob C, B, Z; } .section __TEXT,__gcc_except_tab ... ;; CallSite Table .long Ltmp0-Leh_func_begin0 .long Ltmp1-Ltmp0 <--- this region covers the call to foo .long Ltmp2-Leh_func_begin0 .byte 1 <--- here is its Action Table index ... ;; Action Table .byte 1 .byte 0 ;; Types Table .long 0 ------------------------------------------------------------------------ --------------------------------------- On Jul 28, 2011, at 1:00 PM, John McCall wrote:> On Jul 28, 2011, at 8:41 AM, Peter Lawrence wrote: >> In short the problem is that there is an ambiguity between a >> cleanup handler having >> an Action Table entry that looks like >> .byte 1 ;; Type = 1 (ie #1 entry in Types Table) >> .byte 0 ;; Next = 0 (ie none, ie this is the list terminator for >> this try-statement) >> together with a corresponding Types Table entry #1 that looks like >> .long 0 ;; RTTI pointer == NULL > > This is not a cleanup. In the LSDAs for GCC's family of > personalities, cleanups > by definition have a zero index into the types table. I think I > see your confusion, > though. > > LLVM-GCC and Clang used to share a bug where cleanups would sometimes > be emitted as catch-alls as a workaround to a flaw in the inliner. > I fixed this > flaw (or to be specific, I worked around it to the best of my > ability given the > constraints of the broken eh.exception/eh.selector representation) > sometime > in June, but part of the fix requires the front-end to emit > different code, and I've > only updated Clang to do so because I can't touch dragonegg and > LLVM-GCC > is dead. > > AFAIK, GCC never had this bug. > > John.