mingw: building and linking mingw32.lib

This commit is contained in:
Andrew Kelley 2019-07-10 14:13:00 -04:00
parent 1c7f21852f
commit ea90a3a9a1
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
37 changed files with 4269 additions and 11 deletions

View File

@ -7583,11 +7583,45 @@ set(ZIG_LIBC_FILES
"include/x86_64-linux-musl/bits/user.h"
"include/wasm32-freestanding-musl/bits/alltypes.h"
"include/wasm32-freestanding-musl/errno.h"
"mingw/crt/CRT_fp10.c"
"mingw/crt/_newmode.c"
"mingw/crt/charmax.c"
"mingw/crt/cinitexe.c"
"mingw/crt/crt0_c.c"
"mingw/crt/crt0_w.c"
"mingw/crt/crt_handler.c"
"mingw/crt/crtdll.c"
"mingw/crt/crtexe.c"
"mingw/crt/cxa_atexit.c"
"mingw/crt/dll_argv.c"
"mingw/crt/dllargv.c"
"mingw/crt/gccmain.c"
"mingw/crt/gs_support.c"
"mingw/crt/merr.c"
"mingw/crt/mingw_helpers.c"
"mingw/crt/natstart.c"
"mingw/crt/pesect.c"
"mingw/crt/pseudo-reloc-list.c"
"mingw/crt/pseudo-reloc.c"
"mingw/crt/tlsmcrt.c"
"mingw/crt/tlsmthread.c"
"mingw/crt/tlssup.c"
"mingw/crt/tlsthrd.c"
"mingw/crt/udll_argv.c"
"mingw/crt/udllargc.c"
"mingw/crt/wildcard.c"
"mingw/crt/xncommod.c"
"mingw/crt/xthdloc.c"
"mingw/crt/xtxtmode.c"
"mingw/def-include/.func.def.in.swp"
"mingw/def-include/.msvcrt-common.def.in.swp"
"mingw/def-include/func.def.in"
"mingw/def-include/msvcrt-common.def.in"
"mingw/include/config.h"
"mingw/include/internal.h"
"mingw/include/oscalls.h"
"mingw/include/sect_attribs.h"
"mingw/lib-common/msvcrt.def.in"
"musl/arch/aarch64/atomic_arch.h"
"musl/arch/aarch64/bits/alltypes.h.in"
"musl/arch/aarch64/bits/endian.h"

View File

@ -224,7 +224,7 @@ limitations in handling dllimport attribute. */
#ifndef __MSVCRT_VERSION__
/* High byte is the major version, low byte is the minor. */
# define __MSVCRT_VERSION__ 0x1400
# define __MSVCRT_VERSION__ 0x700
#endif

32
libc/mingw/crt/CRT_fp10.c Normal file
View File

@ -0,0 +1,32 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
void _fpreset (void);
void _fpreset (void)
{
#if defined(_ARM_) || defined(__arm__)
__asm__ __volatile__ (
"vmsr fpscr, %0\n\t" : : "r"(0 /* INITIAL_FPSCR */));
#elif defined(_ARM64_) || defined(__aarch64__)
__asm__ __volatile__ (
"msr fpcr, %0\n\t" : : "r"(0LL /* INITIAL_FPSCR */));
#else
#ifdef __GNUC__
__asm__ ("fninit");
#else /* msvc: */
__asm fninit;
#endif
#endif
}
#ifdef __GNUC__
void __attribute__ ((alias ("_fpreset"))) fpreset(void);
#else
void fpreset(void) {
_fpreset();
}
#endif

View File

@ -0,0 +1,7 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
int _newmode = 0;

22
libc/mingw/crt/charmax.c Normal file
View File

@ -0,0 +1,22 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#include <crtdefs.h>
#include <sect_attribs.h>
#include <corecrt_startup.h>
__declspec(dllimport) int __lconv_init (void);
int mingw_initcharmax = 0;
int _charmax = 255;
static int my_lconv_init(void)
{
return __lconv_init();
}
_CRTALLOC(".CRT$XIC") _PIFV __mingw_pinit = my_lconv_init;

13
libc/mingw/crt/cinitexe.c Normal file
View File

@ -0,0 +1,13 @@
#include <stdio.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 };
_CRTALLOC(".CRT$XCZ") _PVFV __xc_z[] = { NULL };

20
libc/mingw/crt/crt0_c.c Normal file
View File

@ -0,0 +1,20 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#include <windows.h>
extern HINSTANCE __mingw_winmain_hInstance;
extern LPSTR __mingw_winmain_lpCmdLine;
extern DWORD __mingw_winmain_nShowCmd;
/*ARGSUSED*/
int main (int __UNUSED_PARAM(flags),
char ** __UNUSED_PARAM(cmdline),
char ** __UNUSED_PARAM(inst))
{
return (int) WinMain (__mingw_winmain_hInstance, NULL,
__mingw_winmain_lpCmdLine, __mingw_winmain_nShowCmd);
}

25
libc/mingw/crt/crt0_w.c Normal file
View File

@ -0,0 +1,25 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#include <windows.h>
/* Do the UNICODE prototyping of WinMain. Be aware that in winbase.h WinMain is a macro
defined to wWinMain. */
int WINAPI wWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPWSTR lpCmdLine,int nShowCmd);
extern HINSTANCE __mingw_winmain_hInstance;
extern LPWSTR __mingw_winmain_lpCmdLine;
extern DWORD __mingw_winmain_nShowCmd;
int wmain (int, wchar_t **, wchar_t **);
/*ARGSUSED*/
int wmain (int __UNUSED_PARAM(flags),
wchar_t ** __UNUSED_PARAM(cmdline),
wchar_t ** __UNUSED_PARAM(inst))
{
return (int) wWinMain (__mingw_winmain_hInstance, NULL,
__mingw_winmain_lpCmdLine, __mingw_winmain_nShowCmd);
}

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 mingw-w64 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);
#if defined(__x86_64__) && !defined(_MSC_VER)
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;
}

151
libc/mingw/crt/cxa_atexit.c Normal file
View File

@ -0,0 +1,151 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#include <sect_attribs.h>
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <corecrt_startup.h>
#include <process.h>
typedef void (__thiscall * dtor_fn)(void*);
int __cxa_atexit(dtor_fn dtor, void *obj, void *dso);
int __cxa_thread_atexit(dtor_fn dtor, void *obj, void *dso);
typedef struct dtor_obj dtor_obj;
struct dtor_obj {
dtor_fn dtor;
void *obj;
dtor_obj *next;
};
HANDLE __dso_handle;
extern char __mingw_module_is_dll;
static CRITICAL_SECTION lock;
static int inited = 0;
static dtor_obj *global_dtors = NULL;
static __thread dtor_obj *tls_dtors = NULL;
int __cxa_atexit(dtor_fn dtor, void *obj, void *dso) {
if (!inited)
return 1;
assert(!dso || dso == &__dso_handle);
dtor_obj *handler = (dtor_obj *) calloc(1, sizeof(*handler));
if (!handler)
return 1;
handler->dtor = dtor;
handler->obj = obj;
EnterCriticalSection(&lock);
handler->next = global_dtors;
global_dtors = handler;
LeaveCriticalSection(&lock);
return 0;
}
static void run_dtor_list(dtor_obj **ptr) {
dtor_obj *list = *ptr;
while (list) {
list->dtor(list->obj);
dtor_obj *next = list->next;
free(list);
list = next;
}
*ptr = NULL;
}
int __cxa_thread_atexit(dtor_fn dtor, void *obj, void *dso) {
if (!inited)
return 1;
assert(!dso || dso == &__dso_handle);
dtor_obj *handler = (dtor_obj *) calloc(1, sizeof(*handler));
if (!handler)
return 1;
handler->dtor = dtor;
handler->obj = obj;
handler->next = tls_dtors;
tls_dtors = handler;
return 0;
}
static void WINAPI tls_atexit_callback(HANDLE __UNUSED_PARAM(hDllHandle), DWORD dwReason, LPVOID __UNUSED_PARAM(lpReserved)) {
if (dwReason == DLL_PROCESS_DETACH) {
run_dtor_list(&tls_dtors);
run_dtor_list(&global_dtors);
}
}
static void WINAPI tls_callback(HANDLE hDllHandle, DWORD dwReason, LPVOID __UNUSED_PARAM(lpReserved)) {
switch (dwReason) {
case DLL_PROCESS_ATTACH:
if (inited == 0) {
InitializeCriticalSection(&lock);
__dso_handle = hDllHandle;
/*
* We can only call _register_thread_local_exe_atexit_callback once
* in a process; if we call it a second time the process terminates.
* When DLLs are unloaded, this callback is invoked before we run the
* _onexit tables, but for exes, we need to ask this to be called before
* all other registered atexit functions.
* Since we are registered as a normal TLS callback, we will be called
* another time later as well, but that doesn't matter, it's safe to
* invoke this with DLL_PROCESS_DETACH twice.
*/
if (!__mingw_module_is_dll)
_register_thread_local_exe_atexit_callback(tls_atexit_callback);
}
inited = 1;
break;
case DLL_PROCESS_DETACH:
/*
* If there are other threads still running that haven't been detached,
* we don't attempt to run their destructors (MSVC doesn't either), but
* simply leak the destructor list and whatever resources the destructors
* would have released.
*
* From Vista onwards, we could have used FlsAlloc to get a TLS key that
* runs a destructor on each thread that has a value attached ot it, but
* since MSVC doesn't run destructors on other threads in this case,
* users shouldn't assume it and we don't attempt to do anything potentially
* risky about it. TL;DR, threads with pending TLS destructors for a DLL
* need to be joined before unloading the DLL.
*
* This gets called both when exiting cleanly (via exit or returning from
* main, or when a DLL is unloaded), and when exiting bypassing some of
* the cleanup, by calling _exit or ExitProcess. In the latter cases,
* destructors (both TLS and global) in loaded DLLs still get called,
* but only TLS destructors get called for the main executable, global
* variables' destructors don't run. (This matches what MSVC does with
* a dynamically linked CRT.)
*/
run_dtor_list(&tls_dtors);
if (__mingw_module_is_dll) {
/* For DLLs, run dtors when detached. For EXEs, run dtors via the
* thread local atexit callback, to make sure they don't run when
* exiting the process with _exit or ExitProcess. */
run_dtor_list(&global_dtors);
}
if (inited == 1) {
inited = 0;
DeleteCriticalSection(&lock);
}
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
run_dtor_list(&tls_dtors);
break;
}
}
_CRTALLOC(".CRT$XLE") PIMAGE_TLS_CALLBACK __xl_e = (PIMAGE_TLS_CALLBACK) tls_callback;

25
libc/mingw/crt/dll_argv.c Normal file
View File

@ -0,0 +1,25 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#ifdef CRTDLL
#undef CRTDLL
#endif
#include <internal.h>
extern int _dowildcard;
#ifdef WPRFLAG
int __CRTDECL
__wsetargv (void)
#else
int __CRTDECL
__setargv (void)
#endif
{
_dowildcard = 1;
return 0;
}

22
libc/mingw/crt/dllargv.c Normal file
View File

@ -0,0 +1,22 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#ifdef CRTDLL
#undef CRTDLL
#endif
#include <internal.h>
#ifdef WPRFLAG
int __CRTDECL
_wsetargv (void)
#else
int __CRTDECL
_setargv (void)
#endif
{
return 0;
}

85
libc/mingw/crt/gccmain.c Normal file
View File

@ -0,0 +1,85 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#include <windows.h>
#include <stdlib.h>
#include <setjmp.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
typedef void (*func_ptr) (void);
extern func_ptr __CTOR_LIST__[];
extern func_ptr __DTOR_LIST__[];
void __do_global_dtors (void);
void __do_global_ctors (void);
void __main (void);
void
__do_global_dtors (void)
{
static func_ptr *p = __DTOR_LIST__ + 1;
while (*p)
{
(*(p)) ();
p++;
}
}
#ifndef HAVE_CTOR_LIST
// If the linker didn't provide __CTOR_LIST__, we provided it ourselves,
// and then we also know we have __CTOR_END__ available.
extern func_ptr __CTOR_END__[];
extern func_ptr __DTOR_END__[];
void __do_global_ctors (void)
{
static func_ptr *p = __CTOR_END__ - 1;
while (*p != (func_ptr) -1) {
(*(p))();
p--;
}
atexit (__do_global_dtors);
}
#else
// old method that iterates the list twice because old linker scripts do not have __CTOR_END__
void
__do_global_ctors (void)
{
unsigned long nptrs = (unsigned long) (ptrdiff_t) __CTOR_LIST__[0];
unsigned long i;
if (nptrs == (unsigned long) -1)
{
for (nptrs = 0; __CTOR_LIST__[nptrs + 1] != 0; nptrs++);
}
for (i = nptrs; i >= 1; i--)
{
__CTOR_LIST__[i] ();
}
atexit (__do_global_dtors);
}
#endif
static int initialized = 0;
void
__main (void)
{
if (!initialized)
{
initialized = 1;
__do_global_ctors ();
}
}

154
libc/mingw/crt/gs_support.c Normal file
View File

@ -0,0 +1,154 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#define WIN32_NO_STATUS
#include <stdlib.h> /* abort () */
#include <windows.h>
#undef WIN32_NO_STATUS
#include <ntstatus.h> /* STATUS macros */
#ifdef _WIN64
#include <intrin.h>
#endif
#ifdef _WIN64
#define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232ll
#else
#define DEFAULT_SECURITY_COOKIE 0xBB40E64E
#endif
/* Externals. */
typedef LONG NTSTATUS; /* same as in ntdef.h / winternl.h */
#define UNW_FLAG_NHANDLER 0x0
typedef union
{
unsigned __int64 ft_scalar;
FILETIME ft_struct;
} FT;
static EXCEPTION_RECORD GS_ExceptionRecord;
static CONTEXT GS_ContextRecord;
static const EXCEPTION_POINTERS GS_ExceptionPointers = {
&GS_ExceptionRecord,&GS_ContextRecord
};
DECLSPEC_SELECTANY UINT_PTR __security_cookie = DEFAULT_SECURITY_COOKIE;
DECLSPEC_SELECTANY UINT_PTR __security_cookie_complement = ~(DEFAULT_SECURITY_COOKIE);
void __cdecl __security_init_cookie (void);
void __cdecl
__security_init_cookie (void)
{
UINT_PTR cookie;
FT systime = { 0, };
LARGE_INTEGER perfctr;
if (__security_cookie != DEFAULT_SECURITY_COOKIE)
{
__security_cookie_complement = ~__security_cookie;
return;
}
GetSystemTimeAsFileTime (&systime.ft_struct);
#ifdef _WIN64
cookie = systime.ft_scalar;
#else
cookie = systime.ft_struct.dwLowDateTime;
cookie ^= systime.ft_struct.dwHighDateTime;
#endif
cookie ^= GetCurrentProcessId ();
cookie ^= GetCurrentThreadId ();
cookie ^= GetTickCount ();
QueryPerformanceCounter (&perfctr);
#ifdef _WIN64
cookie ^= perfctr.QuadPart;
#else
cookie ^= perfctr.LowPart;
cookie ^= perfctr.HighPart;
#endif
#ifdef _WIN64
cookie &= 0x0000ffffffffffffll;
#endif
if (cookie == DEFAULT_SECURITY_COOKIE)
cookie = DEFAULT_SECURITY_COOKIE + 1;
__security_cookie = cookie;
__security_cookie_complement = ~cookie;
}
#if defined(__GNUC__) /* wrap msvc intrinsics onto gcc builtins */
#undef _ReturnAddress
#undef _AddressOfReturnAddress
#define _ReturnAddress() __builtin_return_address(0)
#define _AddressOfReturnAddress() __builtin_frame_address (0)
#endif /* __GNUC__ */
__declspec(noreturn) void __cdecl __report_gsfailure (ULONG_PTR);
#define UNUSED_PARAM(x) { x = x; }
__declspec(noreturn) void __cdecl
__report_gsfailure (ULONG_PTR StackCookie)
{
volatile UINT_PTR cookie[2] __MINGW_ATTRIB_UNUSED;
#if defined(_WIN64) && !defined(__aarch64__)
ULONG64 controlPC, imgBase, establisherFrame;
PRUNTIME_FUNCTION fctEntry;
PVOID hndData;
RtlCaptureContext (&GS_ContextRecord);
controlPC = GS_ContextRecord.Rip;
fctEntry = RtlLookupFunctionEntry (controlPC, &imgBase, NULL);
if (fctEntry != NULL)
{
RtlVirtualUnwind (UNW_FLAG_NHANDLER, imgBase, controlPC, fctEntry,
&GS_ContextRecord, &hndData, &establisherFrame, NULL);
}
else
#endif /* _WIN64 */
{
#if defined(__x86_64__) || defined(_AMD64_)
GS_ContextRecord.Rip = (ULONGLONG) _ReturnAddress();
GS_ContextRecord.Rsp = (ULONGLONG) _AddressOfReturnAddress() + 8;
#elif defined(__i386__) || defined(_X86_)
GS_ContextRecord.Eip = (DWORD) _ReturnAddress();
GS_ContextRecord.Esp = (DWORD) _AddressOfReturnAddress() + 4;
#elif defined(__arm__) || defined(_ARM_)
GS_ContextRecord.Pc = (DWORD) _ReturnAddress();
GS_ContextRecord.Sp = (DWORD) _AddressOfReturnAddress() + 4;
#endif /* _WIN64 */
}
#if defined(__x86_64__) || defined(_AMD64_)
GS_ExceptionRecord.ExceptionAddress = (PVOID) GS_ContextRecord.Rip;
GS_ContextRecord.Rcx = StackCookie;
#elif defined(__i386__) || defined(_X86_)
GS_ExceptionRecord.ExceptionAddress = (PVOID) GS_ContextRecord.Eip;
GS_ContextRecord.Ecx = StackCookie;
#elif defined(__arm__) || defined(_ARM_)
GS_ExceptionRecord.ExceptionAddress = (PVOID) GS_ContextRecord.Pc;
UNUSED_PARAM(StackCookie);
#endif /* _WIN64 */
GS_ExceptionRecord.ExceptionCode = STATUS_STACK_BUFFER_OVERRUN;
GS_ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
cookie[0] = __security_cookie;
cookie[1] = __security_cookie_complement;
SetUnhandledExceptionFilter (NULL);
UnhandledExceptionFilter ((EXCEPTION_POINTERS *) &GS_ExceptionPointers);
TerminateProcess (GetCurrentProcess (), STATUS_STACK_BUFFER_OVERRUN);
abort();
}

76
libc/mingw/crt/merr.c Normal file
View File

@ -0,0 +1,76 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#include <internal.h>
#include <math.h>
#include <stdio.h>
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 = (char*)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)
{
const char * type;
switch(pexcept->type)
{
case _DOMAIN:
type = "Argument domain error (DOMAIN)";
break;
case _SING:
type = "Argument singularity (SIGN)";
break;
case _OVERFLOW:
type = "Overflow range error (OVERFLOW)";
break;
case _PLOSS:
type = "Partial loss of significance (PLOSS)";
break;
case _TLOSS:
type = "Total loss of significance (TLOSS)";
break;
case _UNDERFLOW:
type = "The result is too small to be represented (UNDERFLOW)";
break;
default:
type = "Unknown error";
break;
}
fprintf (stderr, "_matherr(): %s in %s(%g, %g) (retval=%g)\n",
type, pexcept->name, pexcept->arg1, pexcept->arg2, pexcept->retval);
return 0;
}

View File

@ -0,0 +1,31 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#include <oscalls.h>
#include <internal.h>
#include <process.h>
#include <math.h>
#include <stdlib.h>
#include <tchar.h>
#include <sect_attribs.h>
#include <locale.h>
extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback;
void * __cdecl
_decode_pointer (void *codedptr)
{
return (void *) codedptr;
}
void * __cdecl
_encode_pointer (void *ptr)
{
return ptr;
}
/* 0:console, 1:windows. */
int mingw_app_type = 0;

14
libc/mingw/crt/natstart.c Normal file
View File

@ -0,0 +1,14 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#include <crtdefs.h>
#include <internal.h>
_PGLOBAL
volatile unsigned int __native_dllmain_reason = UINT_MAX;
volatile unsigned int __native_vcclrit_reason = UINT_MAX;
volatile __enative_startup_state __native_startup_state;
volatile void *__native_startup_lock;

230
libc/mingw/crt/pesect.c Normal file
View File

@ -0,0 +1,230 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 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
#ifdef __GNUC__
/* Hack, for bug in ld. Will be removed soon. */
#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;
}
const char *
__mingw_enum_import_library_names (int);
const char *
__mingw_enum_import_library_names (int i)
{
PBYTE pImageBase;
PIMAGE_NT_HEADERS pNTHeader;
PIMAGE_IMPORT_DESCRIPTOR importDesc;
PIMAGE_SECTION_HEADER pSection;
DWORD importsStartRVA;
pImageBase = (PBYTE) &__ImageBase;
if (! _ValidateImageBase (pImageBase))
return NULL;
pNTHeader = (PIMAGE_NT_HEADERS) (pImageBase + ((PIMAGE_DOS_HEADER) pImageBase)->e_lfanew);
importsStartRVA = pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
if (!importsStartRVA)
return NULL;
pSection = _FindPESection (pImageBase, importsStartRVA);
if (!pSection)
return NULL;
importDesc = (PIMAGE_IMPORT_DESCRIPTOR) (pImageBase + importsStartRVA);
if (!importDesc)
return NULL;
for (;;)
{
if (importDesc->TimeDateStamp == 0 && importDesc->Name == 0)
break;
if (i <= 0)
return (char *) (pImageBase + importDesc->Name);
--i;
importDesc++;
}
return NULL;
}

View File

@ -0,0 +1,8 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
char __RUNTIME_PSEUDO_RELOC_LIST_END__ = 0;
char __RUNTIME_PSEUDO_RELOC_LIST__ = 0;

View File

@ -0,0 +1,487 @@
/* 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>
#include <internal.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[PATH_MAX];
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, PATH_MAX);
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");
vfprintf (stderr, msg, argp);
# else
fprintf (stderr, "Mingw runtime failure:\n");
vfprintf (stderr, msg, argp);
#endif
va_end (argp);
abort ();
#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;
PVOID base_address;
SIZE_T region_size;
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
&& b.Protect != PAGE_EXECUTE_WRITECOPY && b.Protect != PAGE_WRITECOPY)
{
the_secs[i].base_address = b.BaseAddress;
the_secs[i].region_size = b.RegionSize;
if (!VirtualProtect (b.BaseAddress, b.RegionSize,
PAGE_EXECUTE_READWRITE,
&the_secs[i].old_protect))
__report_error (" VirtualProtect failed with code 0x%x",
(int) GetLastError ());
}
++maxSections;
return;
}
static void
restore_modified_sections (void)
{
int i;
DWORD oldprot;
for (i = 0; i < maxSections; i++)
{
if (the_secs[i].old_protect == 0)
continue;
VirtualProtect (the_secs[i].base_address, the_secs[i].region_size,
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.
*
* 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)
{
if (!len)
return;
#ifdef __MINGW64_VERSION_MAJOR
/* Mark the section writable once, and unset it in
* restore_modified_sections */
mark_section_writable ((LPVOID) addr);
#else
MEMORY_BASIC_INFORMATION b;
DWORD oldprot = 0;
int call_unprotect = 0;
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
&& b.Protect != PAGE_WRITECOPY && b.Protect != PAGE_EXECUTE_WRITECOPY)
{
call_unprotect = 1;
VirtualProtect (b.BaseAddress, b.RegionSize, PAGE_EXECUTE_READWRITE,
&oldprot);
}
#endif
/* write the data. */
memcpy (addr, src, len);
#ifndef __MINGW64_VERSION_MAJOR
/* Restore original protection. */
if (call_unprotect
&& b.Protect != PAGE_EXECUTE_READWRITE && b.Protect != PAGE_READWRITE
&& b.Protect != PAGE_WRITECOPY && b.Protect != PAGE_EXECUTE_WRITECOPY)
VirtualProtect (b.BaseAddress, b.RegionSize, oldprot, &oldprot);
#endif
}
#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;
#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__,
#ifdef __GNUC__
&__MINGW_LSYMBOL(_image_base__)
#else
&__ImageBase
#endif
);
#ifdef __MINGW64_VERSION_MAJOR
restore_modified_sections ();
#endif /* __MINGW64_VERSION_MAJOR */
}

13
libc/mingw/crt/tlsmcrt.c Normal file
View File

@ -0,0 +1,13 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*
* Written by Kai Tietz <kai.tietz@onevision.com>
*/
/* We support TLS cleanup code in any case. If shared version of libgcc is used _CRT_MT has value 1,
otherwise
we do tls cleanup in runtime and _CRT_MT has value 2. */
int _CRT_MT = 2;

View File

@ -0,0 +1,33 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*
* Written by Kai Tietz <kai.tietz@onevision.com>
*/
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <stdlib.h>
int __mingwthr_key_dtor (DWORD key, void (*dtor)(void *));
int __mingwthr_remove_key_dtor (DWORD key);
extern int ___w64_mingwthr_remove_key_dtor (DWORD key);
extern int ___w64_mingwthr_add_key_dtor (DWORD key, void (*dtor)(void *));
int
__mingwthr_remove_key_dtor (DWORD key)
{
return ___w64_mingwthr_remove_key_dtor (key);
}
int
__mingwthr_key_dtor (DWORD key, void (*dtor)(void *))
{
if (dtor)
return ___w64_mingwthr_add_key_dtor (key, dtor);
return 0;
}

175
libc/mingw/crt/tlssup.c Normal file
View File

@ -0,0 +1,175 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*
* Written by Kai Tietz <kai.tietz@onevision.com>
*/
#ifdef CRTDLL
#undef CRTDLL
#endif
#include <sect_attribs.h>
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <stdio.h>
#include <memory.h>
#include <malloc.h>
#include <corecrt_startup.h>
extern WINBOOL __mingw_TLScallback (HANDLE hDllHandle, DWORD reason, LPVOID reserved);
#define FUNCS_PER_NODE 30
typedef struct TlsDtorNode {
int count;
struct TlsDtorNode *next;
_PVFV funcs[FUNCS_PER_NODE];
} TlsDtorNode;
ULONG _tls_index = 0;
/* TLS raw template data start and end.
We use here pointer-types for start/end so that tls-data remains
aligned on pointer-size-width. This seems to be required for
pe-loader. */
_CRTALLOC(".tls") char *_tls_start = NULL;
_CRTALLOC(".tls$ZZZ") char *_tls_end = NULL;
_CRTALLOC(".CRT$XLA") PIMAGE_TLS_CALLBACK __xl_a = 0;
_CRTALLOC(".CRT$XLZ") PIMAGE_TLS_CALLBACK __xl_z = 0;
const IMAGE_TLS_DIRECTORY _tls_used = {
(ULONG_PTR) &_tls_start, (ULONG_PTR) &_tls_end,
(ULONG_PTR) &_tls_index, (ULONG_PTR) (&__xl_a+1),
(ULONG) 0, (ULONG) 0
};
#ifndef __CRT_THREAD
#ifdef HAVE_ATTRIBUTE_THREAD
#define __CRT_THREAD __declspec(thread)
#else
#define __CRT_THREAD __thread
#endif
#endif
#define DISABLE_MS_TLS 1
static _CRTALLOC(".CRT$XDA") _PVFV __xd_a = 0;
static _CRTALLOC(".CRT$XDZ") _PVFV __xd_z = 0;
#if !defined (DISABLE_MS_TLS)
static __CRT_THREAD TlsDtorNode *dtor_list;
static __CRT_THREAD TlsDtorNode dtor_list_head;
#endif
extern int _CRT_MT;
BOOL WINAPI __dyn_tls_init (HANDLE, DWORD, LPVOID);
BOOL WINAPI
__dyn_tls_init (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
{
_PVFV *pfunc;
uintptr_t ps;
/* We don't let us trick here. */
if (_CRT_MT != 2)
_CRT_MT = 2;
if (dwReason != DLL_THREAD_ATTACH)
{
if (dwReason == DLL_PROCESS_ATTACH)
__mingw_TLScallback (hDllHandle, dwReason, lpreserved);
return TRUE;
}
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)();
}
return TRUE;
}
const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback = (const PIMAGE_TLS_CALLBACK) __dyn_tls_init;
_CRTALLOC(".CRT$XLC") PIMAGE_TLS_CALLBACK __xl_c = (PIMAGE_TLS_CALLBACK) __dyn_tls_init;
int __cdecl __tlregdtor (_PVFV);
int __cdecl
__tlregdtor (_PVFV func)
{
if (!func)
return 0;
#if !defined (DISABLE_MS_TLS)
if (dtor_list == NULL)
{
dtor_list = &dtor_list_head;
dtor_list_head.count = 0;
}
else if (dtor_list->count == FUNCS_PER_NODE)
{
TlsDtorNode *pnode = (TlsDtorNode *) malloc (sizeof (TlsDtorNode));
if (pnode == NULL)
return -1;
pnode->count = 0;
pnode->next = dtor_list;
dtor_list = pnode;
dtor_list->count = 0;
}
dtor_list->funcs[dtor_list->count++] = func;
#endif
return 0;
}
static BOOL WINAPI
__dyn_tls_dtor (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
{
#if !defined (DISABLE_MS_TLS)
TlsDtorNode *pnode, *pnext;
int i;
#endif
if (dwReason != DLL_THREAD_DETACH && dwReason != DLL_PROCESS_DETACH)
return TRUE;
/* As TLS variables are detroyed already by DLL_THREAD_DETACH
call, we have to avoid access on the possible DLL_PROCESS_DETACH
call the already destroyed TLS vars.
TODO: The used local thread based variables have to be handled
manually, so that we can control their lifetime here. */
#if !defined (DISABLE_MS_TLS)
if (dwReason != DLL_PROCESS_DETACH)
{
for (pnode = dtor_list; pnode != NULL; pnode = pnext)
{
for (i = pnode->count - 1; i >= 0; --i)
{
if (pnode->funcs[i] != NULL)
(*pnode->funcs[i])();
}
pnext = pnode->next;
if (pnext != NULL)
free ((void *) pnode);
}
}
#endif
__mingw_TLScallback (hDllHandle, dwReason, lpreserved);
return TRUE;
}
_CRTALLOC(".CRT$XLD") PIMAGE_TLS_CALLBACK __xl_d = (PIMAGE_TLS_CALLBACK) __dyn_tls_dtor;
int mingw_initltsdrot_force = 0;
int mingw_initltsdyn_force = 0;
int mingw_initltssuo_force = 0;

158
libc/mingw/crt/tlsthrd.c Normal file
View File

@ -0,0 +1,158 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*
* Written by Kai Tietz <kai.tietz@onevision.com>
*
* This file is used by if gcc is built with --enable-threads=win32.
*
* Based on version created by Mumit Khan <khan@nanotech.wisc.edu>
*
*/
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <stdlib.h>
extern void __cdecl __MINGW_NOTHROW _fpreset (void);
WINBOOL __mingw_TLScallback (HANDLE hDllHandle, DWORD reason, LPVOID reserved);
int ___w64_mingwthr_remove_key_dtor (DWORD key);
int ___w64_mingwthr_add_key_dtor (DWORD key, void (*dtor)(void *));
/* To protect the thread/key association data structure modifications. */
static CRITICAL_SECTION __mingwthr_cs;
static volatile int __mingwthr_cs_init = 0;
typedef struct __mingwthr_key __mingwthr_key_t;
/* The list of threads active with key/dtor pairs. */
struct __mingwthr_key {
DWORD key;
void (*dtor)(void *);
__mingwthr_key_t volatile *next;
};
static __mingwthr_key_t volatile *key_dtor_list;
int
___w64_mingwthr_add_key_dtor (DWORD key, void (*dtor)(void *))
{
__mingwthr_key_t *new_key;
if (__mingwthr_cs_init == 0)
return 0;
new_key = (__mingwthr_key_t *) calloc (1, sizeof (__mingwthr_key_t));
if (new_key == NULL)
return -1;
new_key->key = key;
new_key->dtor = dtor;
EnterCriticalSection (&__mingwthr_cs);
new_key->next = key_dtor_list;
key_dtor_list = new_key;
LeaveCriticalSection (&__mingwthr_cs);
return 0;
}
int
___w64_mingwthr_remove_key_dtor (DWORD key)
{
__mingwthr_key_t volatile *prev_key;
__mingwthr_key_t volatile *cur_key;
if (__mingwthr_cs_init == 0)
return 0;
EnterCriticalSection (&__mingwthr_cs);
prev_key = NULL;
cur_key = key_dtor_list;
while (cur_key != NULL)
{
if ( cur_key->key == key)
{
if (prev_key == NULL)
key_dtor_list = cur_key->next;
else
prev_key->next = cur_key->next;
free ((void*)cur_key);
break;
}
prev_key = cur_key;
cur_key = cur_key->next;
}
LeaveCriticalSection (&__mingwthr_cs);
return 0;
}
static void
__mingwthr_run_key_dtors (void)
{
__mingwthr_key_t volatile *keyp;
if (__mingwthr_cs_init == 0)
return;
EnterCriticalSection (&__mingwthr_cs);
for (keyp = key_dtor_list; keyp; )
{
LPVOID value = TlsGetValue (keyp->key);
if (GetLastError () == ERROR_SUCCESS)
{
if (value)
(*keyp->dtor) (value);
}
keyp = keyp->next;
}
LeaveCriticalSection (&__mingwthr_cs);
}
WINBOOL
__mingw_TLScallback (HANDLE __UNUSED_PARAM(hDllHandle),
DWORD reason,
LPVOID __UNUSED_PARAM(reserved))
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
if (__mingwthr_cs_init == 0)
InitializeCriticalSection (&__mingwthr_cs);
__mingwthr_cs_init = 1;
break;
case DLL_PROCESS_DETACH:
__mingwthr_run_key_dtors();
if (__mingwthr_cs_init == 1)
{
__mingwthr_key_t volatile *keyp, *t;
for (keyp = key_dtor_list; keyp; )
{
t = keyp->next;
free((void *)keyp);
keyp = t;
}
key_dtor_list = NULL;
__mingwthr_cs_init = 0;
DeleteCriticalSection (&__mingwthr_cs);
}
break;
case DLL_THREAD_ATTACH:
_fpreset();
break;
case DLL_THREAD_DETACH:
__mingwthr_run_key_dtors();
break;
}
return TRUE;
}

View File

@ -0,0 +1,16 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
#define WPRFLAG 1
#include "dll_argv.c"

16
libc/mingw/crt/udllargc.c Normal file
View File

@ -0,0 +1,16 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
#define WPRFLAG 1
#include "dllargv.c"

33
libc/mingw/crt/wildcard.c Normal file
View File

@ -0,0 +1,33 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
/* _dowildcard is an int that controls the globbing of the command line.
* If _dowildcard is non-zero, the command line will be globbed: *.*
* will be expanded to be all files in the startup directory.
*
* In the mingw-w64 library the _dowildcard variable is defined as being
* 0, therefore command line globbing is DISABLED by default. To turn it
* on and to leave wildcard command line processing MS's globbing code,
* include a line in one of your source modules defining _dowildcard and
* setting it to -1, like so:
* int _dowildcard = -1;
*
* Alternatively, the mingw-w64 library can be configured using the
* --enable-wildcard option and compiled thusly upon which the resulting
* library will have _dowildcard as -1 and command line globbing will be
* enabled by default.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifndef __ENABLE_GLOBBING
#define __ENABLE_GLOBBING 0 /* -1 */
#endif
int _dowildcard = __ENABLE_GLOBBING;

View File

@ -0,0 +1,7 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
int _commode = 0;

7
libc/mingw/crt/xthdloc.c Normal file
View File

@ -0,0 +1,7 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
int __globallocalestatus = ~0x1;

View File

@ -0,0 +1,6 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
int _fmode = 0;

View File

@ -0,0 +1,57 @@
// F32 - function available on all 32 bit architectures
// F64 - function available on all 64 bit architectures
// F_X86_ANY - function available on i386 and x86_64
// F_I386 - function available only on i386
// F_X64 - function available only on x86_64
// F_ARM32 - function available only on arm32
// F_ARM64 - function available only on arm64
// F_ARM_ANY - function available on 32 and 64 bit arm
// F_NON_I386 - function available on everything but i386
#if defined(DEF_X64)
#define F64(x) x
#define F_X64(x) x
#define F_X86_ANY(x) x
#define F_NON_I386(x) x
#elif defined(DEF_I386)
#define F32(x) x
#define F_I386(x) x
#define F_X86_ANY(x) x
#elif defined(DEF_ARM32)
#define F32(x) x
#define F_ARM32(x) x
#define F_ARM_ANY(x) x
#define F_NON_I386(x) x
#elif defined(DEF_ARM64)
#define F64(x) x
#define F_ARM64(x) x
#define F_ARM_ANY(x) x
#define F_NON_I386(x) x
#endif
#ifndef F32
#define F32(x)
#endif
#ifndef F64
#define F64(x)
#endif
#ifndef F_X86_ANY
#define F_X86_ANY(x)
#endif
#ifndef F_I386
#define F_I386(x)
#endif
#ifndef F_X64
#define F_X64(x)
#endif
#ifndef F_ARM_ANY
#define F_ARM_ANY(x)
#endif
#ifndef F_ARM32
#define F_ARM32(x)
#endif
#ifndef F_ARM64
#define F_ARM64(x)
#endif
#ifndef F_NON_I386
#define F_NON_I386(x)
#endif

View File

@ -0,0 +1,145 @@
#define ADD_UNDERSCORE(symbol) symbol == _ ## symbol
#define ADD_DOUBLE_UNDERSCORE(symbol) symbol == __ ## symbol
ADD_DOUBLE_UNDERSCORE(iscsymf)
ADD_DOUBLE_UNDERSCORE(iscsym)
ADD_DOUBLE_UNDERSCORE(isascii)
ADD_DOUBLE_UNDERSCORE(toascii)
wcscmpi == _wcsicmp
strcasecmp == _stricmp
strncasecmp == _strnicmp
ADD_UNDERSCORE(access)
ADD_UNDERSCORE(chdir)
ADD_UNDERSCORE(chmod)
ADD_UNDERSCORE(chsize)
ADD_UNDERSCORE(close)
ADD_UNDERSCORE(creat)
ADD_UNDERSCORE(cwait)
ADD_UNDERSCORE(dup)
ADD_UNDERSCORE(dup2)
ADD_UNDERSCORE(ecvt)
ADD_UNDERSCORE(eof)
ADD_UNDERSCORE(execl)
ADD_UNDERSCORE(execle)
ADD_UNDERSCORE(execlp)
ADD_UNDERSCORE(execlpe)
ADD_UNDERSCORE(execv)
ADD_UNDERSCORE(execve)
ADD_UNDERSCORE(execvp)
ADD_UNDERSCORE(execvpe)
ADD_UNDERSCORE(fcvt)
ADD_UNDERSCORE(fdopen)
ADD_UNDERSCORE(fgetchar)
ADD_UNDERSCORE(fgetwchar)
ADD_UNDERSCORE(filelength)
ADD_UNDERSCORE(fileno)
; fpreset)
ADD_UNDERSCORE(fputchar)
ADD_UNDERSCORE(fputwchar)
;fstat)
;ftime)
ADD_UNDERSCORE(gcvt)
ADD_UNDERSCORE(getch)
ADD_UNDERSCORE(getche)
ADD_UNDERSCORE(getcwd)
ADD_UNDERSCORE(getpid)
ADD_UNDERSCORE(getw)
ADD_UNDERSCORE(heapwalk)
ADD_UNDERSCORE(isatty)
ADD_UNDERSCORE(itoa)
ADD_UNDERSCORE(kbhit)
ADD_UNDERSCORE(lfind)
ADD_UNDERSCORE(lsearch)
ADD_UNDERSCORE(lseek)
ADD_UNDERSCORE(ltoa)
ADD_UNDERSCORE(memccpy)
ADD_UNDERSCORE(memicmp)
ADD_UNDERSCORE(mkdir)
ADD_UNDERSCORE(mktemp)
ADD_UNDERSCORE(open)
ADD_UNDERSCORE(pclose)
ADD_UNDERSCORE(popen)
ADD_UNDERSCORE(putch)
ADD_UNDERSCORE(putenv)
ADD_UNDERSCORE(putw)
ADD_UNDERSCORE(read)
ADD_UNDERSCORE(rmdir)
ADD_UNDERSCORE(rmtmp)
ADD_UNDERSCORE(searchenv)
ADD_UNDERSCORE(setmode)
ADD_UNDERSCORE(sopen)
ADD_UNDERSCORE(spawnl)
ADD_UNDERSCORE(spawnle)
ADD_UNDERSCORE(spawnlp)
ADD_UNDERSCORE(spawnlpe)
ADD_UNDERSCORE(spawnv)
ADD_UNDERSCORE(spawnve)
ADD_UNDERSCORE(spawnvp)
ADD_UNDERSCORE(spawnvpe)
;stat)
#ifndef UCRTBASE
ADD_UNDERSCORE(strcmpi)
#endif
ADD_UNDERSCORE(strdup)
ADD_UNDERSCORE(stricmp)
ADD_UNDERSCORE(stricoll)
ADD_UNDERSCORE(strlwr)
ADD_UNDERSCORE(strnicmp)
ADD_UNDERSCORE(strnset)
ADD_UNDERSCORE(strrev)
ADD_UNDERSCORE(strset)
ADD_UNDERSCORE(strupr)
ADD_UNDERSCORE(swab)
ADD_UNDERSCORE(tell)
ADD_UNDERSCORE(tempnam)
#ifndef UCRTBASE
ADD_UNDERSCORE(tzset)
#endif
ADD_UNDERSCORE(umask)
ADD_UNDERSCORE(ungetch)
ADD_UNDERSCORE(unlink)
#ifndef UCRTBASE
ADD_UNDERSCORE(utime)
#endif
ADD_UNDERSCORE(wcsdup)
ADD_UNDERSCORE(wcsicmp)
ADD_UNDERSCORE(wcsicoll)
ADD_UNDERSCORE(wcslwr)
ADD_UNDERSCORE(wcsnicmp)
ADD_UNDERSCORE(wcsnset)
ADD_UNDERSCORE(wcsrev)
ADD_UNDERSCORE(wcsset)
ADD_UNDERSCORE(wcsupr)
ADD_UNDERSCORE(wpopen)
ADD_UNDERSCORE(write)
; non-ANSI functions declared in math.h
ADD_UNDERSCORE(j0)
ADD_UNDERSCORE(j1)
ADD_UNDERSCORE(jn)
ADD_UNDERSCORE(y0)
ADD_UNDERSCORE(y1)
ADD_UNDERSCORE(yn)
ADD_UNDERSCORE(chgsign)
;scalb
ADD_UNDERSCORE(finite)
ADD_UNDERSCORE(fpclass)
; C99 functions
;cabs
ADD_UNDERSCORE(hypot)
;logb
ADD_UNDERSCORE(nextafter)
#ifndef UCRTBASE
_daylight DATA
_timezone DATA
_tzname DATA
ADD_UNDERSCORE(daylight)
ADD_UNDERSCORE(timezone)
ADD_UNDERSCORE(tzname)
ADD_UNDERSCORE(vsnprintf_s)
longjmp DATA
#endif

View File

@ -0,0 +1,74 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Whether the linker provides __CTOR_LIST__ */
/* #undef HAVE_CTOR_LIST */
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Name of package */
#define PACKAGE "mingw-w64-runtime"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "mingw-w64-public@lists.sourceforge.net"
/* Define to the full name of this package. */
#define PACKAGE_NAME "mingw-w64-runtime"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "mingw-w64-runtime 4.0b"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "mingw-w64-runtime"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "4.0b"
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Version number of package */
#define VERSION "4.0b"
/* Build DFP support */
/* #undef __ENABLE_DFP */
/* Define as -1 to enable command line globbing or 0 to disable it. */
#define __ENABLE_GLOBBING 0
/* Build DFP support */
/* #undef __ENABLE_PRINTF128 */
/* Build DFP support */
/* #undef __ENABLE_REGISTEREDPRINTF */
/* Build softmath routines */
/* #undef __ENABLE_SOFTMATH */

File diff suppressed because it is too large Load Diff

View File

@ -9698,10 +9698,14 @@ void codegen_build_and_link(CodeGen *g) {
}
}
codegen_release_caches(g);
codegen_add_time_event(g, "Done");
}
void codegen_release_caches(CodeGen *g) {
while (g->caches_to_release.length != 0) {
cache_release(g->caches_to_release.pop());
}
codegen_add_time_event(g, "Done");
}
ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const char *root_src_path,

View File

@ -61,4 +61,6 @@ Buf *codegen_generate_builtin_source(CodeGen *g);
TargetSubsystem detect_subsystem(CodeGen *g);
void codegen_release_caches(CodeGen *codegen);
#endif

View File

@ -573,17 +573,18 @@ static const char *build_musl(CodeGen *parent) {
static const char *get_libc_crt_file(CodeGen *parent, const char *file) {
if (parent->libc == nullptr && parent->zig_target->os == OsWindows) {
if (strcmp(file, "crt2u.obj") == 0) {
if (strcmp(file, "crt2.obj") == 0) {
CFile *c_file = allocate<CFile>(1);
c_file->source_path = buf_ptr(buf_sprintf(
"%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "crt" OS_SEP "crtexe.c", buf_ptr(parent->zig_lib_dir)));
mingw_add_cc_args(parent, c_file);
c_file->args.append("-U__CRTDLL__");
c_file->args.append("-D__MSVCRT__");
c_file->args.append("-DUNICODE");
c_file->args.append("-D_UNICODE");
c_file->args.append("-DWPRFLAG=1");
return build_libc_object(parent, "crt2u", c_file);
// Uncomment these 3 things for crtu
//c_file->args.append("-DUNICODE");
//c_file->args.append("-D_UNICODE");
//c_file->args.append("-DWPRFLAG=1");
return build_libc_object(parent, "crt2", c_file);
} else if (strcmp(file, "dllcrt2.obj") == 0) {
CFile *c_file = allocate<CFile>(1);
c_file->source_path = buf_ptr(buf_sprintf(
@ -592,6 +593,64 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) {
c_file->args.append("-U__CRTDLL__");
c_file->args.append("-D__MSVCRT__");
return build_libc_object(parent, "dllcrt2", c_file);
} else if (strcmp(file, "mingw32.lib") == 0) {
CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr);
codegen_set_out_name(child_gen, buf_create_from_str("mingw32"));
static const char *deps[] = {
"mingw" OS_SEP "crt" OS_SEP "crt0_c.c",
"mingw" OS_SEP "crt" OS_SEP "dll_argv.c",
"mingw" OS_SEP "crt" OS_SEP "gccmain.c",
"mingw" OS_SEP "crt" OS_SEP "natstart.c",
"mingw" OS_SEP "crt" OS_SEP "pseudo-reloc-list.c",
"mingw" OS_SEP "crt" OS_SEP "wildcard.c",
"mingw" OS_SEP "crt" OS_SEP "charmax.c",
"mingw" OS_SEP "crt" OS_SEP "crt0_w.c",
"mingw" OS_SEP "crt" OS_SEP "dllargv.c",
"mingw" OS_SEP "crt" OS_SEP "gs_support.c",
"mingw" OS_SEP "crt" OS_SEP "_newmode.c",
"mingw" OS_SEP "crt" OS_SEP "tlssup.c",
"mingw" OS_SEP "crt" OS_SEP "xncommod.c",
"mingw" OS_SEP "crt" OS_SEP "cinitexe.c",
"mingw" OS_SEP "crt" OS_SEP "merr.c",
"mingw" OS_SEP "crt" OS_SEP "pesect.c",
"mingw" OS_SEP "crt" OS_SEP "udllargc.c",
"mingw" OS_SEP "crt" OS_SEP "xthdloc.c",
"mingw" OS_SEP "crt" OS_SEP "CRT_fp10.c",
"mingw" OS_SEP "crt" OS_SEP "mingw_helpers.c",
"mingw" OS_SEP "crt" OS_SEP "pseudo-reloc.c",
"mingw" OS_SEP "crt" OS_SEP "udll_argv.c",
"mingw" OS_SEP "crt" OS_SEP "xtxtmode.c",
"mingw" OS_SEP "crt" OS_SEP "crt_handler.c",
"mingw" OS_SEP "crt" OS_SEP "tlsthrd.c",
"mingw" OS_SEP "crt" OS_SEP "tlsmthread.c",
"mingw" OS_SEP "crt" OS_SEP "tlsmcrt.c",
"mingw" OS_SEP "crt" OS_SEP "cxa_atexit.c",
};
for (size_t i = 0; i < array_length(deps); i += 1) {
CFile *c_file = allocate<CFile>(1);
c_file->source_path = path_from_libc(parent, deps[i]);
c_file->args.append("-DHAVE_CONFIG_H");
c_file->args.append("-D_SYSCRT=1");
c_file->args.append("-DCRTDLL=1");
c_file->args.append("-isystem");
c_file->args.append(path_from_libc(parent, "include" OS_SEP "any-windows-any"));
c_file->args.append("-I");
c_file->args.append(path_from_libc(parent, "mingw" OS_SEP "include" OS_SEP));
c_file->args.append("-std=gnu99");
c_file->args.append("-D_CRTBLD");
c_file->args.append("-D_WIN32_WINNT=0x0f00");
c_file->args.append("-D__MSVCRT_VERSION__=0x700");
c_file->args.append("-g");
c_file->args.append("-O2");
child_gen->c_source_files.append(c_file);
}
codegen_build_and_link(child_gen);
return buf_ptr(&child_gen->output_file_path);
} else {
zig_unreachable();
}
@ -1154,8 +1213,12 @@ static void coff_append_machine_arg(CodeGen *g, ZigList<const char *> *list) {
list->append("-MACHINE:X86");
} else if (g->zig_target->arch == ZigLLVM_x86_64) {
list->append("-MACHINE:X64");
} else if (g->zig_target->arch == ZigLLVM_arm) {
list->append("-MACHINE:ARM");
} else if (target_is_arm(g->zig_target)) {
if (target_arch_pointer_bit_width(g->zig_target->arch) == 32) {
list->append("-MACHINE:ARM");
} else {
list->append("-MACHINE:ARM64");
}
}
}
@ -1223,9 +1286,150 @@ static const char *get_libc_static_file(ZigLibCInstallation *lib, const char *fi
return buf_ptr(out_buf);
}
static void print_zig_cc_cmd(const char *zig_exe, ZigList<const char *> *args) {
fprintf(stderr, "%s", zig_exe);
for (size_t arg_i = 0; arg_i < args->length; arg_i += 1) {
fprintf(stderr, " %s", args->at(arg_i));
}
fprintf(stderr, "\n");
}
static const char *get_def_lib(CodeGen *parent, const char *name, const char *def_in_rel_path) {
Error err;
Buf *self_exe_path = buf_alloc();
if ((err = os_self_exe_path(self_exe_path))) {
fprintf(stderr, "Unable to get self exe path: %s\n", err_str(err));
exit(1);
}
Buf *compiler_id;
if ((err = get_compiler_id(&compiler_id))) {
fprintf(stderr, "Unable to get compiler id: %s\n", err_str(err));
exit(1);
}
Buf *cache_dir = get_stage1_cache_path();
Buf *o_dir = buf_sprintf("%s" OS_SEP CACHE_OUT_SUBDIR, buf_ptr(cache_dir));
Buf *manifest_dir = buf_sprintf("%s" OS_SEP CACHE_HASH_SUBDIR, buf_ptr(cache_dir));
Buf *def_in_file = buf_sprintf("%s" OS_SEP "libc" OS_SEP "%s", buf_ptr(parent->zig_lib_dir), def_in_rel_path);
Buf *def_include_dir = buf_sprintf("%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "def-include",
buf_ptr(parent->zig_lib_dir));
CacheHash *cache_hash = allocate<CacheHash>(1);
cache_init(cache_hash, manifest_dir);
cache_buf(cache_hash, compiler_id);
cache_file(cache_hash, def_in_file);
cache_buf(cache_hash, def_include_dir);
cache_int(cache_hash, parent->zig_target->arch);
Buf digest = BUF_INIT;
buf_resize(&digest, 0);
if ((err = cache_hit(cache_hash, &digest))) {
if (err != ErrorInvalidFormat) {
if (err == ErrorCacheUnavailable) {
// already printed error
} else {
fprintf(stderr, "unable to check cache when processing .def.in file: %s\n", err_str(err));
}
exit(1);
}
}
Buf *artifact_dir;
Buf *lib_final_path;
Buf *final_lib_basename = buf_sprintf("%s.lib", name);
bool is_cache_miss = (buf_len(&digest) == 0);
if (is_cache_miss) {
if ((err = cache_final(cache_hash, &digest))) {
fprintf(stderr, "Unable to finalize cache hash: %s\n", err_str(err));
exit(1);
}
artifact_dir = buf_alloc();
os_path_join(o_dir, &digest, artifact_dir);
if ((err = os_make_path(artifact_dir))) {
fprintf(stderr, "Unable to create output directory '%s': %s",
buf_ptr(artifact_dir), err_str(err));
exit(1);
}
Buf *final_def_basename = buf_sprintf("%s.def", name);
Buf *def_final_path = buf_alloc();
os_path_join(artifact_dir, final_def_basename, def_final_path);
ZigList<const char *> args = {};
args.append(buf_ptr(self_exe_path));
args.append("cc");
args.append("-x");
args.append("c");
args.append(buf_ptr(def_in_file));
args.append("-Wp,-w");
args.append("-undef");
args.append("-P");
args.append("-I");
args.append(buf_ptr(def_include_dir));
if (target_is_arm(parent->zig_target)) {
if (target_arch_pointer_bit_width(parent->zig_target->arch) == 32) {
args.append("-DDEF_ARM32");
} else {
args.append("-DDEF_ARM64");
}
} else if (parent->zig_target->arch == ZigLLVM_x86) {
args.append("-DDEF_I386");
} else if (parent->zig_target->arch == ZigLLVM_x86_64) {
args.append("-DDEF_X64");
} else {
zig_unreachable();
}
args.append("-E");
args.append("-o");
args.append(buf_ptr(def_final_path));
if (parent->verbose_cc) {
print_zig_cc_cmd("zig", &args);
}
Termination term;
os_spawn_process(args, &term);
if (term.how != TerminationIdClean || term.code != 0) {
fprintf(stderr, "\nThe following command failed:\n");
print_zig_cc_cmd(buf_ptr(self_exe_path), &args);
exit(1);
}
lib_final_path = buf_alloc();
os_path_join(artifact_dir, final_lib_basename, lib_final_path);
args.resize(0);
args.append("link");
coff_append_machine_arg(parent, &args);
args.append(buf_ptr(buf_sprintf("-DEF:%s", buf_ptr(def_final_path))));
args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(lib_final_path))));
Buf diag = BUF_INIT;
ZigLLVM_ObjectFormatType target_ofmt = target_object_format(parent->zig_target);
if (!zig_lld_link(target_ofmt, args.items, args.length, &diag)) {
fprintf(stderr, "%s\n", buf_ptr(&diag));
exit(1);
}
} else {
// cache hit
artifact_dir = buf_alloc();
os_path_join(o_dir, &digest, artifact_dir);
lib_final_path = buf_alloc();
os_path_join(artifact_dir, final_lib_basename, lib_final_path);
}
parent->caches_to_release.append(cache_hash);
return buf_ptr(lib_final_path);
}
static void add_mingw_link_args(LinkJob *lj, bool is_library) {
CodeGen *g = lj->codegen;
lj->args.append("-lldmingw");
bool is_dll = g->out_type == OutTypeLib && g->is_dynamic;
if (g->zig_target->arch == ZigLLVM_x86) {
@ -1238,8 +1442,11 @@ static void add_mingw_link_args(LinkJob *lj, bool is_library) {
if (is_dll) {
lj->args.append(get_libc_crt_file(g, "dllcrt2.obj"));
} else {
lj->args.append(get_libc_crt_file(g, "crt2u.obj"));
lj->args.append(get_libc_crt_file(g, "crt2.obj"));
}
lj->args.append(get_libc_crt_file(g, "mingw32.lib"));
lj->args.append(get_def_lib(g, "msvcrt", "mingw" OS_SEP "lib-common" OS_SEP "msvcrt.def.in"));
} else {
if (is_dll) {
lj->args.append(get_libc_file(g->libc, "dllcrt2.o"));
@ -1388,7 +1595,7 @@ static void construct_linker_job_coff(LinkJob *lj) {
}
if (g->out_type == OutTypeExe || (g->out_type == OutTypeLib && g->is_dynamic)) {
if (!g->is_dummy_so) {
if (g->libc_link_lib == nullptr && !g->is_dummy_so) {
Buf *libc_a_path = build_c(g, OutTypeLib);
lj->args.append(buf_ptr(libc_a_path));
}
@ -1762,10 +1969,12 @@ void codegen_link(CodeGen *g) {
}
os_spawn_process(args, &term);
if (term.how != TerminationIdClean || term.code != 0) {
codegen_release_caches(g);
exit(1);
}
} else if (!zig_lld_link(target_object_format(g->zig_target), lj.args.items, lj.args.length, &diag)) {
fprintf(stderr, "%s\n", buf_ptr(&diag));
codegen_release_caches(g);
exit(1);
}
}