mirror of
https://github.com/ziglang/zig.git
synced 2024-11-15 00:26:57 +00:00
mingw: building and linking mingw32.lib
This commit is contained in:
parent
1c7f21852f
commit
ea90a3a9a1
@ -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"
|
||||
|
@ -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
32
libc/mingw/crt/CRT_fp10.c
Normal 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
|
7
libc/mingw/crt/_newmode.c
Normal file
7
libc/mingw/crt/_newmode.c
Normal 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
22
libc/mingw/crt/charmax.c
Normal 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
13
libc/mingw/crt/cinitexe.c
Normal 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
20
libc/mingw/crt/crt0_c.c
Normal 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
25
libc/mingw/crt/crt0_w.c
Normal 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);
|
||||
}
|
290
libc/mingw/crt/crt_handler.c
Normal file
290
libc/mingw/crt/crt_handler.c
Normal 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
151
libc/mingw/crt/cxa_atexit.c
Normal 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
25
libc/mingw/crt/dll_argv.c
Normal 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
22
libc/mingw/crt/dllargv.c
Normal 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
85
libc/mingw/crt/gccmain.c
Normal 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
154
libc/mingw/crt/gs_support.c
Normal 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
76
libc/mingw/crt/merr.c
Normal 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;
|
||||
}
|
||||
|
31
libc/mingw/crt/mingw_helpers.c
Normal file
31
libc/mingw/crt/mingw_helpers.c
Normal 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
14
libc/mingw/crt/natstart.c
Normal 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
230
libc/mingw/crt/pesect.c
Normal 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;
|
||||
}
|
8
libc/mingw/crt/pseudo-reloc-list.c
Normal file
8
libc/mingw/crt/pseudo-reloc-list.c
Normal 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;
|
487
libc/mingw/crt/pseudo-reloc.c
Normal file
487
libc/mingw/crt/pseudo-reloc.c
Normal 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
13
libc/mingw/crt/tlsmcrt.c
Normal 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;
|
||||
|
33
libc/mingw/crt/tlsmthread.c
Normal file
33
libc/mingw/crt/tlsmthread.c
Normal 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
175
libc/mingw/crt/tlssup.c
Normal 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
158
libc/mingw/crt/tlsthrd.c
Normal 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;
|
||||
}
|
||||
|
16
libc/mingw/crt/udll_argv.c
Normal file
16
libc/mingw/crt/udll_argv.c
Normal 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
16
libc/mingw/crt/udllargc.c
Normal 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
33
libc/mingw/crt/wildcard.c
Normal 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;
|
||||
|
7
libc/mingw/crt/xncommod.c
Normal file
7
libc/mingw/crt/xncommod.c
Normal 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
7
libc/mingw/crt/xthdloc.c
Normal 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;
|
6
libc/mingw/crt/xtxtmode.c
Normal file
6
libc/mingw/crt/xtxtmode.c
Normal 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;
|
57
libc/mingw/def-include/func.def.in
Normal file
57
libc/mingw/def-include/func.def.in
Normal 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
|
145
libc/mingw/def-include/msvcrt-common.def.in
Normal file
145
libc/mingw/def-include/msvcrt-common.def.in
Normal 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
|
74
libc/mingw/include/config.h
Normal file
74
libc/mingw/include/config.h
Normal 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 */
|
1577
libc/mingw/lib-common/msvcrt.def.in
Normal file
1577
libc/mingw/lib-common/msvcrt.def.in
Normal file
File diff suppressed because it is too large
Load Diff
@ -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,
|
||||
|
@ -61,4 +61,6 @@ Buf *codegen_generate_builtin_source(CodeGen *g);
|
||||
|
||||
TargetSubsystem detect_subsystem(CodeGen *g);
|
||||
|
||||
void codegen_release_caches(CodeGen *codegen);
|
||||
|
||||
#endif
|
||||
|
227
src/link.cpp
227
src/link.cpp
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user