Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog35
-rw-r--r--winsup/cygwin/Makefile.in16
-rw-r--r--winsup/cygwin/dcrt0.cc12
-rw-r--r--winsup/cygwin/dll_init.cc9
-rw-r--r--winsup/cygwin/globals.cc11
-rw-r--r--winsup/cygwin/include/cygwin/version.h11
-rw-r--r--winsup/cygwin/include/sys/cygwin.h9
-rw-r--r--winsup/cygwin/lib/_cygwin_crt0_common.cc12
-rw-r--r--winsup/cygwin/lib/pseudo-reloc-dummy.c10
-rw-r--r--winsup/cygwin/lib/pseudo-reloc.c367
-rw-r--r--winsup/cygwin/pseudo-reloc.cc160
-rw-r--r--winsup/cygwin/winsup.h2
12 files changed, 172 insertions, 482 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index ec2a931ce..a2d40a9f6 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,38 @@
+2010-05-07 Christopher Faylor <me+cygwin@cgf.cx>
+
+ * Makefile.in (DLL_OFILES): Add pseudo-reloc.o.
+ * dcrt0.cc (child_info_fork::handle_fork): Call
+ _pei386_runtime_relocator here.
+ (dll_crt0_1): Ditto for non-fork case.
+ * dll_init.cc (dll::init): Complain more in comment. Clean up
+ slightly.
+ (dll_dllcrt0_1): Call _pei386_runtime_relocator when we know we have
+ a filled-in per_process structure.
+ * globals.cc (__cygwin_user_data): Accommodate new fields for
+ _pei386_runtime_relocator.
+ * pseudo-reloc.cc: New file adapted from old lib/pseudo-reloc.c.
+ Include winsup.h directly. Collapse #ifdef __CYGWIN__ into one block.
+ Perform minor whitespace code reformatting.
+ (__report_error): Use small_printf to output error.
+ (_pei386_runtime_relocator): Conditionalize for cygwin to take
+ per_process pointer parameter.
+ * winsup.h (_pei386_runtime_relocator): Declare.
+ * include/cygwin/version.h
+ (CYGWIN_VERSION_PER_PROCESS_API_VERSION_COMBINED): New macro.
+ (CYGWIN_VERSION_USER_API_VERSION_COMBINED): Use above macro.
+ (CYGWIN_VERSION_USE_PSEUDO_RELOC_IN_DLL): New macro.
+ (CYGWIN_VERSION_API_MINOR): Bump to 227.
+ * include/sys/cygwin.h: Remove obsolete comment.
+ (per_process::unused2): Shorten.
+ (per_process::pseudo_reloc_start): New field.
+ (per_process::pseudo_reloc_end): Ditto.
+ (per_process::image_base): Ditto.
+ * lib/_cygwin_crt0_common.cc: Declare pseudo runtime externs needed for
+ per_process structure.
+ (_cygwin_crt0_common): Fill in pseudo_reloc runtime constants.
+ * lib/pseudo-reloc-dummy.c: New file. Dummy function to satisify ld.
+ * lib/pseudo-reloc.c: Delete.
+
2010-05-07 Corinna Vinschen <corinna@vinschen.de>
* fhandler_tty.cc (fhandler_tty_slave::init): Disable grabbing
diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in
index 0499a5cc7..3f4c0044f 100644
--- a/winsup/cygwin/Makefile.in
+++ b/winsup/cygwin/Makefile.in
@@ -149,14 +149,14 @@ DLL_OFILES:=assert.o autoload.o bsdlib.o ctype.o cxx.o cygheap.o cygthread.o \
init.o ioctl.o ipc.o kernel32.o libstdcxx_wrapper.o localtime.o lsearch.o \
malloc_wrapper.o minires-os-if.o minires.o miscfuncs.o mktemp.o mmap.o msg.o \
mount.o net.o netdb.o nfs.o nftw.o nlsfuncs.o ntea.o passwd.o path.o \
- pinfo.o pipe.o poll.o posix_ipc.o pthread.o random.o regcomp.o \
- regerror.o regexec.o regfree.o registry.o resource.o rexec.o rcmd.o \
- scandir.o sched.o sec_acl.o sec_auth.o sec_helper.o security.o select.o \
- sem.o setlsapwd.o shared.o shm.o sigfe.o signal.o sigproc.o smallprint.o \
- spawn.o strace.o strfmon.o strfuncs.o strptime.o strsep.o strsig.o sync.o \
- syscalls.o sysconf.o syslog.o termios.o thread.o timer.o times.o \
- tls_pbuf.o tty.o uinfo.o uname.o wait.o wincap.o window.o winf.o \
- xsique.o \
+ pinfo.o pipe.o poll.o posix_ipc.o pseudo-reloc.o pthread.o random.o \
+ regcomp.o regerror.o regexec.o regfree.o registry.o resource.o rexec.o \
+ rcmd.o scandir.o sched.o sec_acl.o sec_auth.o sec_helper.o security.o \
+ select.o sem.o setlsapwd.o shared.o shm.o sigfe.o signal.o sigproc.o \
+ smallprint.o spawn.o strace.o strfmon.o strfuncs.o strptime.o strsep.o \
+ strsig.o sync.o syscalls.o sysconf.o syslog.o termios.o thread.o \
+ timer.o times.o tls_pbuf.o tty.o uinfo.o uname.o wait.o wincap.o \
+ window.o winf.o xsique.o \
$(EXTRA_DLL_OFILES) $(EXTRA_OFILES) $(MALLOC_OFILES) $(MT_SAFE_OBJECTS)
EXCLUDE_STATIC_OFILES:=$(addprefix --exclude=,\
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index 76b89517b..d32ff22c9 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -41,7 +41,6 @@ details. */
#define PREMAIN_LEN (sizeof (user_data->premain) / sizeof (user_data->premain[0]))
-
extern "C" void cygwin_exit (int) __attribute__ ((noreturn));
extern "C" void __sinit (_reent *);
@@ -592,6 +591,12 @@ child_info_fork::handle_fork ()
"dll bss", dll_bss_start, dll_bss_end,
"user heap", cygheap->user_heap.base, cygheap->user_heap.ptr,
NULL);
+
+ /* Do the relocations here. These will actually likely be overwritten by the
+ below child_copy but we do them here in case there is a read-only section
+ which does not get copied by fork. */
+ _pei386_runtime_relocator (user_data);
+
/* step 2 now that the dll has its heap filled in, we can fill in the
user's data and bss since user_data is now filled out. */
child_copy (parent, false,
@@ -794,7 +799,10 @@ dll_crt0_1 (void *)
/* Initialize pthread mainthread when not forked and it is safe to call new,
otherwise it is reinitalized in fixup_after_fork */
if (!in_forkee)
- pthread::init_mainthread ();
+ {
+ pthread::init_mainthread ();
+ _pei386_runtime_relocator (user_data);
+ }
#ifdef DEBUGGING
strace.microseconds ();
diff --git a/winsup/cygwin/dll_init.cc b/winsup/cygwin/dll_init.cc
index c2b141362..ec1132434 100644
--- a/winsup/cygwin/dll_init.cc
+++ b/winsup/cygwin/dll_init.cc
@@ -75,7 +75,7 @@ dll::init ()
{
int ret = 1;
- /* Why didn't we just import this variable? */
+ /* This should be a no-op. Why didn't we just import this variable? */
*(p.envptr) = __cygwin_environ;
/* Don't run constructors or the "main" if we've forked. */
@@ -86,7 +86,7 @@ dll::init ()
/* entry point of dll (use main of per_process with null args...) */
if (p.main)
- ret = (*(p.main)) (0, 0, 0);
+ ret = p.main (0, 0, 0);
}
return ret;
@@ -333,7 +333,10 @@ dll_dllcrt0_1 (VOID *x)
if (p == NULL)
p = &__cygwin_user_data;
else
- *(p->impure_ptr_ptr) = __cygwin_user_data.impure_ptr;
+ {
+ *(p->impure_ptr_ptr) = __cygwin_user_data.impure_ptr;
+ _pei386_runtime_relocator (p);
+ }
bool linked = !in_forkee && !cygwin_finished_initializing;
diff --git a/winsup/cygwin/globals.cc b/winsup/cygwin/globals.cc
index 0baa96e3a..6060edcf3 100644
--- a/winsup/cygwin/globals.cc
+++ b/winsup/cygwin/globals.cc
@@ -147,12 +147,15 @@ extern "C"
/* calloc */ calloc,
/* premain */ {NULL, NULL, NULL, NULL},
/* run_ctors_p */ 0,
- /* unused */ {0, 0, 0, 0, 0, 0, 0},
+ /* unused */ {},
/* cxx_malloc */ &default_cygwin_cxx_malloc,
/* hmodule */ NULL,
- /* api_major */ CYGWIN_VERSION_API_MAJOR,
- /* api_minor */ CYGWIN_VERSION_API_MINOR,
- /* unused2 */ {0, 0, 0, 0, 0, 0},
+ /* api_major */ 0,
+ /* api_minor */ 0,
+ /* unused2 */ {},
+ /* pseudo_reloc_start */ NULL,
+ /* pseudo_reloc_end */ NULL,
+ /* image_base */ NULL,
/* threadinterface */ &_mtinterf,
/* impure_ptr */ _GLOBAL_REENT,
};
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index fb9ce136b..08ffebcf2 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -62,8 +62,11 @@ details. */
/* Every version of cygwin <= this uses an old, incorrect method
to determine signal masks. */
+#define CYGWIN_VERSION_PER_PROCESS_API_VERSION_COMBINED(u) \
+ CYGWIN_VERSION_DLL_MAKE_COMBINED ((u)->api_major, (u)->api_minor)
+
#define CYGWIN_VERSION_USER_API_VERSION_COMBINED \
- CYGWIN_VERSION_DLL_MAKE_COMBINED (user_data->api_major, user_data->api_minor)
+ CYGWIN_VERSION_PER_PROCESS_API_VERSION_COMBINED (user_data)
/* API versions <= this had a termios structure whose members were
too small to accomodate modern settings. */
@@ -98,6 +101,9 @@ details. */
#define CYGWIN_VERSION_CHECK_FOR_OLD_CTYPE \
(CYGWIN_VERSION_USER_API_VERSION_COMBINED <= 209)
+#define CYGWIN_VERSION_USE_PSEUDO_RELOC_IN_DLL(u) \
+ (CYGWIN_VERSION_PER_PROCESS_API_VERSION_COMBINED (u) >= 227)
+
#define CYGWIN_VERSION_CYGWIN_CONV 181
/* API_MAJOR 0.0: Initial version. API_MINOR changes:
@@ -380,12 +386,13 @@ details. */
224: Export xdr* functions.
225: Export __xdr* functions.
226: Export __locale_mb_cur_max.
+ 227: Add pseudo_reloc_start, pseudo_reloc_end, image_base to per_process
*/
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 226
+#define CYGWIN_VERSION_API_MINOR 227
/* There is also a compatibity version number associated with the
shared memory regions. It is incremented when incompatible
diff --git a/winsup/cygwin/include/sys/cygwin.h b/winsup/cygwin/include/sys/cygwin.h
index 425fd82fd..dcf61b081 100644
--- a/winsup/cygwin/include/sys/cygwin.h
+++ b/winsup/cygwin/include/sys/cygwin.h
@@ -244,10 +244,6 @@ struct per_process
/* For future expansion of values set by the app. */
void (*premain[4]) (int, char **, struct per_process *);
- /* The rest are *internal* to cygwin.dll.
- Those that are here because we want the child to inherit the value from
- the parent (which happens when bss is copied) are marked as such. */
-
/* non-zero of ctors have been run. Inherited from parent. */
int run_ctors_p;
@@ -262,7 +258,10 @@ struct per_process
DWORD api_minor; /* linked with */
/* For future expansion, so apps won't have to be relinked if we
add an item. */
- DWORD unused2[6];
+ DWORD unused2[3];
+ void *pseudo_reloc_start;
+ void *pseudo_reloc_end;
+ void *image_base;
#if defined (__INSIDE_CYGWIN__) && defined (__cplusplus)
MTinterface *threadinterface;
diff --git a/winsup/cygwin/lib/_cygwin_crt0_common.cc b/winsup/cygwin/lib/_cygwin_crt0_common.cc
index b8586e557..222f159e1 100644
--- a/winsup/cygwin/lib/_cygwin_crt0_common.cc
+++ b/winsup/cygwin/lib/_cygwin_crt0_common.cc
@@ -49,7 +49,11 @@ extern "C"
{
char **environ;
int _fmode;
-void _pei386_runtime_relocator ();
+void _pei386_runtime_relocator (void);
+
+extern char __RUNTIME_PSEUDO_RELOC_LIST__;
+extern char __RUNTIME_PSEUDO_RELOC_LIST_END__;
+extern char _image_base__;
struct per_process_cxx_malloc __cygwin_cxx_malloc =
{
@@ -146,7 +150,11 @@ _cygwin_crt0_common (MainFunc f, per_process *u)
u->data_end = &_data_end__;
u->bss_start = &_bss_start__;
u->bss_end = &_bss_end__;
-
+ u->pseudo_reloc_start = &__RUNTIME_PSEUDO_RELOC_LIST__;
+ u->pseudo_reloc_end = &__RUNTIME_PSEUDO_RELOC_LIST_END__;
+ u->image_base = &_image_base__;
+ /* This is actually a dummy call to force the linker to load this
+ symbol for older apps which need it. */
_pei386_runtime_relocator ();
return 1;
}
diff --git a/winsup/cygwin/lib/pseudo-reloc-dummy.c b/winsup/cygwin/lib/pseudo-reloc-dummy.c
new file mode 100644
index 000000000..0cd8c4eb4
--- /dev/null
+++ b/winsup/cygwin/lib/pseudo-reloc-dummy.c
@@ -0,0 +1,10 @@
+/* pseudo-reloc.c
+
+ Stub for older binaries.
+*/
+
+void
+_pei386_runtime_relocator ()
+{
+ return;
+}
diff --git a/winsup/cygwin/lib/pseudo-reloc.c b/winsup/cygwin/lib/pseudo-reloc.c
deleted file mode 100644
index 77f041114..000000000
--- a/winsup/cygwin/lib/pseudo-reloc.c
+++ /dev/null
@@ -1,367 +0,0 @@
-/* pseudo-reloc.c
-
- Contributed by Egor Duda <deo@logos-m.ru>
- Modified by addition of runtime_pseudo_reloc version 2
- by Kai Tietz <kai.tietz@onevision.com>
-
- THIS SOFTWARE IS NOT COPYRIGHTED
-
- This source code is offered for use in the public domain. You may
- use, modify or distribute it freely.
-
- This code is distributed in the hope that it will be useful but
- WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY
- DISCLAMED. This includes but is not limited to warrenties of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-*/
-
-#include <windows.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <memory.h>
-
-#if defined(__CYGWIN__)
-#include <wchar.h>
-#include <ntdef.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)
-#define SHORT_MSG_BUF_SZ 128
-#else
-# define NO_COPY
-#endif
-
-#ifdef __GNUC__
-#define ATTRIBUTE_NORETURN __attribute__ ((noreturn))
-#else
-#define ATTRIBUTE_NORETURN
-#endif
-
-#ifndef __MINGW_LSYMBOL
-#define __MINGW_LSYMBOL(sym) sym
-#endif
-
-extern char __RUNTIME_PSEUDO_RELOC_LIST__;
-extern char __RUNTIME_PSEUDO_RELOC_LIST_END__;
-extern char __MINGW_LSYMBOL(_image_base__);
-
-void _pei386_runtime_relocator (void);
-
-/* v1 relocation is basically:
- * *(base + .target) += .addend
- * where (base + .target) is always assumed to point
- * to a DWORD (4 bytes).
- */
-typedef struct {
- DWORD addend;
- DWORD target;
-} runtime_pseudo_reloc_item_v1;
-
-/* v2 relocation is more complex. In effect, it is
- * *(base + .target) += *(base + .sym) - (base + .sym)
- * with care taken in both reading, sign extension, and writing
- * because .flags may indicate that (base + .target) may point
- * to a BYTE, WORD, DWORD, or QWORD (w64).
- */
-typedef struct {
- DWORD sym;
- DWORD target;
- DWORD flags;
-} runtime_pseudo_reloc_item_v2;
-
-typedef struct {
- DWORD magic1;
- DWORD magic2;
- DWORD version;
-} runtime_pseudo_reloc_v2;
-
-static void ATTRIBUTE_NORETURN
-__report_error (const char *msg, ...)
-{
-#ifdef __CYGWIN__
- /* This function is used to print short error messages
- * to stderr, which may occur during DLL initialization
- * while fixing up 'pseudo' relocations. This early, we
- * may not be able to use cygwin stdio functions, so we
- * use the win32 WriteFile api. This should work with both
- * normal win32 console IO handles, redirected ones, and
- * cygwin ptys.
- */
- char buf[SHORT_MSG_BUF_SZ];
- wchar_t module[MAX_PATH];
- char * posix_module = NULL;
- static const char UNKNOWN_MODULE[] = "<unknown module>: ";
- static const size_t UNKNOWN_MODULE_LEN = sizeof (UNKNOWN_MODULE) - 1;
- static const char CYGWIN_FAILURE_MSG[] = "Cygwin runtime failure: ";
- static const size_t CYGWIN_FAILURE_MSG_LEN = sizeof (CYGWIN_FAILURE_MSG) - 1;
- 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)
- cygwin_internal (CW_EXIT_PROCESS,
- STATUS_ILLEGAL_DLL_PSEUDO_RELOCATION,
- 1);
-
- if (modulelen > 0)
- posix_module = cygwin_create_path (CCP_WIN_W_TO_POSIX, module);
-
- va_start (args, msg);
- len = (DWORD) vsnprintf (buf, SHORT_MSG_BUF_SZ, msg, args);
- va_end (args);
- buf[SHORT_MSG_BUF_SZ-1] = '\0'; /* paranoia */
-
- if (posix_module)
- {
- WriteFile (errh, (PCVOID)CYGWIN_FAILURE_MSG,
- CYGWIN_FAILURE_MSG_LEN, &done, NULL);
- 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
- {
- WriteFile (errh, (PCVOID)CYGWIN_FAILURE_MSG,
- CYGWIN_FAILURE_MSG_LEN, &done, NULL);
- WriteFile (errh, (PCVOID)UNKNOWN_MODULE,
- UNKNOWN_MODULE_LEN, &done, NULL);
- WriteFile (errh, (PCVOID)buf, len, &done, NULL);
- }
- WriteFile (errh, (PCVOID)"\n", 1, &done, NULL);
-
- cygwin_internal (CW_EXIT_PROCESS,
- STATUS_ILLEGAL_DLL_PSEUDO_RELOCATION,
- 1);
- /* not reached, but silences noreturn warning */
- abort ();
-#else
- va_list argp;
- va_start (argp, msg);
-# ifdef __MINGW64_VERSION_MAJOR
- fprintf (stderr, "Mingw-w64 runtime failure:\n");
-# else
- fprintf (stderr, "Mingw runtime failure:\n");
-# endif
- vfprintf (stderr, msg, argp);
- va_end (argp);
- abort ();
-#endif
-}
-
-/* This function temporarily marks the page containing addr
- * writable, before copying len bytes from *src to *addr, and
- * then restores the original protection settings to the page.
- *
- * Using this function eliminates the requirement with older
- * pseudo-reloc implementations, that sections containing
- * pseudo-relocs (such as .text and .rdata) be permanently
- * marked writable. This older behavior sabotaged any memory
- * savings achieved by shared libraries on win32 -- and was
- * slower, too. However, on cygwin as of binutils 2.20 the
- * .text section is still marked writable, and the .rdata section
- * is folded into the (writable) .data when --enable-auto-import.
- */
-static void
-__write_memory (void *addr, const void *src, size_t len)
-{
- MEMORY_BASIC_INFORMATION b;
- DWORD oldprot;
-
- if (!len)
- return;
-
- if (!VirtualQuery (addr, &b, sizeof(b)))
- {
- __report_error (" VirtualQuery failed for %d bytes at address %p",
- (int) sizeof(b), addr);
- }
-
- /* 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,
- &oldprot);
- /* write the data. */
- memcpy (addr, src, len);
- /* Restore original protection. */
- if (b.Protect != PAGE_EXECUTE_READWRITE && b.Protect != PAGE_READWRITE)
- VirtualProtect (b.BaseAddress, b.RegionSize, oldprot, &oldprot);
-}
-
-#define RP_VERSION_V1 0
-#define RP_VERSION_V2 1
-
-static void
-do_pseudo_reloc (void * start, void * end, void * base)
-{
- ptrdiff_t addr_imp, reldata;
- ptrdiff_t reloc_target = (ptrdiff_t) ((char *)end - (char*)start);
- runtime_pseudo_reloc_v2 *v2_hdr = (runtime_pseudo_reloc_v2 *) start;
- runtime_pseudo_reloc_item_v2 *r;
-
- /* A valid relocation list will contain at least one entry, and
- * one v1 data structure (the smallest one) requires two DWORDs.
- * So, if the relocation list is smaller than 8 bytes, bail.
- */
- if (reloc_target < 8)
- return;
-
- /* Check if this is the old pseudo relocation version. */
- /* There are two kinds of v1 relocation lists:
- * 1) With a (v2-style) version header. In this case, the
- * first entry in the list is a 3-DWORD structure, with
- * value:
- * { 0, 0, RP_VERSION_V1 }
- * In this case, we skip to the next entry in the list,
- * knowing that all elements after the head item can
- * be cast to runtime_pseudo_reloc_item_v1.
- * 2) Without a (v2-style) version header. In this case, the
- * first element in the list IS an actual v1 relocation
- * record, which is two DWORDs. Because there will never
- * be a case where a v1 relocation record has both
- * addend == 0 and target == 0, this case will not be
- * confused with the prior one.
- * All current binutils, when generating a v1 relocation list,
- * use the second (e.g. original) form -- that is, without the
- * v2-style version header.
- */
- if (reloc_target >= 12
- && v2_hdr->magic1 == 0 && v2_hdr->magic2 == 0
- && v2_hdr->version == RP_VERSION_V1)
- {
- /* We have a list header item indicating that the rest
- * of the list contains v1 entries. Move the pointer to
- * the first true v1 relocation record. By definition,
- * that v1 element will not have both addend == 0 and
- * target == 0 (and thus, when interpreted as a
- * runtime_pseudo_reloc_v2, it will not have both
- * magic1 == 0 and magic2 == 0).
- */
- v2_hdr++;
- }
-
- if (v2_hdr->magic1 != 0 || v2_hdr->magic2 != 0)
- {
- /*************************
- * Handle v1 relocations *
- *************************/
- runtime_pseudo_reloc_item_v1 * o;
- for (o = (runtime_pseudo_reloc_item_v1 *) v2_hdr;
- o < (runtime_pseudo_reloc_item_v1 *)end;
- o++)
- {
- DWORD newval;
- reloc_target = (ptrdiff_t) base + o->target;
- newval = (*((DWORD*) reloc_target)) + o->addend;
- __write_memory ((void *) reloc_target, &newval, sizeof(DWORD));
- }
- return;
- }
-
- /* If we got this far, then we have relocations of version 2 or newer */
-
- /* Check if this is a known version. */
- if (v2_hdr->version != RP_VERSION_V2)
- {
- __report_error (" Unknown pseudo relocation protocol version %d.\n",
- (int) v2_hdr->version);
- return;
- }
-
- /*************************
- * Handle v2 relocations *
- *************************/
-
- /* Walk over header. */
- r = (runtime_pseudo_reloc_item_v2 *) &v2_hdr[1];
-
- for (; r < (runtime_pseudo_reloc_item_v2 *) end; r++)
- {
- /* location where new address will be written */
- reloc_target = (ptrdiff_t) base + r->target;
-
- /* get sym pointer. It points either to the iat entry
- * of the referenced element, or to the stub function.
- */
- addr_imp = (ptrdiff_t) base + r->sym;
- addr_imp = *((ptrdiff_t *) addr_imp);
-
- /* read existing relocation value from image, casting to the
- * bitsize indicated by the 8 LSBs of flags. If the value is
- * negative, manually sign-extend to ptrdiff_t width. Raise an
- * error if the bitsize indicated by the 8 LSBs of flags is not
- * supported.
- */
- switch ((r->flags & 0xff))
- {
- case 8:
- reldata = (ptrdiff_t) (*((unsigned char *)reloc_target));
- if ((reldata & 0x80) != 0)
- reldata |= ~((ptrdiff_t) 0xff);
- break;
- case 16:
- reldata = (ptrdiff_t) (*((unsigned short *)reloc_target));
- if ((reldata & 0x8000) != 0)
- reldata |= ~((ptrdiff_t) 0xffff);
- break;
- case 32:
- reldata = (ptrdiff_t) (*((unsigned int *)reloc_target));
-#ifdef _WIN64
- if ((reldata & 0x80000000) != 0)
- reldata |= ~((ptrdiff_t) 0xffffffff);
-#endif
- break;
-#ifdef _WIN64
- case 64:
- reldata = (ptrdiff_t) (*((unsigned long long *)reloc_target));
- break;
-#endif
- default:
- reldata=0;
- __report_error (" Unknown pseudo relocation bit size %d.\n",
- (int) (r->flags & 0xff));
- break;
- }
-
- /* Adjust the relocation value */
- reldata -= ((ptrdiff_t) base + r->sym);
- reldata += addr_imp;
-
- /* Write the new relocation value back to *reloc_target */
- switch ((r->flags & 0xff))
- {
- case 8:
- __write_memory ((void *) reloc_target, &reldata, 1);
- break;
- case 16:
- __write_memory ((void *) reloc_target, &reldata, 2);
- break;
- case 32:
- __write_memory ((void *) reloc_target, &reldata, 4);
- break;
-#ifdef _WIN64
- case 64:
- __write_memory ((void *) reloc_target, &reldata, 8);
- break;
-#endif
- }
- }
-}
-
-void
-_pei386_runtime_relocator (void)
-{
- static NO_COPY int was_init = 0;
- if (was_init)
- return;
- ++was_init;
- do_pseudo_reloc (&__RUNTIME_PSEUDO_RELOC_LIST__,
- &__RUNTIME_PSEUDO_RELOC_LIST_END__,
- &__MINGW_LSYMBOL(_image_base__));
-}
diff --git a/winsup/cygwin/pseudo-reloc.cc b/winsup/cygwin/pseudo-reloc.cc
index 77f041114..290c1a838 100644
--- a/winsup/cygwin/pseudo-reloc.cc
+++ b/winsup/cygwin/pseudo-reloc.cc
@@ -15,25 +15,23 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
-#include <windows.h>
+#ifndef __CYGWIN__
+# include "windows.h"
+# define NO_COPY
+#else
+# include "winsup.h"
+# include <wchar.h>
+# include <ntdef.h>
+# include <sys/cygwin.h>
+/* custom status code: */
+# define STATUS_ILLEGAL_DLL_PSEUDO_RELOCATION ((NTSTATUS) 0xe0000269)
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <memory.h>
-#if defined(__CYGWIN__)
-#include <wchar.h>
-#include <ntdef.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)
-#define SHORT_MSG_BUF_SZ 128
-#else
-# define NO_COPY
-#endif
-
#ifdef __GNUC__
#define ATTRIBUTE_NORETURN __attribute__ ((noreturn))
#else
@@ -48,8 +46,6 @@ extern char __RUNTIME_PSEUDO_RELOC_LIST__;
extern char __RUNTIME_PSEUDO_RELOC_LIST_END__;
extern char __MINGW_LSYMBOL(_image_base__);
-void _pei386_runtime_relocator (void);
-
/* v1 relocation is basically:
* *(base + .target) += .addend
* where (base + .target) is always assumed to point
@@ -90,55 +86,32 @@ __report_error (const char *msg, ...)
* normal win32 console IO handles, redirected ones, and
* cygwin ptys.
*/
- char buf[SHORT_MSG_BUF_SZ];
+ char buf[128];
wchar_t module[MAX_PATH];
char * posix_module = NULL;
- static const char UNKNOWN_MODULE[] = "<unknown module>: ";
- static const size_t UNKNOWN_MODULE_LEN = sizeof (UNKNOWN_MODULE) - 1;
- static const char CYGWIN_FAILURE_MSG[] = "Cygwin runtime failure: ";
- static const size_t CYGWIN_FAILURE_MSG_LEN = sizeof (CYGWIN_FAILURE_MSG) - 1;
- DWORD len;
- DWORD done;
- va_list args;
+ static const char UNKNOWN_MODULE[] = "<unknown module>: ";
+ static const char CYGWIN_FAILURE_MSG[] = "Cygwin runtime failure: ";
HANDLE errh = GetStdHandle (STD_ERROR_HANDLE);
ssize_t modulelen = GetModuleFileNameW (NULL, module, sizeof (module));
+ va_list args;
+ /* FIXME: cleanup further to avoid old use of cygwin_internal */
if (errh == INVALID_HANDLE_VALUE)
- cygwin_internal (CW_EXIT_PROCESS,
- STATUS_ILLEGAL_DLL_PSEUDO_RELOCATION,
- 1);
+ cygwin_internal (CW_EXIT_PROCESS, STATUS_ILLEGAL_DLL_PSEUDO_RELOCATION, 1);
if (modulelen > 0)
- posix_module = cygwin_create_path (CCP_WIN_W_TO_POSIX, module);
+ posix_module = (char *) cygwin_create_path (CCP_WIN_W_TO_POSIX, module);
va_start (args, msg);
- len = (DWORD) vsnprintf (buf, SHORT_MSG_BUF_SZ, msg, args);
+ vsnprintf (buf, sizeof (buf), msg, args);
va_end (args);
- buf[SHORT_MSG_BUF_SZ-1] = '\0'; /* paranoia */
+ buf[sizeof (buf) - 1] = '\0'; /* paranoia */
+ small_printf ("%s%s: %s\n", CYGWIN_FAILURE_MSG, posix_module ?: UNKNOWN_MODULE, buf);
if (posix_module)
- {
- WriteFile (errh, (PCVOID)CYGWIN_FAILURE_MSG,
- CYGWIN_FAILURE_MSG_LEN, &done, NULL);
- 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
- {
- WriteFile (errh, (PCVOID)CYGWIN_FAILURE_MSG,
- CYGWIN_FAILURE_MSG_LEN, &done, NULL);
- WriteFile (errh, (PCVOID)UNKNOWN_MODULE,
- UNKNOWN_MODULE_LEN, &done, NULL);
- WriteFile (errh, (PCVOID)buf, len, &done, NULL);
- }
- WriteFile (errh, (PCVOID)"\n", 1, &done, NULL);
+ free (posix_module);
- cygwin_internal (CW_EXIT_PROCESS,
- STATUS_ILLEGAL_DLL_PSEUDO_RELOCATION,
- 1);
+ cygwin_internal (CW_EXIT_PROCESS, STATUS_ILLEGAL_DLL_PSEUDO_RELOCATION, 1);
/* not reached, but silences noreturn warning */
abort ();
#else
@@ -177,10 +150,10 @@ __write_memory (void *addr, const void *src, size_t len)
if (!len)
return;
- if (!VirtualQuery (addr, &b, sizeof(b)))
+ if (!VirtualQuery (addr, &b, sizeof (b)))
{
__report_error (" VirtualQuery failed for %d bytes at address %p",
- (int) sizeof(b), addr);
+ (int) sizeof (b), addr);
}
/* Temporarily allow write access to read-only protected memory. */
@@ -259,7 +232,7 @@ do_pseudo_reloc (void * start, void * end, void * base)
DWORD newval;
reloc_target = (ptrdiff_t) base + o->target;
newval = (*((DWORD*) reloc_target)) + o->addend;
- __write_memory ((void *) reloc_target, &newval, sizeof(DWORD));
+ __write_memory ((void *) reloc_target, &newval, sizeof (DWORD));
}
return;
}
@@ -300,33 +273,33 @@ do_pseudo_reloc (void * start, void * end, void * base)
*/
switch ((r->flags & 0xff))
{
- case 8:
- reldata = (ptrdiff_t) (*((unsigned char *)reloc_target));
- if ((reldata & 0x80) != 0)
- reldata |= ~((ptrdiff_t) 0xff);
- break;
- case 16:
- reldata = (ptrdiff_t) (*((unsigned short *)reloc_target));
- if ((reldata & 0x8000) != 0)
- reldata |= ~((ptrdiff_t) 0xffff);
- break;
- case 32:
- reldata = (ptrdiff_t) (*((unsigned int *)reloc_target));
+ case 8:
+ reldata = (ptrdiff_t) (*((unsigned char *)reloc_target));
+ if ((reldata & 0x80) != 0)
+ reldata |= ~((ptrdiff_t) 0xff);
+ break;
+ case 16:
+ reldata = (ptrdiff_t) (*((unsigned short *)reloc_target));
+ if ((reldata & 0x8000) != 0)
+ reldata |= ~((ptrdiff_t) 0xffff);
+ break;
+ case 32:
+ reldata = (ptrdiff_t) (*((unsigned int *)reloc_target));
#ifdef _WIN64
- if ((reldata & 0x80000000) != 0)
- reldata |= ~((ptrdiff_t) 0xffffffff);
+ if ((reldata & 0x80000000) != 0)
+ reldata |= ~((ptrdiff_t) 0xffffffff);
#endif
- break;
+ break;
#ifdef _WIN64
- case 64:
- reldata = (ptrdiff_t) (*((unsigned long long *)reloc_target));
- break;
+ case 64:
+ reldata = (ptrdiff_t) (*((unsigned long long *)reloc_target));
+ break;
#endif
- default:
- reldata=0;
- __report_error (" Unknown pseudo relocation bit size %d.\n",
- (int) (r->flags & 0xff));
- break;
+ default:
+ reldata=0;
+ __report_error (" Unknown pseudo relocation bit size %d.\n",
+ (int) (r->flags & 0xff));
+ break;
}
/* Adjust the relocation value */
@@ -336,25 +309,33 @@ do_pseudo_reloc (void * start, void * end, void * base)
/* Write the new relocation value back to *reloc_target */
switch ((r->flags & 0xff))
{
- case 8:
- __write_memory ((void *) reloc_target, &reldata, 1);
- break;
- case 16:
- __write_memory ((void *) reloc_target, &reldata, 2);
- break;
- case 32:
- __write_memory ((void *) reloc_target, &reldata, 4);
- break;
+ case 8:
+ __write_memory ((void *) reloc_target, &reldata, 1);
+ break;
+ case 16:
+ __write_memory ((void *) reloc_target, &reldata, 2);
+ break;
+ case 32:
+ __write_memory ((void *) reloc_target, &reldata, 4);
+ break;
#ifdef _WIN64
- case 64:
- __write_memory ((void *) reloc_target, &reldata, 8);
- break;
+ case 64:
+ __write_memory ((void *) reloc_target, &reldata, 8);
+ break;
#endif
}
}
}
+#ifdef __CYGWIN__
void
+_pei386_runtime_relocator (per_process *u)
+{
+ if (CYGWIN_VERSION_USE_PSEUDO_RELOC_IN_DLL (u))
+ do_pseudo_reloc (u->pseudo_reloc_start, u->pseudo_reloc_end, u->image_base);
+}
+#else
+extern "C" void
_pei386_runtime_relocator (void)
{
static NO_COPY int was_init = 0;
@@ -365,3 +346,4 @@ _pei386_runtime_relocator (void)
&__RUNTIME_PSEUDO_RELOC_LIST_END__,
&__MINGW_LSYMBOL(_image_base__));
}
+#endif
diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h
index 7f0377ef8..efcdf6dee 100644
--- a/winsup/cygwin/winsup.h
+++ b/winsup/cygwin/winsup.h
@@ -179,6 +179,8 @@ int spawn_guts (const char * prog_arg, const char *const *argv,
/* dynamically loaded dll initialization */
extern "C" int dll_dllcrt0 (HMODULE, per_process *);
+void _pei386_runtime_relocator (per_process *);
+
/* dynamically loaded dll initialization for non-cygwin apps */
extern "C" int dll_noncygwin_dllcrt0 (HMODULE, per_process *);
void __stdcall do_exit (int) __attribute__ ((regparm (1), noreturn));