* 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

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