This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
IA64 HP-UX Unwind patch
- From: Steve Ellcey <sje at cup dot hp dot com>
- To: gcc-patches at gcc dot gnu dot org, libstdc++ at gcc dot gnu dot org
- Date: Wed, 14 Aug 2002 10:45:00 -0700 (PDT)
- Subject: IA64 HP-UX Unwind patch
- Reply-to: sje at cup dot hp dot com
I sent this out a while back but just realised I sent it to gcc-patches
and forgot to also send it to libstdc++.
This patch is the final patch for using HP-UX's libunwind instead of the
GCC unwind code on IA64. The problem I have run into is two ABI
differences between the HP Unwind and the GCC Unwind.
The first is what _URC_ code does _Unwind_DeleteException call the
cleanup routine with. HP uses _URC_NO_REASON and GCC uses
_URC_FOREIGN_EXCEPTION_CAUGHT. My fix for this was to create
_URC_EXPECTED_BY_CLEANUP in unwind.h and define it to
_URC_FOREIGN_EXCEPTION_CAUGHT if it was not already defined and then use
that in __gxx_exception_cleanup (libstdc++-v3/libsupc++/eh_throw.cc).
Then I put my own definition of _URC_EXPECTED_BY_CLEANUP in
libstdc++-v3/config/os/hpux/os_defines.h for HP-UX.
The second problem is with _Unwind_SetIP. Even in ILP32 mode, the HP-UX
Unwind library expects you to pass in a 64 bit pointer on IA64. So, I
created a macro in os_defines.h called UNWIND_SETIP to use instead of
calling _Unwind_SetIP if it is defined. I also ifdef'ed the
_Unwind_SetIP declaration in unwind.h so I could have my own version in
os_defines.h with different arg types.
My definition of UNWIND_SETIP uses a builtin called __extend_ptr to turn
the 32 bit pointer in landing_pad into a 64 bit pointer. I did not
include the implementation of this builtin in this patch but thought I
would do that seperately.
One possible change that I considered but was not able to manage was to
use the system unwind.h instead of the one in GCC when building
libstdc++-v3 but since they are both called unwind.h I couldn't figure
out how to tell unwind-cxx.h to use a system header instead of the GCC
one. Brackets instead of quotes had no effect. If I did this I
wouldn't have to include my own _Unwind_SetIP declaration and I could
put the default _URC_EXPECTED_BY_CLEANUP in eh_throw.c instead of
unwind.h and not mess with any GCC code but only with libstdc++-v3.
I can't think of any way to avoid the ifdef around _Unwind_SetIP though.
Comments?
Steve Ellcey
sje@cup.hp.com
2002-07-24 Steve Ellcey <sje@cup.hp.com>
* gcc/unwind.h (_URC_EXPECTED_BY_CLEANUP): New Macro with
default definition.
(_Unwind_SetIP): Prototype only if UNWIND_SETIP is not set.
* libstdc++-v3/config/os/hpux/os_defines.h (_URC_EXPECTED_BY_CLEANUP):
Define to match HP libunwind.
(UNWIND_SETIP) Define with new modified arguments.
* libstdc++-v3/libsupc++/eh_throw.cc (__gxx_exception_cleanup):
Use _URC_EXPECTED_BY_CLEANUP instead of _URC_FOREIGN_EXCEPTION_CAUGHT.
* libstdc++-v3/libsupc++/eh_personality.cc (PERSONALITY_FUNCTION):
Call UNWIND_SETIP instead of _Unwind_SetIP if defined.
*** gcc.orig/gcc/unwind.h Wed Jul 24 12:16:30 2002
--- gcc/gcc/unwind.h Wed Jul 24 12:42:25 2002
*************** typedef enum
*** 54,59 ****
--- 54,66 ----
_URC_CONTINUE_UNWIND = 8
} _Unwind_Reason_Code;
+ /* G++ _Unwind_DeleteException calls __gxx_exception_cleanup with
+ _URC_FOREIGN_EXCEPTION_CAUGHT, the HP libunwind library version
+ of _Unwind_DeleteException calls it with _URC_NO_REASON. */
+
+ #ifndef _URC_EXPECTED_BY_CLEANUP
+ #define _URC_EXPECTED_BY_CLEANUP _URC_FOREIGN_EXCEPTION_CAUGHT
+ #endif
/* The unwind interface uses a pointer to an exception header object
as its representation of an exception being thrown. In general, the
*************** extern _Unwind_Word _Unwind_GetGR (struc
*** 124,130 ****
--- 131,144 ----
extern void _Unwind_SetGR (struct _Unwind_Context *, int, _Unwind_Word);
extern _Unwind_Ptr _Unwind_GetIP (struct _Unwind_Context *);
+
+ /* HP IA64 ILP32 _Unwind_SetIP requires a 64 bit address, there is
+ a private extern and calling sequence in
+ libstdc++-v3/config/os/hpux/os_defines.h. */
+
+ #ifndef UNWIND_SETIP
extern void _Unwind_SetIP (struct _Unwind_Context *, _Unwind_Ptr);
+ #endif
extern void *_Unwind_GetLanguageSpecificData (struct _Unwind_Context *);
*** gcc.orig/libstdc++-v3/config/os/hpux/os_defines.h Wed Jul 24 12:16:57 2002
--- gcc/libstdc++-v3/config/os/hpux/os_defines.h Wed Jul 24 14:00:28 2002
*************** namespace std
*** 86,89 ****
--- 86,105 ----
typedef long int __padding_type;
#endif
+ /* HPUX IA64 _Unwind_DeleteException calls cleanup routine,
+ __gxx_exception_cleanup, with _URC_NO_REASON and not
+ _URC_FOREIGN_EXCEPTION_CAUGHT. */
+
+ #if defined(__ia64__)
+ #undef _URC_EXPECTED_BY_CLEANUP
+ #define _URC_EXPECTED_BY_CLEANUP _URC_NO_REASON
+ #endif
+
+ /* HPUX IA64 ILP32 Unwind_SetIP needs to be passed a 64 bit pointer. */
+
+ #if !defined(_LP64) && defined (__ia64__)
+ extern void _Unwind_SetIP (struct _Unwind_Context *, unsigned __attribute__((__mode__(__word__))));
+ #define UNWIND_SETIP(CONTEXT,LANDING_PAD) _Unwind_SetIP (CONTEXT, __extend_ptr ((void *) LANDING_PAD))
+ #endif
+
#endif
*** gcc.orig/libstdc++-v3/libsupc++/eh_throw.cc Wed Jul 24 12:17:50 2002
--- gcc/libstdc++-v3/libsupc++/eh_throw.cc Wed Jul 24 12:29:14 2002
*************** __gxx_exception_cleanup (_Unwind_Reason_
*** 42,48 ****
// If we haven't been caught by a foreign handler, then this is
// some sort of unwind error. In that case just die immediately.
! if (code != _URC_FOREIGN_EXCEPTION_CAUGHT)
__terminate (header->terminateHandler);
if (header->exceptionDestructor)
--- 42,48 ----
// If we haven't been caught by a foreign handler, then this is
// some sort of unwind error. In that case just die immediately.
! if (code != _URC_EXPECTED_BY_CLEANUP)
__terminate (header->terminateHandler);
if (header->exceptionDestructor)
*** gcc.orig/libstdc++-v3/libsupc++/eh_personality.cc Wed Jul 24 12:17:55 2002
--- gcc/libstdc++-v3/libsupc++/eh_personality.cc Wed Jul 24 12:30:17 2002
*************** PERSONALITY_FUNCTION (int version,
*** 419,425 ****
--- 419,429 ----
(_Unwind_Ptr) &xh->unwindHeader);
_Unwind_SetGR (context, __builtin_eh_return_data_regno (1),
handler_switch_value);
+ #ifdef UNWIND_SETIP
+ UNWIND_SETIP (context, landing_pad);
+ #else
_Unwind_SetIP (context, landing_pad);
+ #endif
return _URC_INSTALL_CONTEXT;
}