Closed GoogleCodeExporter closed 8 years ago
Some observations from printf'ing around in __tart_eh_personality_impl() a bit
- the following shows (some of) the activity in the exception handling for
EncodingTest.tart.
************************** __tart_eh_personality
actions: 1, forceUnwind? 0 ueHeader: 0x200800268, context: 0x7FFF5FBFECA0,
exceptionClass: 0x0
no langSpecData
************************** __tart_eh_personality
actions: 1, forceUnwind? 0 ueHeader: 0x200800268, context: 0x7FFF5FBFECA0,
exceptionClass: 0x0
pos1 4295085213
pos2 4295085239
found action
************************** __tart_eh_personality
actions: 2, forceUnwind? 0 ueHeader: 0x200800268, context: 0x7FFF5FBFE7C0,
exceptionClass: 0x0
no langSpecData
************************** __tart_eh_personality
actions: 6, forceUnwind? 0 ueHeader: 0x200800268, context: 0x7FFF5FBFE7C0,
exceptionClass: 0x0
pos1 4295085213
pos2 4295085239
_URC_INSTALL_CONTEXT
************************** __tart_eh_personality
actions: 6, forceUnwind? 0 ueHeader: 0x200800268, context: 0x7FFF5FBFECF0,
exceptionClass: 0x0
pos1 4295085213
pos2 4295085252
landingPad == 0
/bin/sh: line 1: 1210 Abort trap ./EncodingTest
The 2 pos values are printed after parseLDSAHeader() and findCallSite()
respectively. Seems like __tart_eh_personality() gets called a second time
with the same data after having return _URC_INSTALL_CONTEXT the previous
iteration to transfer control to the landing pad. The second time, it can't
find the landing pad and bad times ensue. I'm not totally sure what to expect
here, but that seems like slightly strange behavior.
Original comment by lst...@gmail.com
on 18 Mar 2011 at 4:14
That does indeed.
If I remember correctly (always a dubious proposition), the exception
propagation proceeds in two phases.
In the first phase, it calls the personality function for each callframe that
has either a catch block or a finally block (because if the function has
neither, the frontend won't generate invoke instructions for it, which means
effectively that call frame is ignored.)
In the second phase, it does it all again, only this time the cleanup code is
actually executed. In both phases, the personality function returns an action
code tells libunwind what to do for that call frame. Eventually we reach a call
frame that catches, or we reach the end of the stack.
The Tart personality function takes the exception structure, adds a *negative*
offset to get the Tart Throwable object. It then does a standard Tart
"isSubclass" test against each of the exception types listed for that call
frame. (If it's a finally block only, this test is skipped - this is indicated
by a 0 for the llvm.eh.selector argument value.) The result of the isSubclass
test then determines what action will be taken - whether it will catch the
exception or not.
The isSubclass test is fairly easy - every Tart object contains a pointer to a
TypeInfoBlock (TIB) which is very much like the vtable for C++. The TIB
includes a flat array containing all of the superclasses of that type, in the
form of TIB pointers. The DWARF exception data also contains a list of TIB
pointers, representing the catch types. So it's simply a matter of looking at
the throwable, and seeing if it or any of its superclasses are listed in the
catch list.
So given what you have said, here's a list of the first things I would check:
1) In phase one, is the call frame containing the catch block actually
returning the right action code or not?
2) The reason I mentioned alignment and padding is that one of the big
differences between leopard and snow leopard is that the latter is 64-bit. One
thing I worry about is subtracting from the exception address to get the
Throwable address - but as far as I know it's perfectly legal.
3) One way to compare structure alignment and padding is to dump out the .bc
files generated by Tart in text form. I usually use something like "llvm-dis -o
- <filename.bc> | more". You can look for the tart.core.Throwable type, copy
and paste that, and then compare that to what clang generates.
(BTW, I don't know how much of an LLVM whiz you are, so I'm not sure how much
explaining I need to do on that score.)
Original comment by viri...@gmail.com
on 18 Mar 2011 at 8:46
Thanks for the info - I'm definitely *not* an LLVM whiz, but am quite
interested in learning more so this is all good for me. I definitely
appreciate it!
Looks like the alignment is not a problem - everything there seems to have the
appropriate size and offsets, even on Snow Leopard here.
However, after much experimentation I found that within tart_eh_personality.c
if I replaced the implementation of readEncodedValue() with the implementation
of read_encoded_value_with_base() from
http://src.gnu-darwin.org/src/contrib/gcc/unwind-pe.h.html, the exception is
caught successfully and the tests pass (!).
I haven't yet narrowed down where the critical difference is between these two
implementations, but will do so and send a patch.
Original comment by lst...@gmail.com
on 19 Mar 2011 at 8:47
Wow dude, you are awesome!
Original comment by viri...@gmail.com
on 19 Mar 2011 at 9:39
OK, patch attached - looks like there were some additional offset calculations
required in the event DW_EH_PE_pcrel or DW_EH_PE_indirect were specified in the
encoding.
I also removed calls to memcpy() in that routine in the interest of efficiency,
but that's obviously not required.
With this patch, make check is fully successful for me!
Original comment by lst...@gmail.com
on 19 Mar 2011 at 9:54
Attachments:
My apologies for being so slow with applying your patch, I've been busy doing
my taxes which are very complex this year with the house sale and investments
and all that. In the mean time, do you have any idea of what you would like to
work on next (if anything?) I'm still in the process of getting the
documentation up to date.
Original comment by viri...@gmail.com
on 21 Mar 2011 at 2:42
No worries at all.
I would like to dive into the compiler to hack on some of the to-do's you've
identified, but I think first it would be good to do a little bit of
programming in tart proper, to get a better feel for it. I was thinking some
additions to the stdlib might be a good place to start, but am open to other
ideas. Maybe some file handling, or something along those lines?
In the meantime, I think we might finally be able to mark this issue as closed.
Phew.
Original comment by lst...@gmail.com
on 21 Mar 2011 at 3:07
Original comment by viri...@gmail.com
on 24 Mar 2011 at 3:13
Original issue reported on code.google.com by
lst...@gmail.com
on 23 Feb 2011 at 9:58