[CRT/STARTUP]

* Sync startup code to recent mingw-w64. RosBE 2.0 here we come !

svn path=/trunk/; revision=52111
This commit is contained in:
Amine Khaldi 2011-06-06 10:01:14 +00:00
parent e54b5f0d2e
commit 864fd70bcc
10 changed files with 672 additions and 153 deletions

View file

@ -8,6 +8,7 @@ endif()
list(APPEND MSVCRTEX_SOURCE
startup/crtexe.c
startup/wcrtexe.c
startup/crt_handler.c
startup/crtdll.c
startup/_newmode.c
startup/wildcard.c
@ -18,6 +19,7 @@ list(APPEND MSVCRTEX_SOURCE
startup/merr.c
startup/atonexit.c
startup/txtmode.c
startup/pesect.c
startup/pseudo-reloc.c
startup/pseudo-reloc-list.c
startup/tlsmcrt.c

View file

@ -1,11 +1,12 @@
#include <stdio.h>
#include <internal.h>
#include <sect_attribs.h>
#ifdef _MSC_VER
#pragma comment(linker, "/merge:.CRT=.rdata")
#endif
typedef void (__cdecl *_PVFV)(void);
_CRTALLOC(".CRT$XIA") _PVFV __xi_a[] = { NULL };
_CRTALLOC(".CRT$XIZ") _PVFV __xi_z[] = { NULL };
_CRTALLOC(".CRT$XCA") _PVFV __xc_a[] = { NULL };

View file

@ -0,0 +1,290 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the w64 mingw-runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#include <windows.h>
#include <excpt.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <signal.h>
#include <stdio.h>
#if defined (_WIN64) && defined (__ia64__)
#error FIXME: Unsupported __ImageBase implementation.
#else
#ifndef _MSC_VER
#define __ImageBase __MINGW_LSYMBOL(_image_base__)
#endif
/* This symbol is defined by the linker. */
extern IMAGE_DOS_HEADER __ImageBase;
#endif
#pragma pack(push,1)
typedef struct _UNWIND_INFO {
BYTE VersionAndFlags;
BYTE PrologSize;
BYTE CountOfUnwindCodes;
BYTE FrameRegisterAndOffset;
ULONG AddressOfExceptionHandler;
} UNWIND_INFO,*PUNWIND_INFO;
#pragma pack(pop)
PIMAGE_SECTION_HEADER _FindPESectionByName (const char *);
PIMAGE_SECTION_HEADER _FindPESectionExec (size_t);
PBYTE _GetPEImageBase (void);
int __mingw_init_ehandler (void);
extern void _fpreset (void);
#ifdef _WIN64
EXCEPTION_DISPOSITION __mingw_SEH_error_handler(struct _EXCEPTION_RECORD *, void *, struct _CONTEXT *, void *);
#define MAX_PDATA_ENTRIES 32
static RUNTIME_FUNCTION emu_pdata[MAX_PDATA_ENTRIES];
static UNWIND_INFO emu_xdata[MAX_PDATA_ENTRIES];
int
__mingw_init_ehandler (void)
{
static int was_here = 0;
size_t e = 0;
PIMAGE_SECTION_HEADER pSec;
PBYTE _ImageBase = _GetPEImageBase ();
if (was_here || !_ImageBase)
return was_here;
was_here = 1;
if (_FindPESectionByName (".pdata") != NULL)
return 1;
/* Allocate # of e tables and entries. */
memset (emu_pdata, 0, sizeof (RUNTIME_FUNCTION) * MAX_PDATA_ENTRIES);
memset (emu_xdata, 0, sizeof (UNWIND_INFO) * MAX_PDATA_ENTRIES);
e = 0;
/* Fill tables and entries. */
while (e < MAX_PDATA_ENTRIES && (pSec = _FindPESectionExec (e)) != NULL)
{
emu_xdata[e].VersionAndFlags = 9; /* UNW_FLAG_EHANDLER | UNW_VERSION */
emu_xdata[e].AddressOfExceptionHandler =
(DWORD)(size_t) ((LPBYTE)__mingw_SEH_error_handler - _ImageBase);
emu_pdata[e].BeginAddress = pSec->VirtualAddress;
emu_pdata[e].EndAddress = pSec->VirtualAddress + pSec->Misc.VirtualSize;
emu_pdata[e].UnwindData =
(DWORD)(size_t)((LPBYTE)&emu_xdata[e] - _ImageBase);
++e;
}
#ifdef _DEBUG_CRT
if (!e || e > MAX_PDATA_ENTRIES)
abort ();
#endif
/* RtlAddFunctionTable. */
if (e != 0)
RtlAddFunctionTable (emu_pdata, e, (DWORD64)_ImageBase);
return 1;
}
extern void _fpreset (void);
EXCEPTION_DISPOSITION
__mingw_SEH_error_handler (struct _EXCEPTION_RECORD* ExceptionRecord,
void *EstablisherFrame __attribute__ ((unused)),
struct _CONTEXT* ContextRecord __attribute__ ((unused)),
void *DispatcherContext __attribute__ ((unused)))
{
EXCEPTION_DISPOSITION action = ExceptionContinueSearch; /* EXCEPTION_CONTINUE_SEARCH; */
void (*old_handler) (int);
int reset_fpu = 0;
switch (ExceptionRecord->ExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION:
/* test if the user has set SIGSEGV */
old_handler = signal (SIGSEGV, SIG_DFL);
if (old_handler == SIG_IGN)
{
/* this is undefined if the signal was raised by anything other
than raise (). */
signal (SIGSEGV, SIG_IGN);
action = 0; //EXCEPTION_CONTINUE_EXECUTION;
}
else if (old_handler != SIG_DFL)
{
/* This means 'old' is a user defined function. Call it */
(*old_handler) (SIGSEGV);
action = 0; // EXCEPTION_CONTINUE_EXECUTION;
}
else
action = 4; /* EXCEPTION_EXECUTE_HANDLER; */
break;
case EXCEPTION_ILLEGAL_INSTRUCTION:
case EXCEPTION_PRIV_INSTRUCTION:
/* test if the user has set SIGILL */
old_handler = signal (SIGILL, SIG_DFL);
if (old_handler == SIG_IGN)
{
/* this is undefined if the signal was raised by anything other
than raise (). */
signal (SIGILL, SIG_IGN);
action = 0; // EXCEPTION_CONTINUE_EXECUTION;
}
else if (old_handler != SIG_DFL)
{
/* This means 'old' is a user defined function. Call it */
(*old_handler) (SIGILL);
action = 0; // EXCEPTION_CONTINUE_EXECUTION;
}
else
action = 4; /* EXCEPTION_EXECUTE_HANDLER;*/
break;
case EXCEPTION_FLT_INVALID_OPERATION:
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
case EXCEPTION_FLT_DENORMAL_OPERAND:
case EXCEPTION_FLT_OVERFLOW:
case EXCEPTION_FLT_UNDERFLOW:
case EXCEPTION_FLT_INEXACT_RESULT:
reset_fpu = 1;
/* fall through. */
case EXCEPTION_INT_DIVIDE_BY_ZERO:
/* test if the user has set SIGFPE */
old_handler = signal (SIGFPE, SIG_DFL);
if (old_handler == SIG_IGN)
{
signal (SIGFPE, SIG_IGN);
if (reset_fpu)
_fpreset ();
action = 0; // EXCEPTION_CONTINUE_EXECUTION;
}
else if (old_handler != SIG_DFL)
{
/* This means 'old' is a user defined function. Call it */
(*old_handler) (SIGFPE);
action = 0; // EXCEPTION_CONTINUE_EXECUTION;
}
break;
case EXCEPTION_DATATYPE_MISALIGNMENT:
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
case EXCEPTION_FLT_STACK_CHECK:
case EXCEPTION_INT_OVERFLOW:
case EXCEPTION_INVALID_HANDLE:
/*case EXCEPTION_POSSIBLE_DEADLOCK: */
action = 0; // EXCEPTION_CONTINUE_EXECUTION;
break;
default:
break;
}
return action;
}
#endif
LPTOP_LEVEL_EXCEPTION_FILTER __mingw_oldexcpt_handler = NULL;
long CALLBACK
_gnu_exception_handler (EXCEPTION_POINTERS *exception_data);
#define GCC_MAGIC (('G' << 16) | ('C' << 8) | 'C' | (1U << 29))
long CALLBACK
_gnu_exception_handler (EXCEPTION_POINTERS *exception_data)
{
void (*old_handler) (int);
long action = EXCEPTION_CONTINUE_SEARCH;
int reset_fpu = 0;
#ifdef __SEH__
if ((exception_data->ExceptionRecord->ExceptionCode & 0x20ffffff) == GCC_MAGIC)
{
if ((exception_data->ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE) == 0)
return EXCEPTION_CONTINUE_EXECUTION;
}
#endif
switch (exception_data->ExceptionRecord->ExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION:
/* test if the user has set SIGSEGV */
old_handler = signal (SIGSEGV, SIG_DFL);
if (old_handler == SIG_IGN)
{
/* this is undefined if the signal was raised by anything other
than raise (). */
signal (SIGSEGV, SIG_IGN);
action = EXCEPTION_CONTINUE_EXECUTION;
}
else if (old_handler != SIG_DFL)
{
/* This means 'old' is a user defined function. Call it */
(*old_handler) (SIGSEGV);
action = EXCEPTION_CONTINUE_EXECUTION;
}
break;
case EXCEPTION_ILLEGAL_INSTRUCTION:
case EXCEPTION_PRIV_INSTRUCTION:
/* test if the user has set SIGILL */
old_handler = signal (SIGILL, SIG_DFL);
if (old_handler == SIG_IGN)
{
/* this is undefined if the signal was raised by anything other
than raise (). */
signal (SIGILL, SIG_IGN);
action = EXCEPTION_CONTINUE_EXECUTION;
}
else if (old_handler != SIG_DFL)
{
/* This means 'old' is a user defined function. Call it */
(*old_handler) (SIGILL);
action = EXCEPTION_CONTINUE_EXECUTION;
}
break;
case EXCEPTION_FLT_INVALID_OPERATION:
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
case EXCEPTION_FLT_DENORMAL_OPERAND:
case EXCEPTION_FLT_OVERFLOW:
case EXCEPTION_FLT_UNDERFLOW:
case EXCEPTION_FLT_INEXACT_RESULT:
reset_fpu = 1;
/* fall through. */
case EXCEPTION_INT_DIVIDE_BY_ZERO:
/* test if the user has set SIGFPE */
old_handler = signal (SIGFPE, SIG_DFL);
if (old_handler == SIG_IGN)
{
signal (SIGFPE, SIG_IGN);
if (reset_fpu)
_fpreset ();
action = EXCEPTION_CONTINUE_EXECUTION;
}
else if (old_handler != SIG_DFL)
{
/* This means 'old' is a user defined function. Call it */
(*old_handler) (SIGFPE);
action = EXCEPTION_CONTINUE_EXECUTION;
}
break;
#ifdef _WIN64
case EXCEPTION_DATATYPE_MISALIGNMENT:
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
case EXCEPTION_FLT_STACK_CHECK:
case EXCEPTION_INT_OVERFLOW:
case EXCEPTION_INVALID_HANDLE:
/*case EXCEPTION_POSSIBLE_DEADLOCK: */
action = EXCEPTION_CONTINUE_EXECUTION;
break;
#endif
default:
break;
}
if (action == EXCEPTION_CONTINUE_SEARCH && __mingw_oldexcpt_handler)
action = (*__mingw_oldexcpt_handler)(exception_data);
return action;
}

View file

@ -20,7 +20,6 @@
#include <tchar.h>
#include <sect_attribs.h>
#include <locale.h>
#include <intrin.h>
#ifndef __winitenv
extern wchar_t *** __MINGW_IMP_SYMBOL(__winitenv);
@ -44,11 +43,11 @@ extern void _fpreset (void);
#define SPACECHAR _T(' ')
#define DQUOTECHAR _T('\"')
__declspec(dllimport) void __setusermatherr(int (__cdecl *)(struct _exception *));
extern int * __MINGW_IMP_SYMBOL(_fmode);
extern int * __MINGW_IMP_SYMBOL(_commode);
#undef _fmode
extern int _fmode;
extern int * __MINGW_IMP_SYMBOL(_commode);
#define _commode (* __MINGW_IMP_SYMBOL(_commode))
extern int _dowildcard;
@ -56,7 +55,7 @@ extern int _dowildcard;
#if defined(__GNUC__)
int _MINGW_INSTALL_DEBUG_MATHERR __attribute__((weak)) = 0;
#else
int __declspec(selectany) _MINGW_INSTALL_DEBUG_MATHERR = 0;
int _MINGW_INSTALL_DEBUG_MATHERR = 0;
#endif
extern int __defaultmatherr;
extern _CRTIMP void __cdecl _initterm(_PVFV *, _PVFV *);
@ -81,8 +80,8 @@ _TCHAR *__mingw_winmain_lpCmdLine;
DWORD __mingw_winmain_nShowCmd;
static int argc;
#ifdef WPRFLAG
extern void __main(void);
#ifdef WPRFLAG
static wchar_t **argv;
static wchar_t **envp;
#else
@ -95,10 +94,10 @@ static int mainret=0;
static int managedapp;
static int has_cctor = 0;
static _startupinfo startinfo;
static LPTOP_LEVEL_EXCEPTION_FILTER __mingw_oldexcpt_handler = NULL;
extern LPTOP_LEVEL_EXCEPTION_FILTER __mingw_oldexcpt_handler;
extern void _pei386_runtime_relocator (void);
static long CALLBACK _gnu_exception_handler (EXCEPTION_POINTERS * exception_data);
long CALLBACK _gnu_exception_handler (EXCEPTION_POINTERS * exception_data);
#ifdef WPRFLAG
static void duplicate_ppstrings (int ac, wchar_t ***av);
#else
@ -108,8 +107,10 @@ static void duplicate_ppstrings (int ac, char ***av);
static int __cdecl pre_c_init (void);
static void __cdecl pre_cpp_init (void);
static void __cdecl __mingw_prepare_except_for_msvcr80_and_higher (void);
_CRTALLOC(".CRT$XIAA") _PIFV __declspec(selectany) mingw_pcinit = pre_c_init;
_CRTALLOC(".CRT$XCAA") _PVFV __declspec(selectany) mingw_pcppinit = pre_cpp_init;
_CRTALLOC(".CRT$XIAA") _PIFV mingw_pcinit = pre_c_init;
_CRTALLOC(".CRT$XCAA") _PVFV mingw_pcppinit = pre_cpp_init;
extern int _MINGW_INSTALL_DEBUG_MATHERR;
static int __cdecl
pre_c_init (void)
@ -131,11 +132,7 @@ pre_c_init (void)
#endif
if (_MINGW_INSTALL_DEBUG_MATHERR)
{
if (! __defaultmatherr)
{
__setusermatherr (_matherr);
__defaultmatherr = 1;
}
__setusermatherr (_matherr);
}
if (__globallocalestatus == -1)
@ -162,9 +159,24 @@ int WinMainCRTStartup (void);
int WinMainCRTStartup (void)
{
int ret = 255;
#ifdef __SEH__
asm ("\t.l_startw:\n"
"\t.seh_handler __C_specific_handler, @except\n"
"\t.seh_handlerdata\n"
"\t.long 1\n"
"\t.rva .l_startw, .l_endw, _gnu_exception_handler ,.l_endw\n"
"\t.text"
);
#endif
mingw_app_type = 1;
__security_init_cookie ();
return __tmainCRTStartup ();
ret = __tmainCRTStartup ();
#ifdef __SEH__
asm ("\tnop\n"
"\t.l_endw: nop\n");
#endif
return ret;
}
int mainCRTStartup (void);
@ -175,9 +187,24 @@ int __mingw_init_ehandler (void);
int mainCRTStartup (void)
{
int ret = 255;
#ifdef __SEH__
asm ("\t.l_start:\n"
"\t.seh_handler __C_specific_handler, @except\n"
"\t.seh_handlerdata\n"
"\t.long 1\n"
"\t.rva .l_start, .l_end, _gnu_exception_handler ,.l_end\n"
"\t.text"
);
#endif
mingw_app_type = 0;
__security_init_cookie ();
return __tmainCRTStartup ();
ret = __tmainCRTStartup ();
#ifdef __SEH__
asm ("\tnop\n"
"\t.l_end: nop\n");
#endif
return ret;
}
static
@ -188,7 +215,16 @@ __tmainCRTStartup (void)
STARTUPINFO StartupInfo;
WINBOOL inDoubleQuote = FALSE;
memset (&StartupInfo, 0, sizeof (STARTUPINFO));
#ifndef _WIN64
/* We need to make sure that this function is build with frame-pointer
and that we align the stack to 16 bytes for the sake of SSE ops in main
or in functions inlined into main. */
lpszCommandLine = (_TCHAR *) alloca (32);
memset (lpszCommandLine, 0xcc, 32);
asm __volatile__ ("andl $-16, %%esp" : : : "%esp");
#endif
if (mingw_app_type)
GetStartupInfo (&StartupInfo);
{
@ -267,11 +303,11 @@ __tmainCRTStartup (void)
StartupInfo.wShowWindow : SW_SHOWDEFAULT;
}
duplicate_ppstrings (argc, &argv);
__main ();
#ifdef WPRFLAG
__winitenv = envp;
/* C++ initialization.
gcc inserts this call automatically for a function called main, but not for wmain. */
__main ();
mainret = wmain (argc, argv, envp);
#else
__initenv = envp;
@ -329,97 +365,6 @@ check_managed_app (void)
return 0;
}
static long CALLBACK
_gnu_exception_handler (EXCEPTION_POINTERS *exception_data)
{
void (*old_handler) (int);
long action = EXCEPTION_CONTINUE_SEARCH;
int reset_fpu = 0;
switch (exception_data->ExceptionRecord->ExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION:
/* test if the user has set SIGSEGV */
old_handler = signal (SIGSEGV, SIG_DFL);
if (old_handler == SIG_IGN)
{
/* this is undefined if the signal was raised by anything other
than raise (). */
signal (SIGSEGV, SIG_IGN);
action = EXCEPTION_CONTINUE_EXECUTION;
}
else if (old_handler != SIG_DFL)
{
/* This means 'old' is a user defined function. Call it */
(*old_handler) (SIGSEGV);
action = EXCEPTION_CONTINUE_EXECUTION;
}
break;
case EXCEPTION_ILLEGAL_INSTRUCTION:
case EXCEPTION_PRIV_INSTRUCTION:
/* test if the user has set SIGILL */
old_handler = signal (SIGILL, SIG_DFL);
if (old_handler == SIG_IGN)
{
/* this is undefined if the signal was raised by anything other
than raise (). */
signal (SIGILL, SIG_IGN);
action = EXCEPTION_CONTINUE_EXECUTION;
}
else if (old_handler != SIG_DFL)
{
/* This means 'old' is a user defined function. Call it */
(*old_handler) (SIGILL);
action = EXCEPTION_CONTINUE_EXECUTION;
}
break;
case EXCEPTION_FLT_INVALID_OPERATION:
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
case EXCEPTION_FLT_DENORMAL_OPERAND:
case EXCEPTION_FLT_OVERFLOW:
case EXCEPTION_FLT_UNDERFLOW:
case EXCEPTION_FLT_INEXACT_RESULT:
reset_fpu = 1;
/* fall through. */
case EXCEPTION_INT_DIVIDE_BY_ZERO:
/* test if the user has set SIGFPE */
old_handler = signal (SIGFPE, SIG_DFL);
if (old_handler == SIG_IGN)
{
signal (SIGFPE, SIG_IGN);
if (reset_fpu)
_fpreset ();
action = EXCEPTION_CONTINUE_EXECUTION;
}
else if (old_handler != SIG_DFL)
{
/* This means 'old' is a user defined function. Call it */
(*old_handler) (SIGFPE);
action = EXCEPTION_CONTINUE_EXECUTION;
}
break;
#ifdef _WIN64
case EXCEPTION_DATATYPE_MISALIGNMENT:
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
case EXCEPTION_FLT_STACK_CHECK:
case EXCEPTION_INT_OVERFLOW:
case EXCEPTION_INVALID_HANDLE:
/*case EXCEPTION_POSSIBLE_DEADLOCK: */
action = EXCEPTION_CONTINUE_EXECUTION;
break;
#endif
default:
break;
}
if (action == EXCEPTION_CONTINUE_SEARCH && __mingw_oldexcpt_handler)
action = (*__mingw_oldexcpt_handler)(exception_data);
return action;
}
#ifdef WPRFLAG
static size_t wbytelen(const wchar_t *p)
{

View file

@ -12,13 +12,6 @@ typedef void (*func_ptr) (void);
extern func_ptr __CTOR_LIST__[];
extern func_ptr __DTOR_LIST__[];
static HMODULE hMsvcrt = NULL;
static int free_Msvcrt = 0;
typedef void __cdecl flongjmp(jmp_buf _Buf,int _Value);
flongjmp *fctMsvcrtLongJmp = NULL;
void __do_global_dtors (void);
void __do_global_ctors (void);
void __main (void);
@ -33,12 +26,6 @@ __do_global_dtors (void)
(*(p)) ();
p++;
}
if (free_Msvcrt && hMsvcrt)
{
free_Msvcrt = 0;
FreeLibrary (hMsvcrt);
hMsvcrt = NULL;
}
}
void
@ -47,19 +34,6 @@ __do_global_ctors (void)
unsigned long nptrs = (unsigned long) (ptrdiff_t) __CTOR_LIST__[0];
unsigned long i;
if (!hMsvcrt) {
hMsvcrt = GetModuleHandleA ("msvcr80.dll");
if (!hMsvcrt)
hMsvcrt = GetModuleHandleA ("msvcr70.dll");
if (!hMsvcrt)
hMsvcrt = GetModuleHandleA ("msvcrt.dll");
if (!hMsvcrt) {
hMsvcrt = LoadLibraryA ("msvcrt.dll");
free_Msvcrt = 1;
}
fctMsvcrtLongJmp = (flongjmp *) GetProcAddress( hMsvcrt, "longjmp");
}
if (nptrs == (unsigned long) -1)
{
for (nptrs = 0; __CTOR_LIST__[nptrs + 1] != 0; nptrs++);

View file

@ -23,11 +23,6 @@
#endif
/* Externals. */
#ifdef _WIN64
PRUNTIME_FUNCTION RtlLookupFunctionEntry (ULONG64, PULONG64, PVOID);
PVOID RtlVirtualUnwind (ULONG HandlerType, ULONG64, ULONG64, PRUNTIME_FUNCTION,
PCONTEXT, PVOID *, PULONG64, PVOID);
#endif
typedef LONG NTSTATUS; /* same as in ntdef.h / winternl.h */

View file

@ -10,6 +10,31 @@
int __defaultmatherr = 0;
typedef int (__cdecl *fUserMathErr)(struct _exception *);
static fUserMathErr stUserMathErr;
void __mingw_raise_matherr (int typ, const char *name, double a1, double a2,
double rslt)
{
struct _exception ex;
if (!stUserMathErr)
return;
ex.type = typ;
ex.name = name;
ex.arg1 = a1;
ex.arg2 = a2;
ex.retval = rslt;
(*stUserMathErr)(&ex);
}
#undef __setusermatherr
void __mingw_setusermatherr (int (__cdecl *f)(struct _exception *))
{
stUserMathErr = f;
__setusermatherr (f);
}
int __CRTDECL
_matherr (struct _exception *pexcept)
{
@ -50,3 +75,4 @@ _matherr (struct _exception *pexcept)
type, pexcept->name, pexcept->arg1, pexcept->arg2, pexcept->retval);
return 0;
}

View file

@ -0,0 +1,186 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the w64 mingw-runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#include <windows.h>
#include <string.h>
#if defined (_WIN64) && defined (__ia64__)
#error FIXME: Unsupported __ImageBase implementation.
#else
/* Hack, for bug in ld. Will be removed soon. */
#ifndef _MSC_VER
#define __ImageBase __MINGW_LSYMBOL(_image_base__)
#endif
/* This symbol is defined by the linker. */
extern IMAGE_DOS_HEADER __ImageBase;
#endif
WINBOOL _ValidateImageBase (PBYTE);
WINBOOL
_ValidateImageBase (PBYTE pImageBase)
{
PIMAGE_DOS_HEADER pDOSHeader;
PIMAGE_NT_HEADERS pNTHeader;
PIMAGE_OPTIONAL_HEADER pOptHeader;
pDOSHeader = (PIMAGE_DOS_HEADER) pImageBase;
if (pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE)
return FALSE;
pNTHeader = (PIMAGE_NT_HEADERS) ((PBYTE) pDOSHeader + pDOSHeader->e_lfanew);
if (pNTHeader->Signature != IMAGE_NT_SIGNATURE)
return FALSE;
pOptHeader = (PIMAGE_OPTIONAL_HEADER) &pNTHeader->OptionalHeader;
if (pOptHeader->Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
return FALSE;
return TRUE;
}
PIMAGE_SECTION_HEADER _FindPESection (PBYTE, DWORD_PTR);
PIMAGE_SECTION_HEADER
_FindPESection (PBYTE pImageBase, DWORD_PTR rva)
{
PIMAGE_NT_HEADERS pNTHeader;
PIMAGE_SECTION_HEADER pSection;
unsigned int iSection;
pNTHeader = (PIMAGE_NT_HEADERS) (pImageBase + ((PIMAGE_DOS_HEADER) pImageBase)->e_lfanew);
for (iSection = 0, pSection = IMAGE_FIRST_SECTION (pNTHeader);
iSection < pNTHeader->FileHeader.NumberOfSections;
++iSection,++pSection)
{
if (rva >= pSection->VirtualAddress
&& rva < pSection->VirtualAddress + pSection->Misc.VirtualSize)
return pSection;
}
return NULL;
}
PIMAGE_SECTION_HEADER _FindPESectionByName (const char *);
PIMAGE_SECTION_HEADER
_FindPESectionByName (const char *pName)
{
PBYTE pImageBase;
PIMAGE_NT_HEADERS pNTHeader;
PIMAGE_SECTION_HEADER pSection;
unsigned int iSection;
/* Long names aren't supported. */
if (strlen (pName) > IMAGE_SIZEOF_SHORT_NAME)
return NULL;
pImageBase = (PBYTE) &__ImageBase;
if (! _ValidateImageBase (pImageBase))
return NULL;
pNTHeader = (PIMAGE_NT_HEADERS) (pImageBase + ((PIMAGE_DOS_HEADER) pImageBase)->e_lfanew);
for (iSection = 0, pSection = IMAGE_FIRST_SECTION (pNTHeader);
iSection < pNTHeader->FileHeader.NumberOfSections;
++iSection,++pSection)
{
if (!strncmp ((char *) &pSection->Name[0], pName, IMAGE_SIZEOF_SHORT_NAME))
return pSection;
}
return NULL;
}
int __mingw_GetSectionCount (void);
PIMAGE_SECTION_HEADER __mingw_GetSectionForAddress (LPVOID p);
PIMAGE_SECTION_HEADER
__mingw_GetSectionForAddress (LPVOID p)
{
PBYTE pImageBase;
DWORD_PTR rva;
pImageBase = (PBYTE) &__ImageBase;
if (! _ValidateImageBase (pImageBase))
return NULL;
rva = (DWORD_PTR) (((PBYTE) p) - pImageBase);
return _FindPESection (pImageBase, rva);
}
int
__mingw_GetSectionCount (void)
{
PBYTE pImageBase;
PIMAGE_NT_HEADERS pNTHeader;
pImageBase = (PBYTE) &__ImageBase;
if (! _ValidateImageBase (pImageBase))
return 0;
pNTHeader = (PIMAGE_NT_HEADERS) (pImageBase + ((PIMAGE_DOS_HEADER) pImageBase)->e_lfanew);
return (int) pNTHeader->FileHeader.NumberOfSections;
}
PIMAGE_SECTION_HEADER _FindPESectionExec (size_t);
PIMAGE_SECTION_HEADER
_FindPESectionExec (size_t eNo)
{
PBYTE pImageBase;
PIMAGE_NT_HEADERS pNTHeader;
PIMAGE_SECTION_HEADER pSection;
unsigned int iSection;
pImageBase = (PBYTE) &__ImageBase;
if (! _ValidateImageBase (pImageBase))
return NULL;
pNTHeader = (PIMAGE_NT_HEADERS) (pImageBase + ((PIMAGE_DOS_HEADER) pImageBase)->e_lfanew);
for (iSection = 0, pSection = IMAGE_FIRST_SECTION (pNTHeader);
iSection < pNTHeader->FileHeader.NumberOfSections;
++iSection,++pSection)
{
if ((pSection->Characteristics & IMAGE_SCN_MEM_EXECUTE) != 0)
{
if (!eNo)
return pSection;
--eNo;
}
}
return NULL;
}
PBYTE _GetPEImageBase (void);
PBYTE
_GetPEImageBase (void)
{
PBYTE pImageBase;
pImageBase = (PBYTE) &__ImageBase;
if (! _ValidateImageBase (pImageBase))
return NULL;
return pImageBase;
}
WINBOOL _IsNonwritableInCurrentImage (PBYTE);
WINBOOL
_IsNonwritableInCurrentImage (PBYTE pTarget)
{
PBYTE pImageBase;
DWORD_PTR rvaTarget;
PIMAGE_SECTION_HEADER pSection;
pImageBase = (PBYTE) &__ImageBase;
if (! _ValidateImageBase (pImageBase))
return FALSE;
rvaTarget = pTarget - pImageBase;
pSection = _FindPESection (pImageBase, rvaTarget);
if (pSection == NULL)
return FALSE;
return (pSection->Characteristics & IMAGE_SCN_MEM_WRITE) == 0;
}

View file

@ -158,6 +158,87 @@ __report_error (const char *msg, ...)
#endif
}
/* For mingw-w64 we have additional helpers to get image information
on runtime. This allows us to cache for pseudo-relocation pass
the temporary access of code/read-only sections.
This step speeds up pseudo-relocation pass. */
#ifdef __MINGW64_VERSION_MAJOR
extern int __mingw_GetSectionCount (void);
extern PIMAGE_SECTION_HEADER __mingw_GetSectionForAddress (LPVOID p);
extern PBYTE _GetPEImageBase (void);
typedef struct sSecInfo {
/* Keeps altered section flags, or zero if nothing was changed. */
DWORD old_protect;
PBYTE sec_start;
PIMAGE_SECTION_HEADER hash;
} sSecInfo;
static sSecInfo *the_secs = NULL;
static int maxSections = 0;
static void
mark_section_writable (LPVOID addr)
{
MEMORY_BASIC_INFORMATION b;
PIMAGE_SECTION_HEADER h;
int i;
for (i = 0; i < maxSections; i++)
{
if (the_secs[i].sec_start <= ((LPBYTE) addr)
&& ((LPBYTE) addr) < (the_secs[i].sec_start + the_secs[i].hash->Misc.VirtualSize))
return;
}
h = __mingw_GetSectionForAddress (addr);
if (!h)
{
__report_error ("Address %p has no image-section", addr);
return;
}
the_secs[i].hash = h;
the_secs[i].old_protect = 0;
the_secs[i].sec_start = _GetPEImageBase () + h->VirtualAddress;
if (!VirtualQuery (the_secs[i].sec_start, &b, sizeof(b)))
{
__report_error (" VirtualQuery failed for %d bytes at address %p",
(int) h->Misc.VirtualSize, the_secs[i].sec_start);
return;
}
if (b.Protect != PAGE_EXECUTE_READWRITE && b.Protect != PAGE_READWRITE)
VirtualProtect (b.BaseAddress, b.RegionSize, PAGE_EXECUTE_READWRITE,
&the_secs[i].old_protect);
++maxSections;
return;
}
static void
restore_modified_sections (void)
{
int i;
MEMORY_BASIC_INFORMATION b;
DWORD oldprot;
for (i = 0; i < maxSections; i++)
{
if (the_secs[i].old_protect == 0)
continue;
if (!VirtualQuery (the_secs[i].sec_start, &b, sizeof(b)))
{
__report_error (" VirtualQuery failed for %d bytes at address %p",
(int) the_secs[i].hash->Misc.VirtualSize,
the_secs[i].sec_start);
return;
}
VirtualProtect (b.BaseAddress, b.RegionSize, the_secs[i].old_protect,
&oldprot);
}
}
#endif /* __MINGW64_VERSION_MAJOR */
/* 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.
@ -174,12 +255,15 @@ __report_error (const char *msg, ...)
static void
__write_memory (void *addr, const void *src, size_t len)
{
#ifndef __MINGW64_VERSION_MAJOR
MEMORY_BASIC_INFORMATION b;
DWORD oldprot;
#endif /* ! __MINGW64_VERSION_MAJOR */
if (!len)
return;
#ifndef __MINGW64_VERSION_MAJOR
if (!VirtualQuery (addr, &b, sizeof(b)))
{
__report_error (" VirtualQuery failed for %d bytes at address %p",
@ -189,12 +273,18 @@ __write_memory (void *addr, const void *src, size_t len)
/* 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);
&oldprot);
#else /* ! __MINGW64_VERSION_MAJOR */
mark_section_writable ((LPVOID) addr);
#endif /* __MINGW64_VERSION_MAJOR */
/* write the data. */
memcpy (addr, src, len);
/* Restore original protection. */
#ifndef __MINGW64_VERSION_MAJOR
if (b.Protect != PAGE_EXECUTE_READWRITE && b.Protect != PAGE_READWRITE)
VirtualProtect (b.BaseAddress, b.RegionSize, oldprot, &oldprot);
#endif /* !__MINGW64_VERSION_MAJOR */
}
#define RP_VERSION_V1 0
@ -361,10 +451,23 @@ void
_pei386_runtime_relocator (void)
{
static NO_COPY int was_init = 0;
#ifdef __MINGW64_VERSION_MAJOR
int mSecs;
#endif /* __MINGW64_VERSION_MAJOR */
if (was_init)
return;
++was_init;
#ifdef __MINGW64_VERSION_MAJOR
mSecs = __mingw_GetSectionCount ();
the_secs = (sSecInfo *) alloca (sizeof (sSecInfo) * (size_t) mSecs);
maxSections = 0;
#endif /* __MINGW64_VERSION_MAJOR */
do_pseudo_reloc (&__RUNTIME_PSEUDO_RELOC_LIST__,
&__RUNTIME_PSEUDO_RELOC_LIST_END__,
&__ImageBase);
&__MINGW_LSYMBOL(_image_base__));
#ifdef __MINGW64_VERSION_MAJOR
restore_modified_sections ();
#endif /* __MINGW64_VERSION_MAJOR */
}

View file

@ -50,18 +50,11 @@ _CRTALLOC(".tls$ZZZ") char _tls_end = 0;
_CRTALLOC(".CRT$XLA") PIMAGE_TLS_CALLBACK __xl_a = 0;
_CRTALLOC(".CRT$XLZ") PIMAGE_TLS_CALLBACK __xl_z = 0;
#ifdef _WIN64
_CRTALLOC(".tls") const IMAGE_TLS_DIRECTORY64 _tls_used = {
(ULONGLONG) &_tls_start+1, (ULONGLONG) &_tls_end, (ULONGLONG) &_tls_index,
(ULONGLONG) (&__xl_a+1), (ULONG) 0, (ULONG) 0
};
#else
_CRTALLOC(".tls") const IMAGE_TLS_DIRECTORY _tls_used = {
(ULONG)(ULONG_PTR) &_tls_start+1, (ULONG)(ULONG_PTR) &_tls_end,
(ULONG)(ULONG_PTR) &_tls_index, (ULONG)(ULONG_PTR) (&__xl_a+1),
(ULONG_PTR) &_tls_start+1, (ULONG_PTR) &_tls_end,
(ULONG_PTR) &_tls_index, (ULONG_PTR) (&__xl_a+1),
(ULONG) 0, (ULONG) 0
};
#endif
#ifndef __CRT_THREAD
#ifdef HAVE_ATTRIBUTE_THREAD
@ -99,6 +92,7 @@ BOOL WINAPI
__dyn_tls_init (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
{
_PVFV *pfunc;
uintptr_t ps;
#ifndef _WIN64
if (_winmajor < 4)
@ -135,8 +129,11 @@ __dyn_tls_init (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
return TRUE;
}
for (pfunc = &__xd_a + 1; pfunc != &__xd_z; ++pfunc)
ps = (uintptr_t) &__xd_a;
ps += sizeof (uintptr_t);
for ( ; ps != (uintptr_t) &__xd_z; ps += sizeof (uintptr_t))
{
pfunc = (_PVFV *) ps;
if (*pfunc != NULL)
(*pfunc)();
}