[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