This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

patch to support libunwind-based exception handling


Attached below is a small patch against gcc3.1 which makes it possible
to build a version of GCC that uses libunwind as the basis for
exception handling (see
http://www.hpl.hp.com/hosted/linux/mail-archives/libunwind/ for more
discussions on libunwind).

To use this patch, you first need to install libunwind, which is
available at:

	ftp://ftp.hpl.hp.com/pub/linux-ia64/libunwind-0.1.tar.gz

This library is still under development and currently limited to ia64
linux, though eventually the goal is to have it work for several other
platforms.

Once libunwind is installed and the patches below applied, you need to
rerun autoconfig.  Afterwards, configure option
"--enable-libunwind-exceptions" can be used to request GCC to be built
with the libunwind library.  If everything goes well, GCC should build
as usual and libunwind should be used without any additional work.  To
verify that you linked against libunwind, you can run "nm" on a C++
program and you should see several symbols starting with _U_.  For
example:

	4000000000006a90 T _U_ia64_get_frame_state
	400000000000c830 T _U_ia64_get_proc_info

Some caveats: this stuff is not ready for prime-time yet, but I am
interested in any and all feedback from the GCC community.  In
particular, I don't really understand all the issues that are involved
in making libgcc depend on another system library (libunwind).  In the
patch below, you'll see that I made some changes to gcc.c.  I suspect
the changes are quite wrong but I'm not sure what's the right way to
do this.  Also, currently libunwind is available only as a static
library, but eventually, it will be a shared library.  Are there any
issues here that I should be aware of?  Note that part of the reason
I'm working on libunwind is so that different compilers and
applications can share the same basic unwind code, so it would be
really nice if libunwind could be a separate shared library.

Thanks,

	--david

--- /dev/null	Sat Mar 24 01:35:12 2001
+++ unwind-libunwind.c	Thu Feb 14 13:22:14 2002
@@ -0,0 +1,124 @@
+#include "tconfig.h"
+#include "tsystem.h"
+#include "unwind.h"
+
+#define UNW_LOCAL_ONLY
+
+#include <libunwind.h>
+
+typedef struct {
+  _Unwind_Personality_Fn personality;
+} _Unwind_FrameState;
+
+struct _Unwind_Context {
+  unw_cursor_t cursor;
+};
+
+
+/* First come the helper-routines that are needed by unwind.inc.  */
+
+static _Unwind_Reason_Code
+uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  unw_word_t handler;
+
+  if (unw_step (&context->cursor) <= 0)
+    return _URC_END_OF_STACK;
+
+  unw_get_reg (&context->cursor, UNW_REG_HANDLER, &handler);
+  fs->personality = (_Unwind_Personality_Fn) handler;
+
+  return _URC_NO_REASON;
+}
+
+#define uw_update_context(context,fs)	do { ; } while (0)
+
+static inline _Unwind_Ptr
+uw_identify_context (struct _Unwind_Context *context)
+{
+  unw_word_t ip;
+  unw_get_reg (&context->cursor, UNW_REG_IP, &ip);
+  return (_Unwind_Ptr) ip;
+}
+
+#define uw_init_context(context)		\
+do						\
+  {						\
+    ucontext_t uc;				\
+    getcontext (&uc);				\
+    unw_init_local (&(context)->cursor, &uc);	\
+  }						\
+while (0)
+
+static inline void __attribute__ ((noreturn))
+uw_install_context (struct _Unwind_Context *current __attribute__ ((unused)),
+		    struct _Unwind_Context *target)
+{
+  unw_resume (&(target)->cursor);
+  abort ();
+}
+
+
+/* Now come the helper-routines which may be called from an exception
+   handler.  The interface for these routines are defined by the C++
+   ABI.  See: http://www.codesourcery.com/cxx-abi/abi-eh.html */
+
+_Unwind_Word
+_Unwind_GetGR (struct _Unwind_Context *context, int index)
+{
+  unw_word_t ret;
+
+  /* Note: here we depend on the fact that general registers are
+     expected to start with register number 0!  */
+  unw_get_reg (&context->cursor, index, &ret);
+  return ret;
+}
+
+/* Overwrite the saved value for register REG in CONTEXT with VAL.  */
+
+void
+_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
+{
+  /* Note: here we depend on the fact that general registers are
+     expected to start with register number 0!  */
+  unw_set_reg (&context->cursor, index, val);
+}
+
+/* Retrieve the return address for CONTEXT.  */
+
+inline _Unwind_Ptr
+_Unwind_GetIP (struct _Unwind_Context *context)
+{
+  unw_word_t ret;
+
+  unw_get_reg (&context->cursor, UNW_REG_IP, &ret);
+  return ret;
+}
+
+/* Overwrite the return address for CONTEXT with VAL.  */
+
+inline void
+_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
+{
+  unw_set_reg (&context->cursor, UNW_REG_IP, val);
+}
+
+void *
+_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
+{
+  unw_word_t ret;
+
+  unw_get_reg (&context->cursor, UNW_REG_LSDA, &ret);
+  return (void *) ret;
+}
+
+_Unwind_Ptr
+_Unwind_GetRegionStart (struct _Unwind_Context *context)
+{
+  unw_word_t ret;
+
+  unw_get_reg (&context->cursor, UNW_REG_PROC_START, &ret);
+  return (_Unwind_Ptr) ret;
+}
+
+#include "unwind.inc"
Index: config.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config.in,v
retrieving revision 1.133
diff -u -r1.133 config.in
--- config.in	2002/01/10 22:21:38	1.133
+++ config.in	2002/02/16 00:18:08
@@ -554,6 +554,9 @@
 /* Define 0/1 to force the choice for exception handling model. */
 #undef CONFIG_SJLJ_EXCEPTIONS
 
+/* Define 0/1 to force the choice for exception handling model. */
+#undef CONFIG_LIBUNWIND_EXCEPTIONS
+
 
 /* Bison unconditionally undefines `const' if neither `__STDC__' nor
    __cplusplus are defined.  That's a problem since we use `const' in
Index: configure.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/configure.in,v
retrieving revision 1.576
diff -u -r1.576 configure.in
--- configure.in	2002/01/10 22:21:36	1.576
+++ configure.in	2002/02/16 00:18:16
@@ -2129,6 +2129,13 @@
 fi
 AC_SUBST(MAINT)dnl
 
+AC_ARG_ENABLE(libunwind-exceptions,
+[  --enable-libunwind-exceptions
+                          arrange to use libunwind-based exception handling],
+[libunwind=`if test $enableval = yes; then echo 1; else echo 0; fi`
+AC_DEFINE_UNQUOTED(CONFIG_LIBUNWIND_EXCEPTIONS, $libunwind,
+  [Define 0/1 to force the choice for exception handling model.])])
+
 # With Setjmp/Longjmp based exception handling.
 AC_ARG_ENABLE(sjlj-exceptions,
 [  --enable-sjlj-exceptions
Index: cppinit.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cppinit.c,v
retrieving revision 1.199
diff -u -r1.199 cppinit.c
--- cppinit.c	2002/02/02 18:56:34	1.199
+++ cppinit.c	2002/02/16 00:18:18
@@ -651,6 +651,10 @@
   /* libgcc needs to know this.  */
   C("__USING_SJLJ_EXCEPTIONS__","1"),
 #endif
+#if USING_LIBUNWIND_EXCEPTIONS
+  /* libgcc needs to know this.  */
+  C("__USING_LIBUNWIND_EXCEPTIONS__","1"),
+#endif
 #ifndef NO_BUILTIN_SIZE_TYPE
   C("__SIZE_TYPE__",		SIZE_TYPE),
 #endif
Index: except.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/except.h,v
retrieving revision 1.61
diff -u -r1.61 except.h
--- except.h	2002/01/12 13:45:38	1.61
+++ except.h	2002/02/16 00:18:18
@@ -171,6 +171,14 @@
 #define MUST_USE_SJLJ_EXCEPTIONS	0
 #endif
 
+#ifdef CONFIG_LIBUNWIND_EXCEPTIONS
+# if CONFIG_LIBUNWIND_EXCEPTIONS == 1
+#  define USING_LIBUNWIND_EXCEPTIONS	1
+# else
+#  define USING_LIBUNWIND_EXCEPTIONS	0
+# endif
+#endif
+
 #ifdef CONFIG_SJLJ_EXCEPTIONS
 # if CONFIG_SJLJ_EXCEPTIONS == 1
 #  define USING_SJLJ_EXCEPTIONS		1
Index: gcc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gcc.c,v
retrieving revision 1.290
diff -u -r1.290 gcc.c
--- gcc.c	2002/02/11 22:14:22	1.290
+++ gcc.c	2002/02/16 00:18:23
@@ -1524,8 +1524,8 @@
 			    "-lgcc_s%M"
 #endif
 			    ,
-			    "-lgcc",
-			    "-lgcc_eh");
+			    "-lgcc -lunwind",
+			    "-lgcc_eh -lunwind");
 	    p += 5;
 	    in_sep = 0;
 	  }
@@ -1540,8 +1540,8 @@
 			    "-lgcc_s%M"
 #endif
 			    ,
-			    "libgcc.a%s",
-			    "libgcc_eh.a%s");
+			    "libgcc.a%s libunwind.a%s",
+			    "libgcc_eh.a%s libunwind.a%s");
 	    p += 10;
 	    in_sep = 0;
 	  }
Index: config/ia64/unwind-ia64.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/ia64/unwind-ia64.c,v
retrieving revision 1.5
diff -u -r1.5 unwind-ia64.c
--- config/ia64/unwind-ia64.c	2002/01/21 02:24:02	1.5
+++ config/ia64/unwind-ia64.c	2002/02/16 00:18:27
@@ -30,13 +30,16 @@
    This exception does not however invalidate any other reasons why
    the executable file might be covered by the GNU General Public License.  */
 
+#ifndef __USING_SJLJ_EXCEPTIONS__
+# ifdef __USING_LIBUNWIND_EXCEPTIONS__
+#  include "unwind-libunwind.c"
+# else /* ! __USING_LIBUNWIND_EXCEPTIONS__ */
 
 #include "tconfig.h"
 #include "tsystem.h"
 #include "unwind.h"
 #include "unwind-ia64.h"
 
-#ifndef __USING_SJLJ_EXCEPTIONS__
 #define UNW_VER(x)		((x) >> 48)
 #define UNW_FLAG_MASK		0x0000ffff00000000
 #define UNW_FLAG_OSMASK		0x0000f00000000000
@@ -2036,4 +2039,6 @@
 }
 
 #include "unwind.inc"
-#endif
+
+# endif /* ! __USING_LIBUNWIND_EXCEPTIONS__ */
+#endif /* !__USING_SJLJ_EXCEPTIONS__ */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]