* 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 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
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=,\
#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 *);
"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,
/* 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 ();
{
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. */
/* 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;
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;
/* 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,
};
/* 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. */
#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:
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
/* 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;
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;
{
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 =
{
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;
}
--- /dev/null
+/* pseudo-reloc.c
+
+ Stub for older binaries.
+*/
+
+void
+_pei386_runtime_relocator ()
+{
+ return;
+}
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
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
* 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
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. */
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;
}
*/
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 */
/* 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;
&__RUNTIME_PSEUDO_RELOC_LIST_END__,
&__MINGW_LSYMBOL(_image_base__));
}
+#endif
/* 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));