From 7ccf7807b3f12428adc5d9ca0ede4e3f4ec6dbbc Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 7 Jul 2019 17:06:09 -0400 Subject: ability to target any glibc version --- src/codegen.hpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/codegen.hpp') diff --git a/src/codegen.hpp b/src/codegen.hpp index 9a340d7205..d7cabe879e 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -20,6 +20,9 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget OutType out_type, BuildMode build_mode, Buf *zig_lib_dir, Buf *override_std_dir, ZigLibCInstallation *libc, Buf *cache_dir); +CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType out_type, + ZigLibCInstallation *libc); + void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len); void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len); void codegen_set_is_test(CodeGen *codegen, bool is_test); -- cgit v1.2.3 From ea90a3a9a16af83efdd8878285d5f53ae36ba9f3 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 10 Jul 2019 14:13:00 -0400 Subject: mingw: building and linking mingw32.lib --- CMakeLists.txt | 34 + libc/include/any-windows-any/_mingw.h | 2 +- libc/mingw/crt/CRT_fp10.c | 32 + libc/mingw/crt/_newmode.c | 7 + libc/mingw/crt/charmax.c | 22 + libc/mingw/crt/cinitexe.c | 13 + libc/mingw/crt/crt0_c.c | 20 + libc/mingw/crt/crt0_w.c | 25 + libc/mingw/crt/crt_handler.c | 290 +++++ libc/mingw/crt/cxa_atexit.c | 151 +++ libc/mingw/crt/dll_argv.c | 25 + libc/mingw/crt/dllargv.c | 22 + libc/mingw/crt/gccmain.c | 85 ++ libc/mingw/crt/gs_support.c | 154 +++ libc/mingw/crt/merr.c | 76 ++ libc/mingw/crt/mingw_helpers.c | 31 + libc/mingw/crt/natstart.c | 14 + libc/mingw/crt/pesect.c | 230 ++++ libc/mingw/crt/pseudo-reloc-list.c | 8 + libc/mingw/crt/pseudo-reloc.c | 487 +++++++++ libc/mingw/crt/tlsmcrt.c | 13 + libc/mingw/crt/tlsmthread.c | 33 + libc/mingw/crt/tlssup.c | 175 +++ libc/mingw/crt/tlsthrd.c | 158 +++ libc/mingw/crt/udll_argv.c | 16 + libc/mingw/crt/udllargc.c | 16 + libc/mingw/crt/wildcard.c | 33 + libc/mingw/crt/xncommod.c | 7 + libc/mingw/crt/xthdloc.c | 7 + libc/mingw/crt/xtxtmode.c | 6 + libc/mingw/def-include/func.def.in | 57 + libc/mingw/def-include/msvcrt-common.def.in | 145 +++ libc/mingw/include/config.h | 74 ++ libc/mingw/lib-common/msvcrt.def.in | 1577 +++++++++++++++++++++++++++ src/codegen.cpp | 6 +- src/codegen.hpp | 2 + src/link.cpp | 227 +++- 37 files changed, 4269 insertions(+), 11 deletions(-) create mode 100644 libc/mingw/crt/CRT_fp10.c create mode 100644 libc/mingw/crt/_newmode.c create mode 100644 libc/mingw/crt/charmax.c create mode 100644 libc/mingw/crt/cinitexe.c create mode 100644 libc/mingw/crt/crt0_c.c create mode 100644 libc/mingw/crt/crt0_w.c create mode 100644 libc/mingw/crt/crt_handler.c create mode 100644 libc/mingw/crt/cxa_atexit.c create mode 100644 libc/mingw/crt/dll_argv.c create mode 100644 libc/mingw/crt/dllargv.c create mode 100644 libc/mingw/crt/gccmain.c create mode 100644 libc/mingw/crt/gs_support.c create mode 100644 libc/mingw/crt/merr.c create mode 100644 libc/mingw/crt/mingw_helpers.c create mode 100644 libc/mingw/crt/natstart.c create mode 100644 libc/mingw/crt/pesect.c create mode 100644 libc/mingw/crt/pseudo-reloc-list.c create mode 100644 libc/mingw/crt/pseudo-reloc.c create mode 100644 libc/mingw/crt/tlsmcrt.c create mode 100644 libc/mingw/crt/tlsmthread.c create mode 100644 libc/mingw/crt/tlssup.c create mode 100644 libc/mingw/crt/tlsthrd.c create mode 100644 libc/mingw/crt/udll_argv.c create mode 100644 libc/mingw/crt/udllargc.c create mode 100644 libc/mingw/crt/wildcard.c create mode 100644 libc/mingw/crt/xncommod.c create mode 100644 libc/mingw/crt/xthdloc.c create mode 100644 libc/mingw/crt/xtxtmode.c create mode 100644 libc/mingw/def-include/func.def.in create mode 100644 libc/mingw/def-include/msvcrt-common.def.in create mode 100644 libc/mingw/include/config.h create mode 100644 libc/mingw/lib-common/msvcrt.def.in (limited to 'src/codegen.hpp') diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ffa3907af..3897c74912 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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" diff --git a/libc/include/any-windows-any/_mingw.h b/libc/include/any-windows-any/_mingw.h index 578121431d..8195a435e9 100644 --- a/libc/include/any-windows-any/_mingw.h +++ b/libc/include/any-windows-any/_mingw.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 diff --git a/libc/mingw/crt/CRT_fp10.c b/libc/mingw/crt/CRT_fp10.c new file mode 100644 index 0000000000..f39b5175f7 --- /dev/null +++ b/libc/mingw/crt/CRT_fp10.c @@ -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 diff --git a/libc/mingw/crt/_newmode.c b/libc/mingw/crt/_newmode.c new file mode 100644 index 0000000000..2bb5d94a27 --- /dev/null +++ b/libc/mingw/crt/_newmode.c @@ -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; diff --git a/libc/mingw/crt/charmax.c b/libc/mingw/crt/charmax.c new file mode 100644 index 0000000000..08aa5a1d3e --- /dev/null +++ b/libc/mingw/crt/charmax.c @@ -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 +#include +#include + +__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; diff --git a/libc/mingw/crt/cinitexe.c b/libc/mingw/crt/cinitexe.c new file mode 100644 index 0000000000..ee441ed77f --- /dev/null +++ b/libc/mingw/crt/cinitexe.c @@ -0,0 +1,13 @@ +#include +#include + +#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 }; diff --git a/libc/mingw/crt/crt0_c.c b/libc/mingw/crt/crt0_c.c new file mode 100644 index 0000000000..e42dd320f4 --- /dev/null +++ b/libc/mingw/crt/crt0_c.c @@ -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 + +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); +} diff --git a/libc/mingw/crt/crt0_w.c b/libc/mingw/crt/crt0_w.c new file mode 100644 index 0000000000..ab099c9632 --- /dev/null +++ b/libc/mingw/crt/crt0_w.c @@ -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 + +/* 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); +} diff --git a/libc/mingw/crt/crt_handler.c b/libc/mingw/crt/crt_handler.c new file mode 100644 index 0000000000..6571e69e8f --- /dev/null +++ b/libc/mingw/crt/crt_handler.c @@ -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 +#include +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/libc/mingw/crt/cxa_atexit.c b/libc/mingw/crt/cxa_atexit.c new file mode 100644 index 0000000000..06912a8266 --- /dev/null +++ b/libc/mingw/crt/cxa_atexit.c @@ -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 + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include + +#include +#include +#include +#include +#include + + +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; diff --git a/libc/mingw/crt/dll_argv.c b/libc/mingw/crt/dll_argv.c new file mode 100644 index 0000000000..22397af50c --- /dev/null +++ b/libc/mingw/crt/dll_argv.c @@ -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 + +extern int _dowildcard; + +#ifdef WPRFLAG +int __CRTDECL +__wsetargv (void) +#else +int __CRTDECL +__setargv (void) +#endif +{ + _dowildcard = 1; + return 0; +} diff --git a/libc/mingw/crt/dllargv.c b/libc/mingw/crt/dllargv.c new file mode 100644 index 0000000000..7cd98dad82 --- /dev/null +++ b/libc/mingw/crt/dllargv.c @@ -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 + +#ifdef WPRFLAG +int __CRTDECL +_wsetargv (void) +#else +int __CRTDECL +_setargv (void) +#endif +{ + return 0; +} diff --git a/libc/mingw/crt/gccmain.c b/libc/mingw/crt/gccmain.c new file mode 100644 index 0000000000..030cdce60b --- /dev/null +++ b/libc/mingw/crt/gccmain.c @@ -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 +#include +#include + +#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 (); + } +} diff --git a/libc/mingw/crt/gs_support.c b/libc/mingw/crt/gs_support.c new file mode 100644 index 0000000000..0c6ac68cd8 --- /dev/null +++ b/libc/mingw/crt/gs_support.c @@ -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 /* abort () */ +#include +#undef WIN32_NO_STATUS +#include /* STATUS macros */ +#ifdef _WIN64 +#include +#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(); +} + diff --git a/libc/mingw/crt/merr.c b/libc/mingw/crt/merr.c new file mode 100644 index 0000000000..f3dff58049 --- /dev/null +++ b/libc/mingw/crt/merr.c @@ -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 +#include +#include + +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; +} + diff --git a/libc/mingw/crt/mingw_helpers.c b/libc/mingw/crt/mingw_helpers.c new file mode 100644 index 0000000000..28c56bc3c5 --- /dev/null +++ b/libc/mingw/crt/mingw_helpers.c @@ -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 +#include +#include +#include +#include +#include +#include +#include + +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; diff --git a/libc/mingw/crt/natstart.c b/libc/mingw/crt/natstart.c new file mode 100644 index 0000000000..06def19d51 --- /dev/null +++ b/libc/mingw/crt/natstart.c @@ -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 +#include + +_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; diff --git a/libc/mingw/crt/pesect.c b/libc/mingw/crt/pesect.c new file mode 100644 index 0000000000..28c34f8cad --- /dev/null +++ b/libc/mingw/crt/pesect.c @@ -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 +#include + +#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; +} diff --git a/libc/mingw/crt/pseudo-reloc-list.c b/libc/mingw/crt/pseudo-reloc-list.c new file mode 100644 index 0000000000..5b903c21d2 --- /dev/null +++ b/libc/mingw/crt/pseudo-reloc-list.c @@ -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; diff --git a/libc/mingw/crt/pseudo-reloc.c b/libc/mingw/crt/pseudo-reloc.c new file mode 100644 index 0000000000..6210368bac --- /dev/null +++ b/libc/mingw/crt/pseudo-reloc.c @@ -0,0 +1,487 @@ +/* pseudo-reloc.c + + Contributed by Egor Duda + Modified by addition of runtime_pseudo_reloc version 2 + by Kai Tietz + + 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 +#include +#include +#include +#include +#include + +#if defined(__CYGWIN__) +#include +#include +#include +/* 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[] = ": "; + 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 */ +} diff --git a/libc/mingw/crt/tlsmcrt.c b/libc/mingw/crt/tlsmcrt.c new file mode 100644 index 0000000000..506bc0ab97 --- /dev/null +++ b/libc/mingw/crt/tlsmcrt.c @@ -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 + */ + +/* 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; + diff --git a/libc/mingw/crt/tlsmthread.c b/libc/mingw/crt/tlsmthread.c new file mode 100644 index 0000000000..9e04b05aeb --- /dev/null +++ b/libc/mingw/crt/tlsmthread.c @@ -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 + */ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#include + +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; +} diff --git a/libc/mingw/crt/tlssup.c b/libc/mingw/crt/tlssup.c new file mode 100644 index 0000000000..582fa8519e --- /dev/null +++ b/libc/mingw/crt/tlssup.c @@ -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 + */ + +#ifdef CRTDLL +#undef CRTDLL +#endif + +#include + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include + +#include +#include +#include +#include + +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; diff --git a/libc/mingw/crt/tlsthrd.c b/libc/mingw/crt/tlsthrd.c new file mode 100644 index 0000000000..bebe27b370 --- /dev/null +++ b/libc/mingw/crt/tlsthrd.c @@ -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 + * + * This file is used by if gcc is built with --enable-threads=win32. + * + * Based on version created by Mumit Khan + * + */ + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#include + +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; +} + diff --git a/libc/mingw/crt/udll_argv.c b/libc/mingw/crt/udll_argv.c new file mode 100644 index 0000000000..a60927cffe --- /dev/null +++ b/libc/mingw/crt/udll_argv.c @@ -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" + diff --git a/libc/mingw/crt/udllargc.c b/libc/mingw/crt/udllargc.c new file mode 100644 index 0000000000..f6ab6b1a77 --- /dev/null +++ b/libc/mingw/crt/udllargc.c @@ -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" + diff --git a/libc/mingw/crt/wildcard.c b/libc/mingw/crt/wildcard.c new file mode 100644 index 0000000000..b53cc18ec0 --- /dev/null +++ b/libc/mingw/crt/wildcard.c @@ -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; + diff --git a/libc/mingw/crt/xncommod.c b/libc/mingw/crt/xncommod.c new file mode 100644 index 0000000000..b2ec312f09 --- /dev/null +++ b/libc/mingw/crt/xncommod.c @@ -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; diff --git a/libc/mingw/crt/xthdloc.c b/libc/mingw/crt/xthdloc.c new file mode 100644 index 0000000000..973ff45b16 --- /dev/null +++ b/libc/mingw/crt/xthdloc.c @@ -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; diff --git a/libc/mingw/crt/xtxtmode.c b/libc/mingw/crt/xtxtmode.c new file mode 100644 index 0000000000..dcbbe11846 --- /dev/null +++ b/libc/mingw/crt/xtxtmode.c @@ -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; diff --git a/libc/mingw/def-include/func.def.in b/libc/mingw/def-include/func.def.in new file mode 100644 index 0000000000..58cc36d860 --- /dev/null +++ b/libc/mingw/def-include/func.def.in @@ -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 diff --git a/libc/mingw/def-include/msvcrt-common.def.in b/libc/mingw/def-include/msvcrt-common.def.in new file mode 100644 index 0000000000..364e4409dd --- /dev/null +++ b/libc/mingw/def-include/msvcrt-common.def.in @@ -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 diff --git a/libc/mingw/include/config.h b/libc/mingw/include/config.h new file mode 100644 index 0000000000..45931b832a --- /dev/null +++ b/libc/mingw/include/config.h @@ -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 header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the 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 */ diff --git a/libc/mingw/lib-common/msvcrt.def.in b/libc/mingw/lib-common/msvcrt.def.in new file mode 100644 index 0000000000..1a1db2b4e0 --- /dev/null +++ b/libc/mingw/lib-common/msvcrt.def.in @@ -0,0 +1,1577 @@ +LIBRARY "msvcrt.dll" +EXPORTS + +#include "func.def.in" +#include "msvcrt-common.def.in" + +#ifdef DEF_I386 +_CIacos +_CIasin +_CIatan +_CIatan2 +_CIcos +_CIcosh +_CIexp +_CIfmod +_CIlog +_CIlog10 +_CIpow +_CIsin +_CIsinh +_CIsqrt +_CItan +_CItanh +#endif + +#ifdef DEF_X64 +$I10_OUTPUT +; public: __cdecl __non_rtti_object::__non_rtti_object(class __non_rtti_object const & __ptr64) __ptr64 +; GCC = __ZN17__non_rtti_objectC2ERKS_ +??0__non_rtti_object@@QEAA@AEBV0@@Z +; public: __cdecl __non_rtti_object::__non_rtti_object(char const * __ptr64) __ptr64 +; GCC = __ZN17__non_rtti_objectC1ERKS_ +??0__non_rtti_object@@QEAA@PEBD@Z +; private: __cdecl bad_cast::bad_cast(char const * __ptr64 const * __ptr64) __ptr64 +??0bad_cast@@AEAA@PEBQEBD@Z +; public: __cdecl bad_cast::bad_cast(char const * __ptr64 const & __ptr64) __ptr64 +??0bad_cast@@QEAA@AEBQEBD@Z +; public: __cdecl bad_cast::bad_cast(class bad_cast const & __ptr64) __ptr64 +??0bad_cast@@QEAA@AEBV0@@Z +; public: __cdecl bad_cast::bad_cast(char const * __ptr64) __ptr64 +??0bad_cast@@QEAA@PEBD@Z +; public: __cdecl bad_typeid::bad_typeid(class bad_typeid const & __ptr64) __ptr64 +??0bad_typeid@@QEAA@AEBV0@@Z +; public: __cdecl bad_typeid::bad_typeid(char const * __ptr64) __ptr64 +??0bad_typeid@@QEAA@PEBD@Z +; public: __cdecl exception::exception(char const * __ptr64 const & __ptr64) __ptr64 +??0exception@@QEAA@AEBQEBD@Z +; public: __cdecl exception::exception(char const * __ptr64 const & __ptr64,int) __ptr64 +??0exception@@QEAA@AEBQEBDH@Z +; public: __cdecl exception::exception(class exception const & __ptr64) __ptr64 +??0exception@@QEAA@AEBV0@@Z +; public: __cdecl exception::exception(void) __ptr64 +??0exception@@QEAA@XZ +; public: virtual __cdecl __non_rtti_object::~__non_rtti_object(void) __ptr64 +??1__non_rtti_object@@UEAA@XZ +; public: virtual __cdecl bad_cast::~bad_cast(void) __ptr64 +??1bad_cast@@UEAA@XZ +; public: virtual __cdecl bad_typeid::~bad_typeid(void) __ptr64 +??1bad_typeid@@UEAA@XZ +; public: virtual __cdecl exception::~exception(void) __ptr64 +??1exception@@UEAA@XZ +; public: virtual __cdecl type_info::~type_info(void) __ptr64 +??1type_info@@UEAA@XZ +; void * __ptr64 __cdecl operator new(unsigned __int64) +; GCC = __Znwy +??2@YAPEAX_K@Z +; void __cdecl operator delete(void * __ptr64) +; GCC = __ZdlPv +??3@YAXPEAX@Z +; public: class __non_rtti_object & __ptr64 __cdecl __non_rtti_object::operator=(class __non_rtti_object const & __ptr64) __ptr64 +??4__non_rtti_object@@QEAAAEAV0@AEBV0@@Z +; public: class bad_cast & __ptr64 __cdecl bad_cast::operator=(class bad_cast const & __ptr64) __ptr64 +??4bad_cast@@QEAAAEAV0@AEBV0@@Z +; public: class bad_typeid & __ptr64 __cdecl bad_typeid::operator=(class bad_typeid const & __ptr64) __ptr64 +??4bad_typeid@@QEAAAEAV0@AEBV0@@Z +; public: class exception & __ptr64 __cdecl exception::operator=(class exception const & __ptr64) __ptr64 +??4exception@@QEAAAEAV0@AEBV0@@Z +; public: int __cdecl type_info::operator==(class type_info const & __ptr64)const __ptr64 +??8type_info@@QEBAHAEBV0@@Z +; public: int __cdecl type_info::operator!=(class type_info const & __ptr64)const __ptr64 +??9type_info@@QEBAHAEBV0@@Z +; const __non_rtti_object::`vftable' +??_7__non_rtti_object@@6B@ +; const bad_cast::`vftable' +??_7bad_cast@@6B@ +; const bad_typeid::`vftable' +??_7bad_typeid@@6B@ +; const exception::`vftable' +??_7exception@@6B@ +; public: void __cdecl bad_cast::`default constructor closure'(void) __ptr64 +??_Fbad_cast@@QEAAXXZ +; public: void __cdecl bad_typeid::`default constructor closure'(void) __ptr64 +??_Fbad_typeid@@QEAAXXZ +; void * __ptr64 __cdecl operator new[](unsigned __int64) +; GNU = __Znay +??_U@YAPEAX_K@Z +; void __cdecl operator delete[](void * __ptr64) +; GNU = __ZdaPv +??_V@YAXPEAX@Z +; int (__cdecl*__cdecl _query_new_handler(void))(unsigned __int64) +; GNU = __Z18_query_new_handlerv +?_query_new_handler@@YAP6AH_K@ZXZ +; int __cdecl _query_new_mode(void) +; GNU = __Z15_query_new_modev +?_query_new_mode@@YAHXZ +; int (__cdecl*__cdecl _set_new_handler(int (__cdecl*)(unsigned __int64)))(unsigned __int64) +; GNU = __Z16_set_new_handlerPFiyE +?_set_new_handler@@YAP6AH_K@ZP6AH0@Z@Z +; int __cdecl _set_new_mode(int) +; GNU = __Z13_set_new_modei +?_set_new_mode@@YAHH@Z +; void (__cdecl*__cdecl _set_se_translator(void (__cdecl*)(unsigned int,struct _EXCEPTION_POINTERS * __ptr64)))(unsigned int,struct _EXCEPTION_POINTERS * __ptr64) +; GNU = __Z18_set_se_translatorPFvjP19_EXCEPTION_POINTERSE +?_set_se_translator@@YAP6AXIPEAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z +; public: int __cdecl type_info::before(class type_info const & __ptr64)const __ptr64 +?before@type_info@@QEBAHAEBV1@@Z +; public: char const * __ptr64 __cdecl type_info::name(void)const __ptr64 +?name@type_info@@QEBAPEBDXZ +; public: char const * __ptr64 __cdecl type_info::raw_name(void)const __ptr64 +?raw_name@type_info@@QEBAPEBDXZ +; void (__cdecl*__cdecl set_new_handler(void (__cdecl*)(void)))(void) +; GNU = __Z15set_new_handlerPFvvE +?set_new_handler@@YAP6AXXZP6AXXZ@Z +; void (__cdecl*__cdecl set_terminate(void (__cdecl*)(void)))(void) +; GNU = __Z13set_terminatePFvvE +?set_terminate@@YAP6AXXZP6AXXZ@Z +; void (__cdecl*__cdecl set_unexpected(void (__cdecl*)(void)))(void) +; GNU = __Z14set_unexpectedPFvvE +?set_unexpected@@YAP6AXXZP6AXXZ@Z +; void __cdecl terminate(void) +; GNU = __Z9terminatev +?terminate@@YAXXZ +; void __cdecl unexpected(void) +; GNU = __Z10unexpectedv +?unexpected@@YAXXZ +; public: virtual char const * __ptr64 __cdecl exception::what(void)const __ptr64 +?what@exception@@UEBAPEBDXZ +#endif + +#ifdef DEF_ARM32 +??0__non_rtti_object@@QAA@ABV0@@Z +??0__non_rtti_object@@QAA@PBD@Z +??0bad_cast@@AAA@PBQBD@Z +??0bad_cast@@QAA@ABV0@@Z +??0bad_cast@@QAA@PBD@Z +??0bad_typeid@@QAA@ABV0@@Z +??0bad_typeid@@QAA@PBD@Z +??0exception@@QAA@ABQBD@Z +??0exception@@QAA@ABQBDH@Z +??0exception@@QAA@ABV0@@Z +??0exception@@QAA@XZ +??1__non_rtti_object@@UAA@XZ +??1bad_cast@@UAA@XZ +??1bad_typeid@@UAA@XZ +??1exception@@UAA@XZ +??1type_info@@UAA@XZ +??2@YAPAXI@Z +??2@YAPAXIHPBDH@Z +??3@YAXPAX@Z +??4__non_rtti_object@@QAAAAV0@ABV0@@Z +??4bad_cast@@QAAAAV0@ABV0@@Z +??4bad_typeid@@QAAAAV0@ABV0@@Z +??4exception@@QAAAAV0@ABV0@@Z +??8type_info@@QBAHABV0@@Z +??9type_info@@QBAHABV0@@Z +??_7__non_rtti_object@@6B@ DATA +??_7bad_cast@@6B@ DATA +??_7bad_typeid@@6B@ DATA +??_7exception@@6B@ DATA +??_Fbad_cast@@QAAXXZ +??_Fbad_typeid@@QAAXXZ +??_U@YAPAXI@Z +??_U@YAPAXIHPBDH@Z +??_V@YAXPAX@Z +_CallMemberFunction0 +_CallMemberFunction1 +_CallMemberFunction2 +__ExceptionPtrAssign +__ExceptionPtrCompare +__ExceptionPtrCopy +__ExceptionPtrCopyException +__ExceptionPtrCreate +__ExceptionPtrCurrentException +__ExceptionPtrDestroy +__ExceptionPtrRethrow +__ExceptionPtrSwap +__ExceptionPtrToBool +?_query_new_handler@@YAP6AHI@ZXZ +?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z +?_set_new_mode@@YAHH@Z +?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z +?before@type_info@@QBAHABV1@@Z +?name@type_info@@QBAPBDXZ +?raw_name@type_info@@QBAPBDXZ +?set_terminate@@YAP6AXXZP6AXXZ@Z +?set_unexpected@@YAP6AXXZP6AXXZ@Z +?terminate@@YAXXZ +?unexpected@@YAXXZ +?what@exception@@UBAPBDXZ +#endif + +#ifdef DEF_ARM32 +_CrtCheckMemory +_CrtDbgBreak +_CrtDbgReport +_CrtDbgReportV +_CrtDbgReportW +_CrtDbgReportWV +_CrtDoForAllClientObjects +_CrtDumpMemoryLeaks +_CrtIsMemoryBlock +_CrtIsValidHeapPointer +_CrtIsValidPointer +_CrtMemCheckpoint +_CrtMemDifference +_CrtMemDumpAllObjectsSince +_CrtMemDumpStatistics +_CrtReportBlockType +_CrtSetAllocHook +_CrtSetBreakAlloc +_CrtSetDbgBlockType +_CrtSetDbgFlag +_CrtSetDumpClient +_CrtSetReportFile +_CrtSetReportHook +_CrtSetReportHook2 +_CrtSetReportMode +#endif +_CxxThrowException +F_I386(_EH_prolog) +_Getdays +_Getmonths +_Gettnames +_HUGE DATA +_Strftime +F_ARM_ANY(_W_Getdays) +F_ARM_ANY(_W_Getmonths) +F_ARM_ANY(_W_Gettnames) +F_ARM_ANY(_Wcsftime) +_XcptFilter +F_ARM_ANY(__AdjustPointer) +F_NON_I386(__C_specific_handler) +__CppXcptFilter +F_I386(__CxxCallUnwindDtor) +F_I386(__CxxCallUnwindVecDtor) +F_I386(__CxxDetectRethrow) +F_I386(__CxxExceptionFilter) +__CxxFrameHandler +F_ARM_ANY(__CxxFrameHandler3) +F_I386(__CxxLongjmpUnwind) +F_I386(__CxxQueryExceptionSize) +F_I386(__CxxRegisterExceptionObject) +F_I386(__CxxUnregisterExceptionObject) +__DestructExceptionObject +__RTCastToVoid +__RTDynamicCast +__RTtypeid +__STRINGTOLD +F_NON_I386(___lc_codepage_func) +___lc_collate_cp_func +___lc_handle_func +___mb_cur_max_func +___setlc_active_func +___unguarded_readlc_active_add_func +__argc DATA +__argv DATA +__badioinfo DATA +F_I386(__buffer_overrun) +__crtCompareStringA +__crtCompareStringW +__crtGetLocaleInfoW +__crtGetStringTypeW +__crtLCMapStringA +__crtLCMapStringW +F_ARM_ANY(__daylight) +__dllonexit +__doserrno +F_ARM_ANY(__dstbias) +__fpecode +__getmainargs +F_X86_ANY(__initenv DATA) +__iob_func +__isascii +__iscsym +__iscsymf +F_I386(__lc_clike) +__lc_codepage DATA +__lc_collate_cp DATA +__lc_handle DATA +__lconv_init +__mb_cur_max DATA +#ifdef DEF_I386 +__p___argc +__p___argv +__p___initenv +__p___mb_cur_max +__p___wargv +__p___winitenv +__p__acmdln +__p__amblksiz +__p__commode +__p__daylight +__p__dstbias +__p__environ +__p__fileinfo +__p__fmode +__p__iob +__p__mbcasemap +__p__mbctype +__p__osver +__p__pctype +__p__pgmptr +__p__pwctype +__p__timezone +__p__tzname +__p__wcmdln +__p__wenviron +__p__winmajor +__p__winminor +__p__winver +__p__wpgmptr +#endif +__pctype_func +__pioinfo DATA +__pwctype_func +__pxcptinfoptrs +F_I386(__security_error_handler) +__set_app_type +F_I386(__set_buffer_overrun_handler) +__setlc_active DATA +__setusermatherr +F_ARM_ANY(__strncnt) +__threadhandle +__threadid +__toascii +__uncaught_exception +__unDName +__unDNameEx +__unguarded_readlc_active DATA +__wargv DATA +__wcserror +F_NON_I386(__wcserror_s) +F_ARM_ANY(__wcsncnt) +__wgetmainargs +F_X86_ANY(__winitenv DATA) +F_I386(_abnormal_termination) +F_NON_I386(_abs64) +_access +; _access_s Replaced by emu +_acmdln DATA +#ifdef DEF_I386 +_adj_fdiv_m16i +_adj_fdiv_m32 +_adj_fdiv_m32i +_adj_fdiv_m64 +_adj_fdiv_r +_adj_fdivr_m16i +_adj_fdivr_m32 +_adj_fdivr_m32i +_adj_fdivr_m64 +_adj_fpatan +_adj_fprem +_adj_fprem1 +_adj_fptan +_adjust_fdiv DATA +#endif +_aexit_rtn DATA +_aligned_free +F_ARM_ANY(_aligned_free_dbg) +_aligned_malloc +F_ARM_ANY(_aligned_malloc_dbg) +_aligned_offset_malloc +F_ARM_ANY(_aligned_offset_malloc_dbg) +_aligned_offset_realloc +F_ARM_ANY(_aligned_offset_realloc_dbg) +_aligned_realloc +F_ARM_ANY(_aligned_realloc_dbg) +_amsg_exit +_assert DATA +_atodbl +_atodbl_l +_atof_l +_atoflt_l +_atoi64 +_atoi64_l +_atoi_l +_atol_l +_atoldbl +F_NON_I386(_atoldbl_l) +_beep +_beginthread +_beginthreadex +_c_exit +_cabs DATA +_callnewh +F_ARM_ANY(_calloc_dbg) +_cexit +_cgets +; _cgets_s replaced by emu +_cgetws +; _cgetws_s replaced by emu +_chdir +_chdrive +_chgsign +F_NON_I386(_chgsignf) +_chmod +F_I386(_chkesp) +_chsize +; _chsize_s replaced by emu +F_ARM_ANY(_chvalidator) +F_ARM_ANY(_chvalidator_l) +_clearfp +_close +_commit +_commode DATA +_control87 +_controlfp +; _controlfp_s replaced by emu +_copysign +F_NON_I386(_copysignf) +_cprintf +_cprintf_l +_cprintf_p +_cprintf_p_l +; _cprintf_s Replaced by emu +; _cprintf_s_l likewise. +_cputs +_cputws +F_I386(_CRT_RTC_INIT) +_creat +_create_locale +F_ARM32(_crtAssertBusy) +F_ARM32(_crtBreakAlloc) +F_ARM32(_crtDbgFlag) +_cscanf +_cscanf_l +_cscanf_s +_cscanf_s_l +F_ARM_ANY(_ctime32) +F_I386(_ctime32 == ctime) +; _ctime32_s replaced by emu +_ctime64 +; _ctime64_s replaced by emu +_ctype F_I386(DATA) +_cwait +_cwprintf +_cwprintf_l +_cwprintf_p +_cwprintf_p_l +; _cwprintf_s Replaced by emu +; _cwprintf_s_l Likewise. +_cwscanf +_cwscanf_l +_cwscanf_s +_cwscanf_s_l +_dstbias DATA +F_ARM_ANY(_daylight DATA) +F_ARM_ANY(_difftime32) +F_ARM_ANY(_difftime64) +_dup +_dup2 +_ecvt +_ecvt_s +_endthread +_endthreadex +F_X86_ANY(_environ DATA) +_eof +_errno +F_I386(_except_handler2) +F_I386(_except_handler3) +_execl +_execle +_execlp +_execlpe +_execv +_execve +_execvp +_execvpe +_exit +_expand +F_ARM_ANY(_expand_dbg) +_fcloseall +_fcvt +_fcvt_s +_fdopen +_fgetchar +_fgetwchar +_filbuf +F_X86_ANY(_fileinfo DATA) +_filelength +_filelengthi64 +_fileno +_findclose +_findfirst +F32(_findfirst32 == _findfirst) +_findfirst64 +_findfirsti64 +F32(_findfirst32i64 == _findfirsti64) +F64(_findfirst64i32 == _findfirst) +_findnext +F32(_findnext32 == _findnext) +_findnext64 +_findnexti64 +F32(_findnext32i64 == _findnexti64) +F64(_findnext64i32 == _findnext) +_finite +F_NON_I386(_finitef) +_flsbuf +_flushall +_fmode DATA +_fpclass +F_X64(_fpclassf) +F_I386(_fpieee_flt) +F_ARM_ANY(_fpieee_flt) +_fpreset DATA +_fprintf_l +_fprintf_p +_fprintf_p_l +_fprintf_s_l +_fputchar +_fputwchar +F_ARM_ANY(_free_dbg) +_free_locale +F_ARM_ANY(_freea) +F_NON_I386(_fscanf_l) +F_NON_I386(_fscanf_s_l) +F_ARM_ANY(_fseeki64) +_fsopen +_fstat +F32(_fstat32 == _fstat) +_fstat64 +_fstati64 +F64(_fstat64i32 == _fstat) +_ftime +F_ARM_ANY(_ftime32) +_ftime32_s +_ftime64 +_ftime64_s +F32(_ftime_s == _ftime32_s) +F64(_ftime_s == _ftime64_s) +F_I386(_ftol) +_fullpath +F_ARM_ANY(_fullpath_dbg) +_futime +F_ARM_ANY(_futime32) +_futime64 +_fwprintf_l +_fwprintf_p +_fwprintf_p_l +_fwprintf_s_l +_fwscanf_l +_fwscanf_s_l +_gcvt +_gcvt_s +F_ARM_ANY(_get_current_locale) +F_ARM_ANY(_get_doserrno) +F_ARM_ANY(_get_environ) +F_ARM_ANY(_get_errno) +F_ARM_ANY(_get_fileinfo) +F_ARM_ANY(_get_fmode) +_get_heap_handle +_get_osfhandle +;_get_output_format provided by emu +_get_sbh_threshold +F_ARM_ANY(_get_wenviron) +_getch +_getche +_getcwd +_getdcwd +_getdiskfree +_getdllprocaddr +_getdrive +_getdrives +_getmaxstdio +_getmbcp +_getpid +_getsystime +_getw +_getwch +_getwche +_getws +F_I386(_global_unwind2) +_gmtime32 F_I386(== gmtime) +; _gmtime32_s replaced by emu +_gmtime64 +; _gmtime64_s replaced by emu +_heapadd +_heapchk +_heapmin +_heapset +_heapused +_heapwalk +_hypot +F_NON_I386(_hypotf) +_i64toa +_i64toa_s +_i64tow +_i64tow_s +_initterm +F_ARM_ANY(_initterm_e) +F_I386(_inp) +F_I386(_inpd) +F_I386(_inpw) +F_ARM_ANY(_invalid_parameter) +_iob DATA +_isalnum_l +_isalpha_l +_isatty +_iscntrl_l +_isctype +_isctype_l +_isdigit_l +_isgraph_l +_isleadbyte_l +_islower_l +_ismbbalnum +_ismbbalnum_l +_ismbbalpha +_ismbbalpha_l +_ismbbgraph +_ismbbgraph_l +_ismbbkalnum +_ismbbkalnum_l +_ismbbkana +_ismbbkana_l +_ismbbkprint +_ismbbkprint_l +_ismbbkpunct +_ismbbkpunct_l +_ismbblead +_ismbblead_l +_ismbbprint +_ismbbprint_l +_ismbbpunct +_ismbbpunct_l +_ismbbtrail +_ismbbtrail_l +_ismbcalnum +_ismbcalnum_l +_ismbcalpha +_ismbcalpha_l +_ismbcdigit +_ismbcdigit_l +_ismbcgraph +_ismbcgraph_l +_ismbchira +_ismbchira_l +_ismbckata +_ismbckata_l +_ismbcl0 +_ismbcl0_l +_ismbcl1 +_ismbcl1_l +_ismbcl2 +_ismbcl2_l +_ismbclegal +_ismbclegal_l +_ismbclower +_ismbclower_l +_ismbcprint +_ismbcprint_l +_ismbcpunct +_ismbcpunct_l +_ismbcspace +_ismbcspace_l +_ismbcsymbol +_ismbcsymbol_l +_ismbcupper +_ismbcupper_l +_ismbslead +_ismbslead_l +_ismbstrail +_ismbstrail_l +_isnan +F_X64(_isnanf) +_isprint_l +_isspace_l +_isupper_l +_iswalnum_l +_iswalpha_l +_iswcntrl_l +_iswctype_l +_iswdigit_l +_iswgraph_l +_iswlower_l +_iswprint_l +_iswpunct_l +_iswspace_l +_iswupper_l +_iswxdigit_l +_isxdigit_l +_itoa +_itoa_s +_itow +_itow_s +_j0 +_j1 +_jn +_kbhit +_lfind +_loaddll +F_NON_I386(_lfind_s) +F_X64(_local_unwind) +F_I386(_local_unwind2) +_localtime32 F_I386(== localtime) +; _localtime32_s replaced by emu +_localtime64 +; _localtime64_s replaced by emu +_lock +_locking +_logb +F_NON_I386(_logbf) +F_I386(_longjmpex) +_lrotl +_lrotr +_lsearch +F_NON_I386(_lsearch_s) +_lseek +_lseeki64 +_ltoa +F_NON_I386(_ltoa_s) +_ltow +F_NON_I386(_ltow_s) +_makepath +_makepath_s +F_ARM_ANY(_malloc_dbg) +_mbbtombc +_mbbtombc_l +_mbbtype +_mbcasemap F_NON_I386(DATA) +_mbccpy +_mbccpy_l +_mbccpy_s +_mbccpy_s_l +_mbcjistojms +_mbcjistojms_l +_mbcjmstojis +_mbcjmstojis_l +_mbclen +_mbclen_l +_mbctohira +_mbctohira_l +_mbctokata +_mbctokata_l +_mbctolower +_mbctolower_l +_mbctombb +_mbctombb_l +_mbctoupper +_mbctoupper_l +_mbctype DATA +_mblen_l +_mbsbtype +_mbsbtype_l +_mbscat +_mbscat_s +_mbscat_s_l +_mbschr +_mbschr_l +_mbscmp +_mbscmp_l +_mbscoll +_mbscoll_l +_mbscpy +_mbscpy_s +_mbscpy_s_l +_mbscspn +_mbscspn_l +_mbsdec +_mbsdec_l +_mbsdup +_mbsicmp +_mbsicmp_l +_mbsicoll +_mbsicoll_l +_mbsinc +_mbsinc_l +_mbslen +_mbslen_l +_mbslwr +_mbslwr_l +_mbslwr_s +_mbslwr_s_l +_mbsnbcat +_mbsnbcat_l +_mbsnbcat_s +_mbsnbcat_s_l +_mbsnbcmp +_mbsnbcmp_l +_mbsnbcnt +_mbsnbcnt_l +_mbsnbcoll +_mbsnbcoll_l +_mbsnbcpy +_mbsnbcpy_l +_mbsnbcpy_s +_mbsnbcpy_s_l +_mbsnbicmp +_mbsnbicmp_l +_mbsnbicoll +_mbsnbicoll_l +_mbsnbset +_mbsnbset_l +_mbsnbset_s +_mbsnbset_s_l +_mbsncat +_mbsncat_l +_mbsncat_s +_mbsncat_s_l +_mbsnccnt +_mbsnccnt_l +_mbsncmp +_mbsncmp_l +_mbsncoll +_mbsncoll_l +_mbsncpy +_mbsncpy_l +_mbsncpy_s +_mbsncpy_s_l +_mbsnextc +_mbsnextc_l +_mbsnicmp +_mbsnicmp_l +_mbsnicoll +_mbsnicoll_l +_mbsninc +_mbsninc_l +_mbsnlen +_mbsnlen_l +_mbsnset +_mbsnset_l +_mbsnset_s +_mbsnset_s_l +_mbspbrk +_mbspbrk_l +_mbsrchr +_mbsrchr_l +_mbsrev +_mbsrev_l +_mbsset +_mbsset_l +_mbsset_s +_mbsset_s_l +_mbsspn +_mbsspn_l +_mbsspnp +_mbsspnp_l +_mbsstr +_mbsstr_l +_mbstok +_mbstok_l +_mbstok_s +_mbstok_s_l +_mbstowcs_l +_mbstowcs_s_l +_mbstrlen +_mbstrlen_l +_mbstrnlen +_mbstrnlen_l +_mbsupr +_mbsupr_l +_mbsupr_s +_mbsupr_s_l +_mbtowc_l +_memccpy +F_ARM_ANY(_memcpy_strict_align) +_memicmp +_memicmp_l +_mkdir +_mkgmtime +F_I386(_mkgmtime32) +F_ARM_ANY(_mkgmtime32) +F_NON_I386(_mkgmtime64) +_mktemp +; _mktemp_s replaced by emu +F_I386(_mktime32 == mktime) +F_ARM_ANY(_mktime32) +_mktime64 +_msize +F_ARM_ANY(_msize_dbg) +_nextafter +F_X64(_nextafterf) +_onexit +_open +_open_osfhandle +_osplatform DATA +_osver DATA +F_I386(_outp) +F_I386(_outpd) +F_I386(_outpw) +_pclose +_pctype DATA +_pgmptr DATA +_pipe +_popen +_printf_l +_printf_p +_printf_p_l +_printf_s_l +_purecall +_putch +_putenv +_putenv_s +_putw +_putwch +_putws +_pwctype DATA +_read +F_ARM_ANY(_realloc_dbg) +_resetstkoflw +_rmdir +_rmtmp +_rotl +F_NON_I386(_rotl64) +_rotr +F_NON_I386(_rotr64) +#ifdef DEF_I386 +_safe_fdiv +_safe_fdivr +_safe_fprem +_safe_fprem1 +#endif +_scalb +F_X64(_scalbf) +_scanf_l +_scanf_s_l +_scprintf +_scprintf_l +_scprintf_p_l +_scwprintf +_scwprintf_l +_scwprintf_p_l +_searchenv +_searchenv_s +F_I386(_seh_longjmp_unwind) +F_ARM_ANY(_set_controlfp) +F_ARM_ANY(_set_doserrno) +F_ARM_ANY(_set_errno) +_set_error_mode +F_ARM_ANY(_set_fileinfo) +F_ARM_ANY(_set_fmode) +; Does not seem to present even on Win7 msvcrt +;_set_purecall_handler +_set_sbh_threshold +; _set_output_format provided by emu +F_I386(_set_SSE2_enable) +F_I386(_set_security_error_handler) +_seterrormode +_setjmp +F_I386(_setjmp3) +F_NON_I386(_setjmpex) +_setmaxstdio +_setmbcp +_setmode +_setsystime +_sleep +_snprintf +_snprintf_c +_snprintf_c_l +_snprintf_l +_snprintf_s +_snprintf_s_l +_snscanf +_snscanf_l +_snscanf_s +_snscanf_s_l +_snwprintf +snwprintf == _snwprintf +_snwprintf_l +_snwprintf_s +_snwprintf_s_l +_snwscanf +_snwscanf_l +_snwscanf_s +_snwscanf_s_l +_sopen +; _sopen_s replaced by emu +_spawnl +_spawnle +_spawnlp +_spawnlpe +_spawnv +_spawnve +_spawnvp +_spawnvpe +_splitpath +_splitpath_s +_sprintf_l +_sprintf_p_l +_sprintf_s_l +_sscanf_l +_sscanf_s_l +_stat +_stat64 +_stati64 +F32(_stat32 == _stat) +F64(_stat64i32 == _stat) +_statusfp +_strcmpi +_strcoll_l +_strdate +; _strdate_s replaced by emu +_strdup +F_ARM_ANY(_strdup_dbg) +_strerror +_strerror_s +_stricmp +_stricmp_l +_stricoll +_stricoll_l +_strlwr +_strlwr_l +_strlwr_s +_strlwr_s_l +_strncoll +_strncoll_l +_strnicmp +_strnicmp_l +_strnicoll +_strnicoll_l +_strnset +_strnset_s +_strrev +_strset +_strset_s +_strtime +; _strtime_s replaced by emu +_strtod_l +_strtoi64 +_strtoi64_l +_strtol_l +_strtoui64 +_strtoui64_l +_strtoul_l +_strupr +_strupr_l +_strupr_s +_strupr_s_l +_strxfrm_l +_swab +_swprintf == swprintf +F_NON_I386(_swprintf_c) +_swprintf_c_l +_swprintf_p_l +_swprintf_s_l +_swscanf_l +_swscanf_s_l +_sys_errlist DATA +_sys_nerr DATA +_tell +_telli64 +_tempnam +F_ARM_ANY(_tempnam_dbg) +F_I386(_time32 == time) +F_ARM_ANY(_time32) +_time64 +_tolower +_tolower_l +_toupper +_toupper_l +_towlower_l +_towupper_l +_tzset +_ui64toa +_ui64toa_s +_ui64tow +_ui64tow_s +_ultoa +_ultoa_s +_ultow +_ultow_s +_umask +; _umask_s replaced by emu +_ungetch +_ungetwch +_unlink +_unloaddll +_unlock +_utime +F_ARM_ANY(_utime32) +_utime64 +_vcprintf +_vcprintf_l +_vcprintf_p +_vcprintf_p_l +; _vcprintf_s Replaced by emu +; _vcprintf_s_l Likewise. +_vcwprintf +_vcwprintf_l +_vcwprintf_p +_vcwprintf_p_l +; _vcwprintf_s Replaced by emu +; _vcwprintf_s_l Likewise. +_vfprintf_l +_vfprintf_p +_vfprintf_p_l +_vfprintf_s_l +_vfwprintf_l +_vfwprintf_p +_vfwprintf_p_l +_vfwprintf_s_l +_vprintf_l +_vprintf_p +_vprintf_p_l +_vprintf_s_l +_vscprintf +_vscprintf_l +_vscprintf_p_l +_vscwprintf +_vscwprintf_l +_vscwprintf_p_l +_vsnprintf +_vsnprintf_c +_vsnprintf_c_l +_vsnprintf_l +_vsnprintf_s +_vsnprintf_s_l +_vsnwprintf +vsnwprintf == _vsnwprintf +_vsnwprintf_l +_vsnwprintf_s +_vsnwprintf_s_l +_vsprintf_l +_vsprintf_p +_vsprintf_p_l +_vsprintf_s_l +_vswprintf F_I386(== vswprintf) +_vswprintf_c +_vswprintf_c_l +_vswprintf_l +_vswprintf_p_l +_vswprintf_s_l +_vwprintf_l +_vwprintf_p +_vwprintf_p_l +_vwprintf_s_l +_waccess +; _waccess_s Replaced by emu +_wasctime +; _wasctime_s Replaced by emu +F_ARM_ANY(_wassert) +_wchdir +_wchmod +_wcmdln DATA +_wcreat +_wcscoll_l +_wcsdup +F_ARM_ANY(_wcsdup_dbg) +_wcserror +_wcserror_s +_wcsftime_l +_wcsicmp +_wcsicmp_l +_wcsicoll +_wcsicoll_l +_wcslwr +_wcslwr_l +_wcslwr_s +_wcslwr_s_l +_wcsncoll +_wcsncoll_l +_wcsnicmp +_wcsnicmp_l +_wcsnicoll +_wcsnicoll_l +_wcsnset +_wcsnset_s +_wcsrev +_wcsset +_wcsset_s +F_ARM_ANY(_wcstod_l) +_wcstoi64 +_wcstoi64_l +_wcstol_l +_wcstombs_l +_wcstombs_s_l +_wcstoui64 +_wcstoui64_l +_wcstoul_l +_wcsupr +_wcsupr_l +_wcsupr_s +_wcsupr_s_l +_wcsxfrm_l +_wctime +F_I386(_wctime32 == _wctime) +F_ARM_ANY(_wctime32) +; _wctime32_s replaced by emu +_wctime64 +; _wctime64_s replaced by emu +_wctomb_l +_wctomb_s_l +_wctype +F_X86_ANY(_wenviron DATA) +_wexecl +_wexecle +_wexeclp +_wexeclpe +_wexecv +_wexecve +_wexecvp +_wexecvpe +_wfdopen +_wfindfirst +F32(_wfindfirst32 == _wfindfirst) +_wfindfirst64 +_wfindfirsti64 +F32(_wfindfirst32i64 == _wfindfirsti64) +F64(_wfindfirst64i32 == _wfindfirst) +_wfindnext +F32(_wfindnext32 == _wfindnext) +_wfindnext64 +_wfindnexti64 +F32(_wfindnext32i64 == _wfindnexti64) +F64(_wfindnext64i32 == _wfindnext) +_wfopen +_wfopen_s +_wfreopen +_wfreopen_s +_wfsopen +_wfullpath +F_ARM_ANY(_wfullpath_dbg) +_wgetcwd +_wgetdcwd +_wgetenv +_wgetenv_s +_winmajor DATA +_winminor DATA +_winput_s +_winver DATA +_wmakepath +_wmakepath_s +_wmkdir +_wmktemp +; _wmktemp_s replaced by emu +_wopen +_woutput_s +_wperror +_wpgmptr DATA +_wpopen +_wprintf_l +_wprintf_p +_wprintf_p_l +_wprintf_s_l +_wputenv +_wputenv_s +_wremove +_wrename +_write +_wrmdir +_wscanf_l +_wscanf_s_l +_wsearchenv +_wsearchenv_s +_wsetlocale +_wsopen +_wsopen_s +_wspawnl +_wspawnle +_wspawnlp +_wspawnlpe +_wspawnv +_wspawnve +_wspawnvp +_wspawnvpe +_wsplitpath +_wsplitpath_s +_wstat +_wstat64 +_wstati64 +F32(_wstat32 == _wstat) +F64(_wstat64i32 == _wstat) +_wstrdate +; _wstrdate_s replaced by emu +_wstrtime +; _wstrtime_s replaced by emu +_wsystem +_wtempnam +F_ARM_ANY(_wtempnam_dbg) +_wtmpnam +_wtmpnam_s +_wtof +_wtof_l +_wtoi +_wtoi64 +_wtoi64_l +_wtoi_l +_wtol +_wtol_l +_wunlink +_wutime +F_ARM_ANY(_wutime32) +_wutime64 +_y0 +_y1 +_yn +abort +abs +acos +F_NON_I386(acosf F_X86_ANY(DATA)) +asctime +; asctime_s replaced by emu +asin +F_NON_I386(asinf F_X86_ANY(DATA)) +atan +atan2 F_X86_ANY(DATA) +F_NON_I386(atan2f F_X86_ANY(DATA)) +F_NON_I386(atanf F_X86_ANY(DATA)) +atexit DATA +atof +atoi +atol +bsearch +bsearch_s +F_ARM_ANY(btowc) +calloc +ceil DATA +F_NON_I386(ceilf DATA) +clearerr +clearerr_s +clock +cos F_X86_ANY(DATA) +F_NON_I386(cosf F_X86_ANY(DATA)) +cosh +F_NON_I386(coshf DATA) +ctime +difftime +div +exit +exp F_X86_ANY(DATA) +F_NON_I386(expf F_X86_ANY(DATA)) +fabs DATA +F_ARM_ANY(fabsf) +fclose +feof +ferror +fflush +fgetc +fgetpos +fgets +fgetwc +fgetws +floor DATA +F_NON_I386(floorf DATA) +fmod F_X86_ANY(DATA) +F_NON_I386(fmodf F_X86_ANY(DATA)) +fopen +fopen_s +fprintf +fprintf_s +fputc +fputs +fputwc +fputws +fread +free +freopen +freopen_s +; If we implement frexp, we can set it to DATA only. +frexp +fscanf +fscanf_s +fseek +fsetpos +ftell +fwprintf +__ms_fwprintf == fwprintf +fwprintf_s +fwrite +fwscanf +fwscanf_s +getc +getchar +getenv +getenv_s +gets +getwc +getwchar +gmtime +is_wctype +isalnum +isalpha +iscntrl +isdigit +isgraph +isleadbyte +islower +isprint +ispunct +isspace +isupper +iswalnum +iswalpha +iswascii +iswcntrl +iswctype +iswdigit +iswgraph +iswlower +iswprint +iswpunct +iswspace +iswupper +iswxdigit +isxdigit +labs +ldexp F_X86_ANY(DATA) +ldiv +localeconv +localtime +log F_X86_ANY(DATA) +log10 +F_NON_I386(log10f F_X86_ANY(DATA)) +F_NON_I386(logf F_X86_ANY(DATA)) +F_ARM_ANY(longjmp) +malloc +mblen +F_ARM_ANY(mbrlen) +F_ARM_ANY(mbrtowc) +F_ARM_ANY(mbsdup_dbg) +F_ARM_ANY(mbsrtowcs) +mbsrtowcs_s +mbstowcs +mbstowcs_s +mbtowc +memchr +memcmp +memcpy +; memcpy_s replaced by emu +memmove +; memmove_s replaced by emu +memset +mktime +modf DATA +F_NON_I386(modff DATA) +perror +pow F_X86_ANY(DATA) +F_NON_I386(powf F_X86_ANY(DATA)) +printf +printf_s +putc +putchar +puts +putwc +putwchar +qsort +qsort_s +raise +rand +; rand_s replaced by emu +realloc +remove +rename +rewind +scanf +scanf_s +setbuf +F_NON_I386(setjmp) +setlocale +setvbuf +signal +sin F_X86_ANY(DATA) +F_NON_I386(sinf F_X86_ANY(DATA)) +; if we implement sinh, we can set it DATA only. +sinh +F_NON_I386(sinhf DATA) +sprintf +; sprintf_s replaced by emu +sqrt DATA +F_NON_I386(sqrtf DATA) +srand +sscanf +sscanf_s +strcat +strcat_s +strchr +strcmp +strcoll +strcpy +strcpy_s +strcspn +strerror +; strerror_s replaced by emu +strftime +strlen +strncat +strncat_s +strncmp +strncpy +strncpy_s +; strnlen replaced by emu +strpbrk +strrchr +strspn +strstr +strtod +strtok +strtok_s +strtol +strtoul +strxfrm +swprintf +swprintf_s +swscanf +swscanf_s +system +tan +F_NON_I386(tanf F_X86_ANY(DATA)) +; if we implement tanh, we can set it to DATA only. +tanh +F_ARM_ANY(tanhf) +time F_NON_I386(== _time64) +tmpfile +tmpfile_s +tmpnam +tmpnam_s +tolower +toupper +towlower +towupper +ungetc +ungetwc +F_ARM_ANY(utime) +vfprintf +vfprintf_s +vfwprintf +vfwprintf_s +vprintf +vprintf_s +vsnprintf == _vsnprintf +snprintf == _snprintf +vsprintf +; vsprintf_s replaced by emu +vswprintf +vswprintf_s +vwprintf +vwprintf_s +F_ARM_ANY(wcrtomb) +wcrtomb_s +wcscat +wcscat_s +wcschr +wcscmp +wcscoll +wcscpy +wcscpy_s +wcscspn +wcsftime +wcslen +wcsncat +wcsncat_s +wcsncmp +wcsncpy +wcsncpy_s +; We provide replacement implementation in libmingwex +wcsnlen DATA +wcspbrk +wcsrchr +F_ARM_ANY(wcsrtombs) +wcsrtombs_s +wcsspn +wcsstr +wcstod +wcstok +wcstok_s +wcstol +wcstombs +wcstombs_s +wcstoul +wcsxfrm +F_ARM_ANY(wctob) +wctomb +wctomb_s +wprintf +wprintf_s +wscanf +wscanf_s diff --git a/src/codegen.cpp b/src/codegen.cpp index 59d3e1f4a0..f9933aaf28 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -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, diff --git a/src/codegen.hpp b/src/codegen.hpp index d7cabe879e..5de36c1aab 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -61,4 +61,6 @@ Buf *codegen_generate_builtin_source(CodeGen *g); TargetSubsystem detect_subsystem(CodeGen *g); +void codegen_release_caches(CodeGen *codegen); + #endif diff --git a/src/link.cpp b/src/link.cpp index fd1a77c1e9..ef5db4c4ad 100644 --- a/src/link.cpp +++ b/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(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(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(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 *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 *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(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 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); } } -- cgit v1.2.3