* 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.
This commit is contained in:
Christopher Faylor 2010-05-07 21:25:19 +00:00
parent 186bcf2a17
commit 27f564e9a3
12 changed files with 172 additions and 482 deletions

View File

@ -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

View File

@ -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=,\

View File

@ -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 ();

View File

@ -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;

View File

@ -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,
};

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -0,0 +1,10 @@
/* pseudo-reloc.c
Stub for older binaries.
*/
void
_pei386_runtime_relocator ()
{
return;
}

View File

@ -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__));
}

View File

@ -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

View File

@ -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));