This is the mail archive of the
cygwin-developers
mailing list for the Cygwin project.
Re: CFA: pseudo-reloc v2
- From: Charles Wilson <cygwin at cwilson dot fastmail dot fm>
- To: cygwin-developers at cygwin dot com
- Date: Mon, 05 Oct 2009 15:04:53 -0400
- Subject: Re: CFA: pseudo-reloc v2
So here's another approach. It relies on the
cygwin_terminate_process/cygwin_exit_process wrapper functions, posted
here: http://cygwin.com/ml/cygwin-patches/2009-q4/msg00028.html
Attached are two patches. The first contains modifications to the cygwin
DLL.
2009-10-04 Charles Wilson <...>
* ntdll.h: Add custom NTSTATUS value for pseudo-reloc
errors STATUS_ILLEGAL_DLL_PSEUDO_RELOCATION.
* pinfo.cc (status_exit): Map custom pseudo-reloc
error value STATUS_ILLEGAL_DLL_PSEUDO_RELOCATION to 127.
* sigproc.cc (child_info::proc_retry): Return exit code when
STATUS_ILLEGAL_DLL_PSEUDO_RELOCATION.
The second shows the differences between winsup/mingw/pseudo-reloc.c and
winsup/cygwin/lib/pseudo-reloc.c -- that is, it assumes you've already
copied the mingw version over. When I post this to cygwin-patches, I'll
make a traditional diff against CVS HEAD.
This one differs from previous iterations:
1) it uses WriteFile instead of WriteConsoleW.
2) it gets the module name and path itself, and prints error
messages in a form similar to that used already in
pinfo::status_exit() for STATUS_DLL_NOT_FOUND.
3) Nor more need for write_console code copied from cygwin proper,
which is good because that was questionable, license-wise.
Anyway, when combined with the 'TerminateProcess' wrapper patch, this
version works in every test I've thrown at it.
--
Chuck
Index: ntdll.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/ntdll.h,v
retrieving revision 1.94
diff -u -p -r1.94 ntdll.h
--- ntdll.h 14 Jul 2009 17:37:42 -0000 1.94
+++ ntdll.h 5 Oct 2009 16:58:49 -0000
@@ -46,6 +46,8 @@
#define STATUS_ENTRYPOINT_NOT_FOUND ((NTSTATUS) 0xc0000139)
#define STATUS_BAD_DLL_ENTRYPOINT ((NTSTATUS) 0xc0000251)
#define STATUS_ILLEGAL_DLL_RELOCATION ((NTSTATUS) 0xc0000269)
+/* custom status code: */
+#define STATUS_ILLEGAL_DLL_PSEUDO_RELOCATION ((NTSTATUS) 0xe0000269)
#define PDI_MODULES 0x01
#define PDI_HEAPS 0x04
Index: pinfo.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/pinfo.cc,v
retrieving revision 1.253
diff -u -p -r1.253 pinfo.cc
--- pinfo.cc 12 Jul 2009 21:15:47 -0000 1.253
+++ pinfo.cc 5 Oct 2009 16:58:49 -0000
@@ -128,6 +128,10 @@ status_exit (DWORD x)
x = 127;
}
break;
+ case STATUS_ILLEGAL_DLL_PSEUDO_RELOCATION: /* custom error value */
+ /* We've already printed the error message in pseudo-reloc.c */
+ x = 127;
+ break;
default:
x = 127;
}
Index: sigproc.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/sigproc.cc,v
retrieving revision 1.317
diff -u -p -r1.317 sigproc.cc
--- sigproc.cc 2 Aug 2009 21:38:40 -0000 1.317
+++ sigproc.cc 5 Oct 2009 16:58:49 -0000
@@ -923,6 +923,8 @@ child_info::proc_retry (HANDLE h)
break;
case STATUS_DLL_NOT_FOUND:
return exit_code;
+ case STATUS_ILLEGAL_DLL_PSEUDO_RELOCATION: /* pseudo-reloc.c specific */
+ return exit_code;
case STATUS_CONTROL_C_EXIT:
if (saw_ctrl_c ())
return EXITCODE_OK;
--- winsup/mingw/pseudo-reloc.c 2009-03-17 09:18:08.463300000 -0400
+++ winsup/cygwin/lib/pseudo-reloc.c 2009-10-05 14:07:10.268200000 -0400
@@ -20,6 +20,19 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
+
+#if defined(__CYGWIN__)
+#include <wchar.h>
+#include <ntdef.h>
+#include <stdarg.h>
+#include <sys/cygwin.h>
+/* copied from winsup.h */
+# define NO_COPY __attribute__((nocommon)) __attribute__((section(".data_cygwin_nocopy")))
+/* custom status code: */
+#define STATUS_ILLEGAL_DLL_PSEUDO_RELOCATION ((NTSTATUS) 0xe0000269)
+#else
+# define NO_COPY
+#endif
extern char __RUNTIME_PSEUDO_RELOC_LIST__;
extern char __RUNTIME_PSEUDO_RELOC_LIST_END__;
@@ -42,6 +55,51 @@
DWORD version;
} runtime_pseudo_reloc_v2;
+#if defined(__CYGWIN__)
+#define SHORT_MSG_BUF_SZ 128
+static BOOL
+__print_reloc_error (const char *fmt, ...)
+{
+ char buf[SHORT_MSG_BUF_SZ];
+ wchar_t module[MAX_PATH];
+ char * posix_module = NULL;
+ BOOL rVal = FALSE;
+ static const char * UNKNOWN_MODULE = "<unknown module>: ";
+ DWORD len;
+ DWORD done;
+ va_list args;
+ HANDLE errh = GetStdHandle (STD_ERROR_HANDLE);
+ ssize_t modulelen = GetModuleFileNameW (NULL, module, sizeof (module));
+
+ if (errh == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ if (modulelen > 0)
+ posix_module = cygwin_create_path (CCP_WIN_W_TO_POSIX, module);
+
+ va_start (args, fmt);
+ len = (DWORD) vsnprintf (buf, SHORT_MSG_BUF_SZ, fmt, args);
+ va_end (args);
+ buf[SHORT_MSG_BUF_SZ-1] = '\0'; /* paranoia */
+
+ if (posix_module)
+ {
+ rVal = WriteFile (errh, (PCVOID)posix_module,
+ strlen(posix_module), &done, NULL) &&
+ WriteFile (errh, (PCVOID)": ", 2, &done, NULL) &&
+ WriteFile (errh, (PCVOID)buf, len, &done, NULL);
+ free (posix_module);
+ }
+ else
+ {
+ rVal = WriteFile (errh, (PCVOID)UNKNOWN_MODULE,
+ sizeof(UNKNOWN_MODULE), &done, NULL) &&
+ WriteFile (errh, (PCVOID)buf, len, &done, NULL);
+ }
+ return rVal;
+}
+#endif /* __CYGWIN__ */
+
static void
__write_memory (void *addr,const void *src,size_t len)
{
@@ -49,7 +107,20 @@
DWORD oldprot;
if (!len)
return;
+
+#if defined(__CYGWIN__)
+ if (!VirtualQuery (addr, &b, sizeof(b)))
+ {
+ __print_reloc_error (
+ "error while loading shared libraries: bad address specified 0x%08x.\n",
+ addr);
+ cygwin_terminate_process (GetCurrentProcess(),
+ STATUS_ILLEGAL_DLL_PSEUDO_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 +166,18 @@
/* Check if this is a known version. */
if (v2_hdr->version != RP_VERSION_V2)
{
-#ifdef DEBUG
+#if defined(__CYGWIN__)
+ __print_reloc_error (
+ "error while loading shared libraries: invalid pseudo_reloc version %d.\n",
+ (int) v2_hdr->version);
+ cygwin_terminate_process (GetCurrentProcess(),
+ STATUS_ILLEGAL_DLL_PSEUDO_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 +218,15 @@
default:
reldata=0;
#ifdef DEBUG
+# if defined(__CYGWIN__)
+ __print_reloc_error (
+ "error while loading shared libraries: unknown pseudo_reloc bit size %d.\n",
+ (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 +255,7 @@
void
_pei386_runtime_relocator ()
{
- static int was_init = 0;
+ static NO_COPY int was_init = 0;
if (was_init)
return;
++was_init;