Index: crtstuff.c =================================================================== --- crtstuff.c (revision 122101) +++ crtstuff.c (working copy) @@ -140,7 +146,7 @@ extern void __do_global_ctors_1 (void); /* Likewise for _Jv_RegisterClasses. */ -extern void _Jv_RegisterClasses (void *) TARGET_ATTRIBUTE_WEAK; +extern void _Jv_RegisterClasses (const void *) TARGET_ATTRIBUTE_WEAK; #ifdef OBJECT_FORMAT_ELF @@ -441,6 +447,78 @@ } #endif /* USE_EH_FRAME_REGISTRY || JCR_SECTION_NAME */ +#elif (defined __CYGWIN__ || defined __MINGW32__) +#define WIN32_LEAN_AND_MEAN +#include + +#ifndef LIBGCC_SONAME +#define LIBGCC_SONAME "libgcc_s.dll" +#endif + +#ifndef LIBGCJ_SONAME +#define LIBGCJ_SONAME "libgcj_s.dll" +#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 *); + static struct object obj; + + 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 +} + #else /* ! INIT_SECTION_ASM_OP && ! HAS_INIT_SECTION */ #error "What are you doing with crtstuff.c, then?" #endif @@ -579,6 +657,26 @@ (*p) (); } + +#elif (defined __CYGWIN__ || defined __MINGW32__) + +/* 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 __[de]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 "); + #else /* ! INIT_SECTION_ASM_OP && ! HAS_INIT_SECTION */ #error "What are you doing with crtstuff.c, then?" #endif Index: config.gcc =================================================================== --- config.gcc (revision 122101) +++ config.gcc (working copy) @@ -1326,13 +1326,14 @@ i[34567]86-*-pe | i[34567]86-*-cygwin*) tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/cygming.h i386/cygwin.h" xm_file=i386/xm-cygwin.h - tmake_file="i386/t-cygwin i386/t-cygming" + tmake_file="i386/t-cygwin i386/t-cygming i386/t-crtfm" target_gtfiles="\$(srcdir)/config/i386/winnt.c" extra_options="${extra_options} i386/cygming.opt" extra_objs="winnt.o winnt-stubs.o" 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 @@ -1340,11 +1341,12 @@ i[34567]86-*-mingw32*) tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/cygming.h i386/mingw32.h" xm_file=i386/xm-mingw32.h - tmake_file="i386/t-cygming i386/t-mingw32" + tmake_file="i386/t-cygming i386/t-mingw32 i386/t-crtfm" target_gtfiles="\$(srcdir)/config/i386/winnt.c" 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: config/i386/cygming.h =================================================================== --- config/i386/cygming.h (revision 122101) +++ config/i386/cygming.h (working copy) @@ -21,18 +21,27 @@ the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + #define DBX_DEBUGGING_INFO 1 #define SDB_DEBUGGING_INFO 1 + #undef PREFERRED_DEBUGGING_TYPE -#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG #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]) +#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 @@ -45,6 +54,10 @@ fputs ("\t.secrel32\t", FILE); \ assemble_name (FILE, LABEL); \ } while (0) + +#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG +#else +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG #endif #define TARGET_EXECUTABLE_SUFFIX ".exe" @@ -266,7 +279,10 @@ /* 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 +#define DWARF2_UNWIND_INFO 1 +/* Support unwinding through signals and SEH. */ +#define MD_UNWIND_SUPPORT "config/i386/w32-unwind.h" + /* Don't assume anything about the header files. */ #define NO_IMPLICIT_EXTERN_C @@ -364,10 +380,10 @@ while (0) #endif /* HAVE_GAS_WEAK */ -/* FIXME: SUPPORTS_WEAK && TARGET_HAVE_NAMED_SECTIONS is true, +/* SUPPORTS_WEAK && TARGET_HAVE_NAMED_SECTIONS is true, but for .jcr section to work we also need crtbegin and crtend objects. */ -#define TARGET_USE_JCR_SECTION 0 +#define TARGET_USE_JCR_SECTION 1 /* Decide whether it is safe to use a local alias for a virtual function when constructing thunks. */ Index: config/i386/cygwin.h =================================================================== --- config/i386/cygwin.h (revision 122101) +++ 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: config/i386/t-mingw32 =================================================================== --- config/i386/t-mingw32 (revision 122101) +++ config/i386/t-mingw32 (working copy) @@ -1,2 +1,18 @@ # Match SYSTEM_INCLUDE_DIR NATIVE_SYSTEM_HEADER_DIR = /mingw/include + +#Build libgcc.as a dll +shared-libgcc: libgcc_s.a libgcc_s.dll +libgcc_s.a libgcc_s.dll: libgcc.a + cp -f libgcc.a libgcc_t.a + $(AR) -d libgcc_t.a _chkstk.o _ctors.o + dlltool --output-def libgcc.def --export-all libgcc_t.a + $(GCC_FOR_TARGET) -shared -o libgcc.dll -Wl,--out-implib,libgcc_s.a libgcc.def libgcc_t.a + $(AR) -r libgcc_s.a libgcc/_chkstk.o libgcc/_ctors.o + rm -f libgcc_t.a _chkstk.o _ctors.o libgcc.def + +install-shared-libgcc: installdirs shared-libgcc + $(INSTALL_DATA) libgcc_s.a $(DESTDIR)$(libsubdir)/ + chmod 644 $(DESTDIR)$(libsubdir)/libgcc_s.a + $(INSTALL_PROGRAM) libgcc.dll $(DESTDIR)$(bindir)/ + chmod 644 $(DESTDIR)$(bindir)/libgcc_s.dll Index: config/i386/mingw32.h =================================================================== --- config/i386/mingw32.h (revision 122101) +++ config/i386/mingw32.h (working copy) @@ -1,6 +1,6 @@ /* Operating system specific defines to be used when targeting GCC for hosting on Windows32, using GNU tools and the Windows32 API Library. - Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 + Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007 Free Software Foundation, Inc. This file is part of GCC. @@ -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 *** /dev/null Wed Feb 21 22:18:48 2007 --- config/i386/w32-unwind.h Wed Feb 21 22:10:02 2007 *************** *** 0 **** --- 1,215 ---- + /* Definitions for Dwarf2 EH unwind support for Windows32 targets + Copyright (C) 2005 + Free Software Foundation, Inc. + Contributed by Pascal Obry + + 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 with other programs, and to distribute + those programs 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 another program.) + + 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. */ + + /* This file implements the md_fallback_frame_state_for routine for Windows, + triggered when the GCC table based unwinding process hits a frame for which + no unwind info has been registered. This typically occurs when raising an + exception from a signal handler, because the handler is actually called + from the OS kernel. + + The basic idea is to detect that we are indeed trying to unwind past a + signal handler and to fill out the GCC internal unwinding structures for + the OS kernel frame as if it had been directly called from the interrupted + context. + + This is all assuming that the code to set the handler asked the kernel to + pass a pointer to such context information. + + There is three main parts. + + 1) The first thing to do is to check if we are in a signal context. If not + we can just return as there is nothing to do. We are probably on some + foreign code for which no unwind frame can be found. If this is a call + from the Windows signal handler, then: + + 2) We must get the signal context information. + + * With the standard exception filter: + + This is on Windows pointed to by an EXCEPTION_POINTERS. We know that the + signal handle will call an UnhandledExceptionFilter with this + parameter. The spec for this routine is: + + LONG WINAPI UnhandledExceptionFilter(struct _EXCEPTION_POINTERS*); + + So the pointer to struct _EXCEPTION_POINTERS must be somewhere on the + stack. + + This was found experimentally to always be at offset 0 of the context + frame in all cases handled by this implementation. + + * With the SEH exception handler: + + In this case the signal context is directly on the stack as the SEH + exception handler has the following prototype: + + DWORD + SEH_error_handler (PEXCEPTION_RECORD ExceptionRecord, + PVOID EstablisherFrame, + PCONTEXT ContextRecord, + PVOID DispatcherContext) + + This was found experimentally to always be at offset 56 of the context + frame in all cases handled by this implementation. + + 3) When we have the signal context we just have to save some registers and + set the return address based on the program counter (Eip). + + Note that this implementation follows closely the same principles as the + GNU/Linux and OSF ones. */ + + #define WIN32_MEAN_AND_LEAN + #include + /* Patterns found experimentally to be on a Windows signal handler */ + + /* In a standard exception filter */ + + #define SIG_PAT1 \ + (pc_[-2] == 0xff && pc_[-1] == 0xd0 /* call %eax */ \ + && pc_[0] == 0x83 && pc_[1] == 0xf8) /* cmp 0xdepl,%eax */ + + #define SIG_PAT2 \ + (pc_[-5] == 0xe8 && pc_[-4] == 0x68 /* call (depl16) */ \ + && pc_[0] == 0xc3) /* ret */ + + /* In a Win32 SEH handler */ + + #define SIG_SEH1 \ + (pc_[-5] == 0xe8 /* call addr */ \ + && pc_[0] == 0x83 && pc_[1] == 0xc4 /* add 0xval,%esp */ \ + && pc_[3] == 0xb8) /* mov 0xval,%eax */ + + #define SIG_SEH2 \ + (pc_[-5] == 0x8b && pc_[-4] == 0x4d /* mov depl(%ebp),%ecx */ \ + && pc_[0] == 0x64 && pc_[1] == 0x8b) /* mov %fs:(0), */ \ + + /* In the GCC alloca (stack probing) */ + + #define SIG_ALLOCA \ + (pc_[-1] == 0x83 /* orl $0x0,(%ecx) */ \ + && pc_[0] == 0x9 && pc_[1] == 0 \ + && pc_[2] == 0x2d && pc_[3] == 0 /* subl $0x1000,%eax */ \ + && pc_[4] == 0x10 && pc_[5] == 0) + + + #define MD_FALLBACK_FRAME_STATE_FOR i386_w32_fallback_frame_state + + static _Unwind_Reason_Code + i386_w32_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) + + { + void * ctx_ra_ = (void *)(context->ra); /* return address */ + void * ctx_cfa_ = (void *)(context->cfa); /* context frame address */ + unsigned char * pc_ = (unsigned char *) ctx_ra_; + + /* In the test below we look for two specific patterns found + experimentally to be in the Windows signal handler. */ + + if (SIG_PAT1 || SIG_PAT2 || SIG_SEH1 || SIG_SEH2) + { + PEXCEPTION_POINTERS weinfo_; + PCONTEXT proc_ctx_; + long new_cfa_; + + if (SIG_SEH1) + proc_ctx_ = (PCONTEXT) (*(int*)(ctx_cfa_ + 56)); + else if (SIG_SEH2) + proc_ctx_ = (PCONTEXT) (*(int*)(ctx_cfa_ + 8)); + else + { + weinfo_ = (PEXCEPTION_POINTERS) (*(int*)ctx_cfa_); + proc_ctx_ = weinfo_->ContextRecord; + } + + /* The new context frame address is the stack pointer. */ + + new_cfa_ = proc_ctx_->Esp; + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = __builtin_dwarf_sp_column(); + fs->regs.cfa_offset = new_cfa_ - (long) ctx_cfa_; + + /* Save some registers. */ + + fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.reg[0].loc.offset = (long)&proc_ctx_->Eax - new_cfa_; + fs->regs.reg[3].how = REG_SAVED_OFFSET; + fs->regs.reg[3].loc.offset = (long)&proc_ctx_->Ebx - new_cfa_; + fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.reg[1].loc.offset = (long)&proc_ctx_->Ecx - new_cfa_; + fs->regs.reg[2].how = REG_SAVED_OFFSET; + fs->regs.reg[2].loc.offset = (long)&proc_ctx_->Edx - new_cfa_; + fs->regs.reg[6].how = REG_SAVED_OFFSET; + fs->regs.reg[6].loc.offset = (long)&proc_ctx_->Esi - new_cfa_; + fs->regs.reg[7].how = REG_SAVED_OFFSET; + fs->regs.reg[7].loc.offset = (long)&proc_ctx_->Edi - new_cfa_; + fs->regs.reg[9].how = REG_SAVED_OFFSET; + fs->regs.reg[9].loc.offset = (long)&proc_ctx_->Eip - new_cfa_; + fs->regs.reg[4].how = REG_SAVED_OFFSET; + fs->regs.reg[4].loc.offset = (long)&proc_ctx_->Ebp - new_cfa_; + + /* Set the return address to Eip + 1. As we can be called multiple + times we use another register for this. */ + + proc_ctx_->Dr0 = proc_ctx_->Eip + 1; + fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.reg[8].loc.offset = (long)&proc_ctx_->Dr0 - new_cfa_; + fs->retaddr_column = 8; + return _URC_NO_REASON; + } + + /* Unwinding through _alloca, propagating from a trap triggered by + one of it's probes prior to the real SP adjustment. The only + operations of interest performed is "pushl %ecx", followed by + ecx clobbering. */ + + else if (SIG_ALLOCA) + { + /* Only one push between entry in _alloca and the probe trap. */ + long new_cfa_ = (long) ctx_cfa_ + 4; + + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = __builtin_dwarf_sp_column(); + fs->regs.cfa_offset = new_cfa_ - (long) ctx_cfa_; + + /* The saved value of %ecx is at CFA - 4 */ + fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.reg[1].loc.offset = -4; + + /* and what is stored at the CFA is the return address. */ + fs->retaddr_column = 8; + fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.reg[8].loc.offset = 0; + + return _URC_NO_REASON; + } + else + return _URC_END_OF_STACK;