[PATCH] Dwarf 2 Unwind frames for mingw32/cygwin

Danny Smith dannysmith@clear.net.nz
Sun Dec 3 08:23:00 GMT 2006


Hello 

The attached patch enable Dwarf2 exception handling on windows32
targets.
It is virtually the same patch that I submitted 2 years ago,

http://gcc.gnu.org/ml/gcc-patches/2004-11/msg01989.html

but with some extra logic to handle weak linkage when using libgcc
as a shared lib (DLL).
 
It adds crtbegin.o and crtend.o as startfile/endfiles based on crtstuff
code, but separated out for now to allow easier specialization for a
system that does not have .init/.fini sections and that needs special
care
when resolving weak symbols from dll's

 __register and __deregister_frame_info are invoked indirectly
via a ctor/dtor pair. The ctor/dtor references live in crtend to make
them the first ctor, last dtor invoked.  The ctor/dtor sections are
given a
very high priority, to avoid  C++ init_priority conflicts. The actual
calls
to the unwind-dw2-fde.o functions are done in crtbegin so that we can
resolve the references in libgcc.a.ation, if that is an issue. 

The removal of #define DWARF2_UNWIND_INFO 0 in cygming.h
makes Dwarf2 unwind the default. It can still be overriden with
--enable-sjlj-exceptions when configuring.

The patch also enables the use of .jcr section to register Java classes.
binutuls support for .jcr section was added in
http://sources.redhat.com/ml/binutils/2004-11/msg00249.html

The patch fixes the old sjlj performance isssue:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14563

The .jcr part is relevant to:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18459

This patch produces no regressions wih mingw32 or cygwin in C, C++,
objc, gfortran. I haven't built libgcj for awhile becuase I only have
512MB of physical memory. Could java person help please. 

The next step after this is to build libgcc/libstdc++ and libjava as
dll's. This allows throwimg exceptions across dll/exe boundaries and
also some other static initialization problems. I can do that now by
adding a few lines to target makefile fragments but don't have the
libtool-fu to libtoolize the builds. 

Danny  


2006-12-03  Danny Smith  <dannysmith@users.sourceforge.net>

	* config.gcc (*-cygwin*): Add crtbegin.o, crtend.o as
	extra_parts.
	* config.gcc (*-mingw*): Likewise.
	* libgcc2.c (L__main): Do nothing for mingw32.
	* config/i386/cygming.h (DBX_REGISTER_NUMBER): Add comment.
	(DWARF_FRAME_REGNUM): Define.
	(DWARF2_UNWIND_INFO): Don't override default.
	* config/i386/cygwin.h (STARTFILE_SPEC): Add crtbegin.o.
	(ENDFILE_SPEC): Define as crtend.o.
	* config/i386/mingw32.h (STARTFILE_SEC): Add crtbegin.o.
	(ENDFILE_SPEC): Define as crtend.o.
	* config/i386/t-cygming: Add rules for crtbegin.o, crtend.o.
	* config/i386/cygming-crtbegin.c: New file.
	* config/i386/cygming-crtend.c: New file.


Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(revision 119268)
+++ gcc/config.gcc	(working copy)
@@ -1314,6 +1314,7 @@
 	c_target_objs=cygwin2.o
 	cxx_target_objs="cygwin2.o winnt-cxx.o"
 	extra_gcc_objs=cygwin1.o
+	extra_parts="crtbegin.o crtend.o"
 	if test x$enable_threads = xyes; then
 		thread_file='posix'
 	fi
@@ -1326,6 +1327,7 @@
 	extra_options="${extra_options} i386/cygming.opt"
 	extra_objs="winnt.o winnt-stubs.o"
 	cxx_target_objs=winnt-cxx.o
+	extra_parts="crtbegin.o crtend.o"
 	default_use_cxa_atexit=yes
 	case ${enable_threads} in
 	  "" | yes | win32)
Index: gcc/libgcc2.c
===================================================================
--- gcc/libgcc2.c	(revision 119268)
+++ gcc/libgcc2.c	(working copy)
@@ -2081,7 +2081,7 @@
 #endif
 #endif /* L_trampoline */
 

-#ifndef __CYGWIN__
+#if !defined (__CYGWIN__)  && !defined (__MINGW32__)
 #ifdef L__main
 
 #include "gbl-ctors.h"
Index: gcc/config/i386/cygming.h
===================================================================
--- gcc/config/i386/cygming.h	(revision 119268)
+++ gcc/config/i386/cygming.h	(working copy)
@@ -29,11 +29,20 @@
 #ifdef HAVE_GAS_PE_SECREL32_RELOC
 #define DWARF2_DEBUGGING_INFO 1
 
+/* Map gcc register number to DBX register number. Maintain
+   compatibility with old -gstabs compiled code.  */
 #undef DBX_REGISTER_NUMBER
 #define DBX_REGISTER_NUMBER(n) (write_symbols == DWARF2_DEBUG   \
                                 ? svr4_dbx_register_map[n]      \
                                 : dbx_register_map[n])
 
+/* Map gcc register number to DWARF 2 CFA column number.  Always
+   use the svr4_dbx_register_map for DWARF .eh_frame even if we
+   don't use DWARF .debug_frame.  */
+#undef DWARF_FRAME_REGNUM
+#define DWARF_FRAME_REGNUM(n) svr4_dbx_register_map[(n)] 
+ 
+
 /* Use section relative relocations for debugging offsets.  Unlike
    other targets that fake this by putting the section VMA at 0, PE
    won't allow it.  */
@@ -263,10 +272,10 @@
 #undef ASM_COMMENT_START
 #define ASM_COMMENT_START " #"
 
-/* DWARF2 Unwinding doesn't work with exception handling yet.  To make
-   it work, we need to build a libgcc_s.dll, and dcrt0.o should be
-   changed to call __register_frame_info/__deregister_frame_info.  */
-#define DWARF2_UNWIND_INFO 0
+/* DWARF2 Unwinding is default exception handling model.  Configure
+   with -enable-sjlj-exceptions to revert to old setjump/longjump
+   model.  */
+#define DWARF2_UNWIND_INFO 1
 
 /* Don't assume anything about the header files.  */
 #define NO_IMPLICIT_EXTERN_C
Index: gcc/config/i386/cygwin.h
===================================================================
--- gcc/config/i386/cygwin.h	(revision 119268)
+++ gcc/config/i386/cygwin.h	(working copy)
@@ -38,7 +38,10 @@
   %{shared|mdll: %{mno-cygwin:dllcrt2%O%s}}\
   %{!shared: %{!mdll: %{!mno-cygwin:crt0%O%s} %{mno-cygwin:crt2%O%s}\
   %{pg:gcrt0%O%s}}}\
-"
+  crtbegin%O%s"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend%O%s"
 
 /* Normally, -lgcc is not needed since everything in it is in the DLL,
but we
    want to allow things to be added to it when installing new versions
of
Index: gcc/config/i386/t-cygming
===================================================================
--- gcc/config/i386/t-cygming	(revision 119268)
+++ gcc/config/i386/t-cygming	(working copy)
@@ -30,3 +30,16 @@
 	$(srcdir)/config/i386/winnt-stubs.c
 
 STMP_FIXINC=stmp-fixinc
+
+# Effectively disable the crtbegin/end rules using crtstuff.c
+T = disable
+
+CRTSTUFF_T_CFLAGS = -fno-omit-frame-pointer
+
+crtbegin.o: $(srcdir)/config/i386/cygming-crtbegin.c $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) -c -o crtbegin.o \
+	$(srcdir)/config/i386/cygming-crtbegin.c
+
+crtend.o: $(srcdir)/config/i386/cygming-crtend.c $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) -c -o crtend.o  \
+	$(srcdir)/config/i386/cygming-crtend.c
Index: gcc/config/i386/mingw32.h
===================================================================
--- gcc/config/i386/mingw32.h	(revision 119268)
+++ gcc/config/i386/mingw32.h	(working copy)
@@ -67,7 +67,12 @@
 
 #undef STARTFILE_SPEC
 #define STARTFILE_SPEC "%{shared|mdll:dllcrt2%O%s} \
-  %{!shared:%{!mdll:crt2%O%s}} %{pg:gcrt2%O%s}"
+  %{!shared:%{!mdll:crt2%O%s}} %{pg:gcrt2%O%s}  \
+  crtbegin%O%s"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend%O%s"
+
 
 /* Override startfile prefix defaults.  */
 #ifndef STANDARD_STARTFILE_PREFIX_1
@@ -116,3 +121,9 @@
 /* mingw32 atexit function is safe to use in shared libraries.  Use it
    to register C++ static destructors.  */
 #define TARGET_CXX_USE_ATEXIT_FOR_CXA_ATEXIT hook_bool_void_true
+
+
+/* This works on mingw32.  */
+#undef TARGET_USE_JCR_SECTION
+#define TARGET_USE_JCR_SECTION 1
+
--- /dev/null	2006-12-03 19:54:27.656250000 +1300
+++ gcc/config/i386/cygming-crtbegin.c.	2006-12-01 09:29:14.562500000
+1300
@@ -0,0 +1,138 @@
+/* crtbegin object for windows32 targets.
+   Copyright (C) 2006  Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file.  (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+/* Target machine header files require this define. */
+#define IN_LIBGCC2
+
+#include "auto-host.h"
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "unwind-dw2-fde.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#ifndef LIBGCC_SONAME
+#define LIBGCC_SONAME "libgcc_s.dll"
+#endif
+
+#ifndef LIBGCJ_SONAME
+#define LIBGCJ_SONAME "libgcj_s.dll"
+#endif
+
+
+/* Make the declarations weak.  This is critical for
+   _Jv_RegisterClasses because it lives in libgcj.a  */
+extern void __register_frame_info (const void *, struct object *)
+				   TARGET_ATTRIBUTE_WEAK;
+extern void *__deregister_frame_info (const void *)
+				      TARGET_ATTRIBUTE_WEAK;
+extern void _Jv_RegisterClasses (const void *) TARGET_ATTRIBUTE_WEAK;
+
+#if defined(HAVE_LD_RO_RW_SECTION_MIXING)
+# define EH_FRAME_SECTION_CONST const
+#else
+# define EH_FRAME_SECTION_CONST
+#endif
+
+/* Stick a label at the beginning of the frame unwind info so we can
+   register/deregister it with the exception handling library code.  */
+#if !__USING_SJLJ_EXCEPTIONS__
+static EH_FRAME_SECTION_CONST char __EH_FRAME_BEGIN__[]
+  __attribute__((section(EH_FRAME_SECTION_NAME), aligned(4)))
+  = { };
+
+static struct object obj;
+#endif
+
+#if TARGET_USE_JCR_SECTION
+static void *__JCR_LIST__[]
+  __attribute__ ((unused, section(JCR_SECTION_NAME),
aligned(sizeof(void*))))
+  = { };
+#endif
+
+/* Pull in references from libgcc.a(unwind-dw2-fde.o) in the
+   startfile. These are referencd by a ctor and dtor in crtend.o.  */
+extern void __do_register_frame (void);
+extern void __do_deregister_frame (void);
+
+void
+__do_register_frame (void)
+{
+#if !__USING_SJLJ_EXCEPTIONS__
+/* Weak undefined symbols won't be pulled in from dlls; hence
+   we first test if the dll is already loaded and, if so,
+   get the symbol's address at run-time.  If the dll is not loaded,
+   fallback to weak linkage to static archive.  */
+
+  void (*register_frame_fn) (const void *, struct object *);
+  HANDLE h = GetModuleHandle (LIBGCC_SONAME);
+  if (h)
+    register_frame_fn = (void (*) (const void *, struct object *))
+			GetProcAddress (h, "__register_frame_info");
+  else 
+    register_frame_fn = &__register_frame_info;
+  if (register_frame_fn)
+     register_frame_fn (__EH_FRAME_BEGIN__, &obj);
+#endif
+
+#if TARGET_USE_JCR_SECTION
+  if (__JCR_LIST__[0])
+    {
+      void (*register_class_fn) (const void *)
+      HANDLE h = GetModuleHandle (LIBGCJ_SONAME);
+      if (h)
+	register_class_fn = (void (*) (const void *))
+			     GetProcAddress (h, "_Jv_RegisterClasses");
+      else
+	register_class_fn = &_Jv_RegisterClasses;
+
+      if (register_class_fn)
+	register_class_fn (__JCR_LIST__);
+    }
+#endif
+}
+
+void
+__do_deregister_frame (void)
+{
+#if !__USING_SJLJ_EXCEPTIONS__
+  void *  (*deregister_frame_fn) (const void *);
+  HANDLE h = GetModuleHandle (LIBGCC_SONAME);
+  if (h)
+    deregister_frame_fn = (void* (*) (const void *))
+			  GetProcAddress (h, "__deregister_frame_info");
+  else 
+    deregister_frame_fn = &__deregister_frame_info;
+  if (deregister_frame_fn)
+     deregister_frame_fn (__EH_FRAME_BEGIN__);
+#endif
+}
--- /dev/null	2006-12-03 19:54:27.687500000 +1300
+++ gcc/config/i386/cygming-crtend.c.	2006-11-29 17:33:45.515625000
+1300
@@ -0,0 +1,89 @@
+/* crtend object for windows32 targets.
+   Copyright (C) 2006  Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file.  (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+/* Target machine header files require this define. */
+#define IN_LIBGCC2
+
+/* auto-host.h is needed by cygming.h for HAVE_GAS_WEAK and here
+   for HAVE_LD_RO_RW_SECTION_MIXING.  */  
+#include "auto-host.h"
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "unwind-dw2-fde.h"
+
+#if defined(HAVE_LD_RO_RW_SECTION_MIXING)
+# define EH_FRAME_SECTION_CONST const
+#else
+# define EH_FRAME_SECTION_CONST
+#endif
+
+#if !__USING_SJLJ_EXCEPTIONS__
+/* Terminate the frame unwind info section with a 0 as a sentinel;
+   this would be the 'length' field in a real FDE.  */
+
+static EH_FRAME_SECTION_CONST int __FRAME_END__[]
+  __attribute__ ((unused,  section(EH_FRAME_SECTION_NAME),
+		  aligned(4)))
+  = { 0 };
+#endif
+
+#if TARGET_USE_JCR_SECTION
+/* Null terminate the .jcr section array.  */
+static void *__JCR_END__[1] 
+   __attribute__ ((unused, section(JCR_SECTION_NAME),
+		   aligned(sizeof(void *))))
+   = { 0 };
+#endif
+
+
+/*
+extern void __do_register_frame (void); 
+extern void __do_deregister_frame (void);
+*/
+
+
+/* Register the eh_frame. This has to be the first .ctor to  be invoked
+   so we put its address in the .ctor section of the last object and
+   give it a high priority (ld uses strcmp to sort sections by name).
+   The definition is in crtbegin.c since we need to pull in.
+   libgcc.a __register_frame_info. 
+   Likewise for frame deregistration on exit from app or dll.  */
+
+__asm__(
+  ".section\t.ctors.zzzzz ,\"w\"\n\t"
+  ".align 4\n\t"
+   ".long\t___do_register_frame");
+
+__asm__(
+  ".section\t.dtors.zzzzz ,\"w\"\n\t"
+  ".align 4\n\t"
+   ".long\t___do_deregister_frame ");
+



More information about the Gcc-patches mailing list