Initial groundwork for ARM64 support

git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@7001 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
anders_k 2018-06-03 21:00:53 +00:00
parent bca384e691
commit 460b3f59a9
11 changed files with 101 additions and 51 deletions

View file

@ -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)
{

View file

@ -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 <intrin.h>
#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 <intrin.h>
# 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)

View file

@ -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

View file

@ -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!"

View file

@ -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'])

View file

@ -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')

View file

@ -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)

View file

@ -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 ###
######################################################################

View file

@ -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;

View file

@ -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); }

View file

@ -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] = {