diff --git a/Contrib/NSISdl/nsisdl.cpp b/Contrib/NSISdl/nsisdl.cpp index ec744bc9..c095ae63 100644 --- a/Contrib/NSISdl/nsisdl.cpp +++ b/Contrib/NSISdl/nsisdl.cpp @@ -191,7 +191,9 @@ extern "C" BOOL APIENTRY DllMain(HINSTANCE _hModule, DWORD ul_reason_for_call, return TRUE; } +#ifndef INT32_MAX #define INT32_MAX 0x7fffffff +#endif int MulDiv64(int nNumber, __int64 nNumerator, __int64 nDenominator) { diff --git a/Contrib/NSISdl/util.cpp b/Contrib/NSISdl/util.cpp index 7fd7c1df..834fffc2 100644 --- a/Contrib/NSISdl/util.cpp +++ b/Contrib/NSISdl/util.cpp @@ -77,13 +77,18 @@ void myitoa64(__int64 i, char *buffer) // Visual Studio 2015 (CLv19 x86) and some older versions of CLv14 x64 will optimize // our loop into a direct call to _memset and this fails to link because we don't use the CRT #if defined(_MSC_VER) && _MSC_VER+0 >= 1400 -#if defined(_MSC_FULL_VER) && _MSC_FULL_VER+0 >= 140050727 -#include -#else -EXTERN_C void __stosb(BYTE*,BYTE,size_t); -#endif //~ _MSC_FULL_VER >= 140050727 -#pragma intrinsic(__stosb) -#define CRTINTRINSIC_memset(p,c,s) __stosb((BYTE*)(p),(BYTE)(c),(s)) +# if defined(_MSC_FULL_VER) && _MSC_FULL_VER+0 >= 140050727 +# include +# else + EXTERN_C void __stosb(BYTE*,BYTE,size_t); +# endif //~ _MSC_FULL_VER >= 140050727 +# if defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64) // __stosb not available under _M_ARM nor _M_ARM64 +# pragma intrinsic(__stosb) +# define CRTINTRINSIC_memset(p,c,s) __stosb((BYTE*)(p),(BYTE)(c),(s)) +# elif defined(_M_ARM) || defined(_M_ARM64) // For _MSC_VER=1914 (VS 15.7.27703.2026/CL 19.14.26430) + EXTERN_C void* __cdecl memset(void *d, int v, size_t l) { char *p=(char*)d; while (l-- > 0) *p++=v; return d; } +# pragma function(memset) +# endif #endif //~ _MSC_VER void mini_memset(void *o,char i,int l) diff --git a/Contrib/System/Source/System.c b/Contrib/System/Source/System.c index a3eb5d28..a692c254 100644 --- a/Contrib/System/Source/System.c +++ b/Contrib/System/Source/System.c @@ -289,6 +289,32 @@ PLUGINFUNCTION(Get) } PLUGINFUNCTIONEND +#ifdef SYSTEM_ARM64 +/* +TODO: CallProc not implemeted. +Fake the behavior of the System plugin for the LoadImage API function so MUI works. +BUGBUG: MUI is leaking DeleteObject and failing GetClientRect +*/ +SystemProc* CallProc(SystemProc *proc) +{ + INT_PTR ret, *place; + int cmp = lstrcmp(proc->ProcName, sizeof(TCHAR) > 1 ? _T("LoadImageW") : _T("LoadImageA")); + if (!cmp) + { + ret = (INT_PTR) LoadImage((HINSTANCE)proc->Params[1].Value, + (LPCTSTR)proc->Params[2].Value, (UINT)proc->Params[3].Value, + (int)proc->Params[4].Value, (int)proc->Params[5].Value, + (UINT)proc->Params[6].Value); + LastError = GetLastError(); + } + else + proc->ProcResult = PR_ERROR, ret = 0, LastError = ERROR_INVALID_FUNCTION; + place = (INT_PTR*) proc->Params[0].Value; + if (proc->Params[0].Option != -1) place = (INT_PTR*) &(proc->Params[0].Value); + if (place) *place = ret; + return proc; +} +#endif //~ SYSTEM_ARM64 #ifdef _WIN64 /* BUGBUG: TODO: CallBack support not implemeted! @@ -1158,7 +1184,7 @@ void ParamsOut(SystemProc *proc) HANDLE CreateCallback(SystemProc *cbproc) { -#ifdef SYSTEM_AMD64 +#if defined(SYSTEM_AMD64) || defined(SYSTEM_ARM64) return BUGBUG64(HANDLE) NULL; #else char *mem; @@ -1357,7 +1383,7 @@ BOOL WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, LPVOID lpReserved) #ifdef SYSTEM_X86 retexpr[0] = (char) 0xC2; retexpr[2] = 0x00; -#elif defined(SYSTEM_AMD64) +#elif defined(SYSTEM_AMD64) || defined(SYSTEM_ARM64) retexpr[0] = BUGBUG64(0); #else #error TODO diff --git a/Contrib/System/Source/System.h b/Contrib/System/Source/System.h index ca51a125..72103b84 100644 --- a/Contrib/System/Source/System.h +++ b/Contrib/System/Source/System.h @@ -7,6 +7,8 @@ # define SYSTEM_AMD64 #elif defined(_M_IX86) || defined(__i386__) || defined(_X86_) # define SYSTEM_X86 +#elif defined(_M_ARM64) +# define SYSTEM_ARM64 #else # error "Unknown architecture!" #endif @@ -147,7 +149,7 @@ struct tag_CallbackThunk #pragma pack(pop) */ char asm_code[10]; - #elif defined(SYSTEM_AMD64) + #elif defined(SYSTEM_AMD64) || defined(SYSTEM_ARM64) char asm_code[BUGBUG64(1)]; // TODO: BUGBUG64 #else #error "Asm thunk not implemeted for this architecture!" @@ -159,7 +161,7 @@ struct tag_CallbackThunk // Free() only knows about pNext in CallbackThunk, it does not know anything about the assembly, that is where this helper comes in... #ifdef SYSTEM_X86 # define GetAssociatedSysProcFromCallbackThunkPtr(pCbT) ( (SystemProc*) *(unsigned int*) (((char*)(pCbT))+1) ) -#elif defined(SYSTEM_AMD64) +#elif defined(SYSTEM_AMD64) || defined(SYSTEM_ARM64) # define GetAssociatedSysProcFromCallbackThunkPtr(pCbT) BUGBUG64(NULL) #else # error "GetAssociatedSysProcFromCallbackThunkPtr not defined for the current architecture!" diff --git a/SCons/Config/ms b/SCons/Config/ms index ad76e7d6..2ea1456b 100644 --- a/SCons/Config/ms +++ b/SCons/Config/ms @@ -144,8 +144,8 @@ stub_env.Append(LINKFLAGS = ['$NODEFLIBS_FLAG']) # no default libraries stub_env.Append(LINKFLAGS = ['$MAP_FLAG']) # generate map file if msvs_version >= 10.0: - # no relocations that our resource editor ignores - stub_env.Append(LINKFLAGS = ['/FIXED']) + if stub_env['TARGET_ARCH'] != 'arm64': # LNK1246: '/FIXED' not compatible with 'ARM64' target machine + stub_env.Append(LINKFLAGS = ['/FIXED']) # no relocations that our resource editor ignores stub_uenv = stub_env.Clone() stub_uenv.Append(CPPDEFINES = ['_UNICODE', 'UNICODE']) diff --git a/SCons/Tools/mstoolkit.py b/SCons/Tools/mstoolkit.py index 4033260e..1edbb7a4 100644 --- a/SCons/Tools/mstoolkit.py +++ b/SCons/Tools/mstoolkit.py @@ -313,7 +313,7 @@ def generate(env): env.PrependENVPath('LIB', lib_path) env.PrependENVPath('PATH', exe_path) - env['ENV']['CPU'] = (targ_arc.upper(), 'i386')['x86' in targ_arc.lower()] # i386 or AMD64 + env['ENV']['CPU'] = (targ_arc.upper(), 'i386')['x86' in targ_arc.lower()] # AMD64/ARM64 or i386 env['ENV']['TARGETOS'] = 'BOTH' env['ENV']['APPVER'] = '4.0' env['ENV']['MSSDK'] = sdk_path @@ -340,6 +340,8 @@ def generate(env): if 'AMD64' in targ_arc.upper(): env['AS'] = 'ml64' + if 'ARM64' in targ_arc.upper(): + env['AS'] = 'armasm64' env['SHLINK'] = '$LINK' env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS /dll') diff --git a/SCons/utils.py b/SCons/utils.py index e12c7d04..372f8ae5 100644 --- a/SCons/utils.py +++ b/SCons/utils.py @@ -175,6 +175,8 @@ class MSPE: self.NTHOffset = fanew self.NTOHMagic = ReadU16LE(f, fanew+4+20) self.IsPEP = 0x20b == self.NTOHMagic # IMAGE_NT_OPTIONAL_HDR64_MAGIC? + def ReadMachine(self): + return ReadU16LE(self._f, self.NTHOffset+4+0) def ReadCharacteristics(self): return ReadU16LE(self._f, self.NTHOffset+4+18) def WriteCharacteristics(self, value): @@ -202,7 +204,8 @@ def SetPESecurityFlagsWorker(filepath): pe.WriteCharacteristics(ifh_c) ioh_dc = pe.ReadDllCharacteristics() ioh_dc |= 0x0100 # +IMAGE_DLLCHARACTERISTICS_NX_COMPAT (DEP) - ioh_dc |= 0x0400 # +IMAGE_DLLCHARACTERISTICS_NO_SEH + if pe.ReadMachine() != 0xaa64: # ARM64 forces exception directory? + ioh_dc |= 0x0400 # +IMAGE_DLLCHARACTERISTICS_NO_SEH ioh_dc |= 0x8000 # +IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE (TODO: Should we set this on .DLLs?) if not (ifh_c & 0x0001): # IMAGE_FILE_RELOCS_STRIPPED? ioh_dc |= 0x0040 # +IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE (ASLR) diff --git a/SConstruct b/SConstruct index 4a15a2a5..748f6cc7 100644 --- a/SConstruct +++ b/SConstruct @@ -171,7 +171,7 @@ opts.Add(('PATH', 'A colon-separated list of system paths instead of the default opts.Add(('TOOLSET', 'A comma-separated list of specific tools used for building instead of the default', None)) opts.Add(BoolVariable('MSTOOLKIT', 'Use Microsoft Visual C++ Toolkit', 'no')) opts.Add(EnumVariable('MSVS_VERSION', 'MS Visual C++ version', os.environ.get('MSVS_VERSION'), allowed_values=('6.0', '7.0', '7.1', '8.0', '8.0Exp', '9.0', '9.0Exp', '10.0', '10.0Exp'))) -opts.Add(EnumVariable('TARGET_ARCH', 'Target processor architecture', 'x86', allowed_values=('x86', 'amd64'))) +opts.Add(EnumVariable('TARGET_ARCH', 'Target processor architecture', 'x86', allowed_values=('x86', 'amd64', 'arm64'))) opts.Add(ListVariable('DOCTYPES', 'A list of document types that will be built', default_doctype, doctypes)) opts.Add(('CC', 'Override C compiler', None)) opts.Add(('CXX', 'Override C++ compiler', None)) @@ -285,6 +285,19 @@ f.close() ####### Common Functions ### ###################################################################### +def GetArcCPU(env): + if (not env.has_key('TARGET_ARCH')) or env['TARGET_ARCH'] == 'x86': + return 'x86' + return env['TARGET_ARCH'] + +def GetArcSuffix(env, unicode = None): + if unicode is None: + unicode = 'UNICODE' in env['CPPDEFINES'] + suff = '-unicode' + if not unicode: + suff = '-ansi' + return GetArcCPU(env) + suff + def SafeFile(f): from types import StringType @@ -334,8 +347,8 @@ defenv['INSTDISTDIR'] = defenv.Dir('#.instdist') defenv['TESTDISTDIR'] = defenv.Dir('#.test') defenv['DISTSUFFIX'] = '' -if defenv['TARGET_ARCH'] == 'amd64': - defenv['DISTSUFFIX'] += '-amd64' +if GetArcCPU(defenv) != 'x86': + defenv['DISTSUFFIX'] += GetArcCPU(defenv) if defenv.has_key('CODESIGNER'): defenv['DISTSUFFIX'] += '-signed' @@ -525,19 +538,6 @@ plugin_uenv = envs[7] Export('plugin_env plugin_uenv') -def GetArcCPU(env): - if (not env.has_key('TARGET_ARCH')) or env['TARGET_ARCH'] == 'x86': - return 'x86' - return env['TARGET_ARCH'] - -def GetArcSuffix(env, unicode = None): - if unicode is None: - unicode = 'UNICODE' in env['CPPDEFINES'] - suff = '-unicode' - if not unicode: - suff = '-ansi' - return GetArcCPU(env) + suff - ###################################################################### ####### Distribution ### ###################################################################### diff --git a/Source/build.cpp b/Source/build.cpp index daecfbcf..385f6c56 100644 --- a/Source/build.cpp +++ b/Source/build.cpp @@ -136,6 +136,9 @@ CEXEBuild::CEXEBuild(signed char pponly, bool warnaserror) : m_target_type=TARGET_X86ANSI; #ifdef _WIN32 if (sizeof(void*) > 4) m_target_type = TARGET_AMD64; // BUGBUG: scons 'TARGET_ARCH' should specify the default +#endif +#ifdef _M_ARM64 + m_target_type = TARGET_ARM64; // BUGBUG: scons 'TARGET_ARCH' should specify the default #endif build_unicode=TARGET_X86ANSI != m_target_type; build_lockedunicodetarget=false; @@ -3880,19 +3883,36 @@ int CEXEBuild::set_target_architecture_data() } definedlist.set(_T("NSIS_PTR_SIZE"), is_target_64bit() ? _T("8") : _T("4")); - tstring cpu = get_string_prefix(get_target_suffix(m_target_type), _T("-")); + const TCHAR* tsuff = get_target_suffix(m_target_type, _T("")); + if (!*tsuff) return PS_ERROR; + tstring cpu = get_string_prefix(tsuff, _T("-")); definedlist.set(_T("NSIS_CPU"), cpu.c_str()); // Used by Library.nsh to pick the correct RegTool - definedlist.del(_T("NSIS_IX86")); - definedlist.del(_T("NSIS_AMD64")); - if (TARGET_AMD64 == m_target_type) - definedlist.set(_T("NSIS_AMD64")); - else - definedlist.set(_T("NSIS_IX86"), build_unicode ? _T("400") : _T("300")); + struct { TARGETTYPE tt; const TCHAR *def; const TCHAR *val; } static const tdef[] = { + { TARGET_X86ANSI, _T("NSIS_IX86"), _T("300") }, + { TARGET_X86UNICODE, _T("NSIS_IX86"), _T("400") }, + { TARGET_AMD64, _T("NSIS_AMD64"), _T("1") }, + { TARGET_ARM64, _T("NSIS_ARM64"), _T("1") } + }; + size_t i; + for (i = 0; i < COUNTOF(tdef); ++i) definedlist.del(tdef[i].def); + for (i = 0; i < COUNTOF(tdef); ++i) if (tdef[i].tt == m_target_type) definedlist.set(tdef[i].def, tdef[i].val); return PS_OK; } +const TCHAR* CEXEBuild::get_target_suffix(CEXEBuild::TARGETTYPE tt, const TCHAR*defval) const +{ + switch(tt) + { + case TARGET_X86ANSI : return _T("x86-ansi"); + case TARGET_X86UNICODE: return _T("x86-unicode"); + case TARGET_AMD64 : return _T("amd64-unicode"); + case TARGET_ARM64 : return _T("arm64-unicode"); + default: return defval; + } +} + int CEXEBuild::change_target_architecture(TARGETTYPE tt) { const bool wide = TARGET_X86ANSI != tt; @@ -3932,17 +3952,6 @@ CEXEBuild::TARGETTYPE CEXEBuild::get_target_type(const TCHAR*s) const return TARGET_UNKNOWN; } -const TCHAR* CEXEBuild::get_target_suffix(CEXEBuild::TARGETTYPE tt, const TCHAR*defval) const -{ - switch(tt) - { - case TARGET_X86ANSI : return _T("x86-ansi"); - case TARGET_X86UNICODE: return _T("x86-unicode"); - case TARGET_AMD64 : return _T("amd64-unicode"); - default: return defval; - } -} - void CEXEBuild::print_bad_targettype_parameter(const TCHAR*cmdname, const TCHAR*prefix) const { tstring errstr = cmdname; diff --git a/Source/build.h b/Source/build.h index 18d84e8d..2e267dbc 100644 --- a/Source/build.h +++ b/Source/build.h @@ -230,6 +230,7 @@ class CEXEBuild { TARGET_X86ANSI = TARGETFIRST, TARGET_X86UNICODE, TARGET_AMD64, // Always Unicode + TARGET_ARM64, // Always Unicode TARGET_UNKNOWN, TARGETCOUNT = (TARGET_UNKNOWN-TARGETFIRST) } TARGETTYPE; @@ -238,7 +239,7 @@ class CEXEBuild { bool m_previous_x86_unicode; const TCHAR* get_target_suffix(CEXEBuild::TARGETTYPE tt, const TCHAR*defval = _T("?")) const; const TCHAR* get_target_suffix() const { return get_target_suffix(m_target_type); } - static bool is_targettype_64bit(TARGETTYPE tt) { return TARGET_AMD64 == tt; } + static bool is_targettype_64bit(TARGETTYPE tt) { return TARGET_AMD64 == tt || TARGET_ARM64 == tt; } bool is_target_64bit() const { return is_targettype_64bit(m_target_type); } void print_bad_targettype_parameter(const TCHAR*cmdname, const TCHAR*prefix = _T("")) const; unsigned int get_header_size() const { return (unsigned int)sizeof(header) + (is_target_64bit() ? (4 * BLOCKS_NUM) : 0); } diff --git a/Source/script.cpp b/Source/script.cpp index d2c620cc..16635bf7 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -876,7 +876,7 @@ int CEXEBuild::process_jump(LineParser &line, int wt, int *offs) #define SECTION_FIELD_GET(field) (FIELD_OFFSET(section, field)/sizeof(int)) #define SECTION_FIELD_SET(field) (-1 - (int)(FIELD_OFFSET(section, field)/sizeof(int))) -#define INVALIDREGROOT ( (HKEY) 0x8000baad ) +#define INVALIDREGROOT ( (HKEY) (UINT_PTR) 0x8000baad ) static HKEY ParseRegRootKey(LineParser &line, int tok) { static const TCHAR *rootkeys[2] = {