--- winsup/mingw/pseudo-reloc.c 2009-03-17 09:18:08.463300000 -0400 +++ winsup/cygwin/lib/pseudo-reloc.c 2009-10-05 01:00:31.362000000 -0400 @@ -20,6 +20,17 @@ #include #include #include + +#if defined(__CYGWIN__) +#include +#include +#include +/* copied from winsup.h */ +# define NO_COPY __attribute__((nocommon)) __attribute__((section(".data_cygwin_nocopy"))) +#define STATUS_ILLEGAL_DLL_RELOCATION ((NTSTATUS) 0xc0000269) +#else +# define NO_COPY +#endif extern char __RUNTIME_PSEUDO_RELOC_LIST__; extern char __RUNTIME_PSEUDO_RELOC_LIST_END__; @@ -42,6 +53,51 @@ DWORD version; } runtime_pseudo_reloc_v2; +#if defined(__CYGWIN__) +#define MAX_WRITE_CHARS 16384 + +/* This function is adapted from cygwin fhandler_console.cc, so + * I'm not sure it can be included in this "not copyrighted" file + */ +static int +__write_console (HANDLE h, PWCHAR buf, DWORD len, DWORD *done) +{ + while (len > 0) + { + DWORD nbytes = len > MAX_WRITE_CHARS ? MAX_WRITE_CHARS : len; + if (!WriteConsoleW (h, buf, nbytes, done, 0)) + { + /* don't bother with errno here; no-one will check it */ + return FALSE; + } + len -= *done; + buf += *done; + } + return TRUE; +} + +#define SHORT_MSG_BUF_SZ 64 +static int +__print_reloc_error (const wchar_t *fmt, ...) +{ + WCHAR buf[SHORT_MSG_BUF_SZ]; + DWORD len; + DWORD done; + va_list args; + HANDLE e = GetStdHandle (STD_ERROR_HANDLE); + + if (e == INVALID_HANDLE_VALUE) + return 0; + + va_start (args, fmt); + len = (DWORD) vswprintf (buf, SHORT_MSG_BUF_SZ, fmt, args); + va_end (args); + + buf[SHORT_MSG_BUF_SZ-1] = L'\0'; /* paranoia */ + return __write_console (e, buf, len, &done); +} +#endif /* __CYGWIN__ */ + static void __write_memory (void *addr,const void *src,size_t len) { @@ -49,7 +105,19 @@ DWORD oldprot; if (!len) return; + +#if defined(__CYGWIN__) + if (!VirtualQuery (addr, &b, sizeof(b))) + { + __print_reloc_error ( + L"Relocation error: bad address specified 0x%08x.", + addr); + TerminateProcess (GetCurrentProcess(), STATUS_ILLEGAL_DLL_RELOCATION); + } +#else assert (VirtualQuery (addr, &b, sizeof(b))); +#endif + /* Temporarily allow write access to read-only protected memory. */ if (b.Protect != PAGE_EXECUTE_READWRITE && b.Protect != PAGE_READWRITE) VirtualProtect (b.BaseAddress, b.RegionSize, PAGE_EXECUTE_READWRITE, @@ -95,10 +163,17 @@ /* Check if this is a known version. */ if (v2_hdr->version != RP_VERSION_V2) { -#ifdef DEBUG +#if defined(__CYGWIN__) + __print_reloc_error ( + L"Relocation error: invalid pseudo_reloc version %d.", + (int) v2_hdr->version); + TerminateProcess (GetCurrentProcess(), STATUS_ILLEGAL_DLL_RELOCATION); +#else +# if defined(DEBUG) fprintf (stderr, "internal mingw runtime error:" "psuedo_reloc version %d is unknown to this runtime.\n", (int) v2_hdr->version); +# endif #endif return; } @@ -139,9 +214,15 @@ default: reldata=0; #ifdef DEBUG +# if defined(__CYGWIN__) + __print_reloc_error ( + L"Relocation error: unknown pseudo_reloc bit size %d.", + (int) (r->flags & 0xff)); +# else fprintf(stderr, "internal mingw runtime error: " "unknown pseudo_reloc bit size %d\n", (int) (r->flags & 0xff)); +# endif #endif break; } @@ -170,7 +251,7 @@ void _pei386_runtime_relocator () { - static int was_init = 0; + static NO_COPY int was_init = 0; if (was_init) return; ++was_init;