OK, as you may have guessed, I'm still driving myself insane trying to fix __try and friends. I have some other less promising ideas on the backburner; this one seemed to have sufficient potential that I thought I would ask the group to let me know what they think.
In short: gcc accepts the above options. The first, is considered to be a C++ compatibility mode in C. That is to say, it provides the right glue such that exceptions can unwind through calls to C libraries. If /any/ library in the call-chain leaves this option out, I'm afraid it breaks down.
The second, -fasync-unwind-tables, provides "dwarf2 unwind tables". I've looked through the dwarf2 spec and some other sources, but I have yet to find solid documentation for this... perhaps it's a "use the source, Luke" situation. But this second option promises "instruction-granularity" unwind tables of some kind. IOW, presumably, this would be enough to implement __try and friends without looking beyond the stack pointer.
As for the idea of stealing the return pointer on the stack. I like it even less now. It appears that signal handlers are allowed to clobber the stack above the SP on some architectures, which means we're pretty much up a creek. There still might be some ultra-clever work-around involving copying the current stack frame, but I think we would at least have to create our own trampolines in asm, which, I fear, might break in subsequent gcc releases...
So... anybody know where these options are actually documented? I mean, I see the blurb in the info pages, which is enticing, but surely there is some API or datastructure to look at somewhere....
Note: I know nothing of exception handling.
Your only option for __try and friends may be fixing gcc. There is a SEH patch for Mingw/gcc that one of the ReactOS developers wrote. There are issues with it not to mention legal issues as borland has a patent on SEH in C. If I am understanding what WINE and ReactOS needs it is C++ style exception handling in C and Capsers SEH patch does a lot of this.
Thanks Steven
--- "Gregory M. Turner" gmturner007@ameritech.net wrote:
OK, as you may have guessed, I'm still driving myself insane trying to fix __try and friends. I have some other less promising ideas on the backburner; this one seemed to have sufficient potential that I thought I would ask the group to let me know what they think.
In short: gcc accepts the above options. The first, is considered to be a C++ compatibility mode in C. That is to say, it provides the right glue such that exceptions can unwind through calls to C libraries. If /any/ library in the call-chain leaves this option out, I'm afraid it breaks down.
The second, -fasync-unwind-tables, provides "dwarf2 unwind tables". I've looked through the dwarf2 spec and some other sources, but I have yet to find solid documentation for this... perhaps it's a "use the source, Luke" situation. But this second option promises "instruction-granularity" unwind tables of some kind. IOW, presumably, this would be enough to implement __try and friends without looking beyond the stack pointer.
As for the idea of stealing the return pointer on the stack. I like it even less now. It appears that signal handlers are allowed to clobber the stack above the SP on some architectures, which means we're pretty much up a creek. There still might be some ultra-clever work-around involving copying the current stack frame, but I think we would at least have to create our own trampolines in asm, which, I fear, might break in subsequent gcc releases...
So... anybody know where these options are actually documented? I mean, I see the blurb in the info pages, which is enticing, but surely there is some API or datastructure to look at somewhere....
-- "Security is mostly superstition. It does not exist in nature, nor do the children of men as a whole experience it. Avoiding danger is no safer in the long run than outright exposure. Life is either a daring adventure, or nothing. To keep our faces toward change and behave like free spirits in the presence of fate is strength undefeatable." --Helen Keller
gmt
__________________________________ Do you Yahoo!? The New Yahoo! Search - Faster. Easier. Bingo. http://search.yahoo.com
Gregory Turner wrote:
The second, -fasync-unwind-tables, provides "dwarf2 unwind tables". I've looked through the dwarf2 spec and some other sources, but I have yet to find solid documentation for this... perhaps it's a "use the source, Luke" situation. But this second option promises "instruction-granularity" unwind tables of some kind. IOW, presumably, this would be enough to implement __try and friends without looking beyond the stack pointer.
By "unwind tables" the GCC manual means here what the DWARF-2 standard calls "Call Frame Information"; they are described in chapter 6.4.
Bascially, the call frame information for a function denotes all points within the routine where 'something interesting' related to the call stack happens: when the function modifies the stack pointer, when the function uses some other register as frame pointer, when and where call-saved registers are stored in the call frame.
Using this information, it is possible for the exception handling runtime to 'virtually unwind' the call stack, which allows to retrieve the frame address, return address, and saved register values for every frame in the call chain.
So... anybody know where these options are actually documented? I mean, I see the blurb in the info pages, which is enticing, but surely there is some API or datastructure to look at somewhere....
Most of the details are internal to the exception handling routines (in libgcc). The exported interface is documented in the unwind.h header (which comes with gcc and/or glibc). To actually trigger stack unwinding, you'd need to use _Unwind_RaiseException or _Unwind_ForcedUnwind. However, those routines are also integrated into the language-specific exception processing, which goes beyond pure unwind tables, so I'm not sure whether you can use them for your purposes.
What exactly do you want to achieve?
Bye, Ulrich
On Tuesday 13 May 2003 03:53 pm, Ulrich Weigand wrote:
By "unwind tables" the GCC manual means here what the DWARF-2 standard calls "Call Frame Information"; they are described in chapter 6.4.
why, thank you, that's helpful.
What exactly do you want to achieve?
Well, you are probably going to laugh, but now that we are using some MIDL-generated code, I'm racking my brains on how to improve the exception handling macro's built into wine. The MIDL-generated code utilizes the typical Microsoftian (Borlandian?) try { } except(bool expr) { } / try { } finally { } construct.
Possible goals are:
achieve real "SEH"-style syntax, that is, no bloody __ENDTRY macro.
fix "break"
fix "return" from try/finally blocks.
Now here comes the part that will make you laugh: I'm supposed to do all this without patching gcc, using c++, or doing anything nonportable. In reality, an x86-specific solution that really worked would probably cut the mustard, IMO, at least as a starting point for cross-platform support.
I made some proof-of-concept patches which use the existing wine macros and various gcc-ism's to achieve some of these goals (they are not "right", of course). I had given up on it, or at least put it on the back burner, but Ove's recent DCOM patches inspired me to continue bashing my head against the wall...
Anyhow, I'll take a look at the dwarf2 goodies, maybe I'll decide that it's do-able, but more trouble than its worth... either way, I intend to make some kind of patch out of this whole investigation, as I am pretty darn sure I can at least fix one of the forementioned deficiencies, maybe even two, without making any major sacrifices.
If I'm lucky, I will stumble upon a solution to all three, but I'm kind of learning some of this (OK, all of it ;) ) as I go, and somewhat skeptical of my chances...
Knowing you, Dr. Weigand, you probably instantly know how to achieve this, so don't worry about spoiling the fun, you can go ahead and tell us ;)
Gregory Turner wrote:
Possible goals are:
achieve real "SEH"-style syntax, that is, no bloody __ENDTRY macro.
fix "break"
fix "return" from try/finally blocks.
These are certainly interesting goals, but they appear to be hard to achieve without compiler support ...
Anyhow, I'll take a look at the dwarf2 goodies, maybe I'll decide that it's do-able, but more trouble than its worth... either way, I intend to make some kind of patch out of this whole investigation, as I am pretty darn sure I can at least fix one of the forementioned deficiencies, maybe even two, without making any major sacrifices.
I don't quite see how dwarf2 unwinding fits into this. Is this just to be able to avoid the setjmp?
Note that g++ exception handling with dwarf2 works quite different from MSVC exception handling -- the former hooks exception processing into the dwarf2 frame 'personality' routines, while the latter uses the exception frame chain anchored in the TEB ...
Bye, Ulrich
On Monday 19 May 2003 05:14 pm, Ulrich Weigand wrote:
Gregory Turner wrote:
Possible goals are:
achieve real "SEH"-style syntax, that is, no bloody __ENDTRY macro.
fix "break"
fix "return" from try/finally blocks.
These are certainly interesting goals, but they appear to be hard to achieve without compiler support ...
heh, so they are :(
Anyhow, I'll take a look at the dwarf2 goodies, maybe I'll decide that it's do-able, but more trouble than its worth... either way, I intend to make some kind of patch out of this whole investigation, as I am pretty darn sure I can at least fix one of the forementioned deficiencies, maybe even two, without making any major sacrifices.
I don't quite see how dwarf2 unwinding fits into this. Is this just to be able to avoid the setjmp?
maybe it doesn't. I was thinking along the lines of using the unwind information to mark various places in the stack, or for dynamically generating bits of machine code... who knows, just "fishing", really.
Note that g++ exception handling with dwarf2 works quite different from MSVC exception handling -- the former hooks exception processing into the dwarf2 frame 'personality' routines, while the latter uses the exception frame chain anchored in the TEB ...
Ideally, some compiler will emerge which would generate the same undocumented unwind tables used by msvc to do it... that way tryblocks from native dlls and wine dlls, and MSVC++ and XYZ++ exceptions could all get along swimmingly... however, I was only trying to get the syntax to do the right thing in wine code, hoping I would find it to be a simpler exercise...
FYI, after a somewhat extensive investigation, and nagging the hell out of Alexandre and wine-devel, I've pretty much given up on anything other than compiler support.
Gregory Turner wrote:
On Monday 19 May 2003 05:14 pm, Ulrich Weigand wrote:
Note that g++ exception handling with dwarf2 works quite different from MSVC exception handling -- the former hooks exception processing into the dwarf2 frame 'personality' routines, while the latter uses the exception frame chain anchored in the TEB ...
Ideally, some compiler will emerge which would generate the same undocumented unwind tables used by msvc to do it... that way tryblocks from native dlls and wine dlls, and MSVC++ and XYZ++ exceptions could all get along swimmingly...
Note that there are two quite different things involved here, as far as GCC extensions are concerned.
First, we'd need a GCC extension to support the __try/__finally and/or __try/__except syntax in the C (and possibly C++) frontend. This would hook into the regular GCC exception infrastructure (which on most targets uses dwarf2 frame personality routines to actually handle exceptions).
However, this wouldn't be enough, as those exception wouldn't be integrated with Windows/Wine 'SEH' based exceptions. So you'd really want *another* GCC extension to get GCC to use a different exception handling infrastructure (for both the new __try/__finally *and* for regular C++ exceptions as well), which would be compatible with Windows exception handling.
As the SEH based exception handling is large undocumented, and also very much platform specific, I'd doubt the GCC folks would be happy about the latter part ...
A different approach might be to add code to Wine to 'interface' between the two exception infrastructures e.g. by catching all Windows exceptions and rethrowing them as GCC exceptions or vice versa at every Windows/Unix code boundary. I'm not sure whether this would actually work, though (and even if, it probably won't be very efficient).
Alternatively, the Wine exception unwinding could try to follow both the SEH TEB-anchored frame chain *and* the dwarf2 CFI stack unwinding chain and intermix between the two as required (this is actually similar to a proposal on the GCC list how to handle C++ cleanups intermixed with pthread cancellation handlers).
Bye, Ulrich
On Monday 19 May 2003 05:14 pm, Ulrich Weigand wrote:
Note that g++ exception handling with dwarf2 works quite different from MSVC exception handling -- the former hooks exception processing into the dwarf2 frame 'personality' routines, while the latter uses the exception frame chain anchored in the TEB ...
Ideally, some compiler will emerge which would generate the same
undocumented
unwind tables used by msvc to do it... that way tryblocks from native dlls
There is a very good articel about the internal implementation of exception handling in VC++:
http://www.codeproject.com/cpp/exceptionhandler.asp?target=internal%7Cseh
May be the information could help you.
-- Martin Fuchs martin-fuchs@gmx.net