* Basic System::Call support when compiling with 64-bit MinGW/GCC toolchain
* Win64 fixes git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6607 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
parent
757d16f937
commit
286edd20c4
41 changed files with 335 additions and 232 deletions
|
@ -29,34 +29,30 @@ Import('BuildPlugin env')
|
|||
defs = ['SYSTEM_EXPORTS']
|
||||
msvc = 'msvc' in env['TOOLS'] or 'mstoolkit' in env['TOOLS']
|
||||
|
||||
if env['TARGET_ARCH'] != 'amd64' or msvc: # BUGBUG: Call-amd64.S is missing GAS macros
|
||||
srcsuff = ''
|
||||
if env['TARGET_ARCH'] != 'x86':
|
||||
srcsuff = '-' + env['TARGET_ARCH']
|
||||
defs += ['SYSTEM_NOCALLBACKS'] # BUGBUG: Remove this when CallBack() is implemented
|
||||
if msvc: # BUGBUG: Remove this when GAS is fixed
|
||||
defs += ['SYSTEM_PARTIALCALLSUPPORT']
|
||||
filename = 'Call' + srcsuff
|
||||
srcsuff = ''
|
||||
if env['TARGET_ARCH'] != 'x86':
|
||||
srcsuff = '-' + env['TARGET_ARCH']
|
||||
defs += ['SYSTEM_NOCALLBACKS'] # BUGBUG: Remove this when CallBack() is implemented
|
||||
defs += ['SYSTEM_PARTIALCALLSUPPORT']
|
||||
filename = 'Call' + srcsuff
|
||||
|
||||
src_ascpp = """
|
||||
#if 0 /* a C style comment */
|
||||
ERROR: assembler-with-cpp required!
|
||||
#else
|
||||
.end
|
||||
#endif
|
||||
"""
|
||||
conf = env.Configure()
|
||||
if conf.TryCompile('END', '.S'):
|
||||
files += ['Source/'+filename+'.S']
|
||||
elif (not msvc) and conf.TryCompile(src_ascpp, '.S'):
|
||||
files += ['Source/'+filename+'CPP.S']
|
||||
elif (not msvc) and conf.TryCompile(src_ascpp, '.sx'):
|
||||
files += ['Source/'+filename+'CPP.sx']
|
||||
else:
|
||||
print 'WARNING: System.dll: unable to find assembler for '+filename+'.S'
|
||||
conf.Finish()
|
||||
src_ascpp = """
|
||||
#if 0 /* a C style comment */
|
||||
ERROR: assembler-with-cpp required!
|
||||
#else
|
||||
.end
|
||||
#endif
|
||||
"""
|
||||
conf = env.Configure()
|
||||
if conf.TryCompile('END', '.S'):
|
||||
files += ['Source/'+filename+'.S']
|
||||
elif (not msvc) and conf.TryCompile(src_ascpp, '.S'):
|
||||
files += ['Source/'+filename+'CPP.S']
|
||||
elif (not msvc) and conf.TryCompile(src_ascpp, '.sx'):
|
||||
files += ['Source/'+filename+'CPP.sx']
|
||||
else:
|
||||
print 'WARNING: System.dll: missing Win64 code, dynamic function calls not supported'
|
||||
print 'WARNING: System.dll: unable to find assembler for '+filename+'.S'
|
||||
conf.Finish()
|
||||
|
||||
BuildPlugin(
|
||||
target,
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
;# MASM:
|
||||
;# ml64.exe /c Call-amd64.S
|
||||
;#
|
||||
;# Notes:
|
||||
;# * MASM does not accept 0x* constants and GAS does not accept *h constants in Intel mode, must use decimal!
|
||||
;#
|
||||
|
||||
; .if 0
|
||||
;# MASM
|
||||
|
@ -34,6 +37,7 @@ IF 0
|
|||
; .else
|
||||
;# GNU
|
||||
.intel_syntax noprefix
|
||||
.set __GNU__,1
|
||||
|
||||
#define IFDEF .ifdef
|
||||
#define ELSE .else
|
||||
|
@ -45,6 +49,15 @@ IF 0
|
|||
#define END .end
|
||||
#define EXTERN .extern
|
||||
|
||||
.macro FUNC_DECL name
|
||||
.global \name
|
||||
.func \name
|
||||
\name:
|
||||
.endm
|
||||
.macro FUNC_END name
|
||||
.endfunc
|
||||
.endm
|
||||
|
||||
;# ~GNU
|
||||
ENDIF
|
||||
|
||||
|
@ -68,14 +81,18 @@ SECTION_CODE
|
|||
|
||||
|
||||
FUNC_DECL CallProc2 ;# rcx=SystemProc* edx=ParamCount
|
||||
mov [rsp+8h], r12
|
||||
mov [rsp+10h], r13
|
||||
mov [rsp+18h], r14
|
||||
;#mov [rsp+20h], r15
|
||||
mov [rsp+8], r12
|
||||
mov [rsp+16], r13
|
||||
mov [rsp+24], r14
|
||||
;#mov [rsp+32], r15
|
||||
|
||||
;# The stack is unaligned on function entry. We have to calculate the required
|
||||
;# stack size for our parameters + maybe 8 padding bytes to end up 16 byte aligned.
|
||||
IFDEF __GNU__
|
||||
#define pSystemProc r14
|
||||
ELSE
|
||||
pSystemProc equ r14
|
||||
ENDIF
|
||||
mov pSystemProc, rcx ;# Save SystemProc*
|
||||
;# Not required since we zero-extend eax: xor rax, rax
|
||||
mov r13d, edx ;# Save ParamCount
|
||||
|
@ -84,9 +101,9 @@ FUNC_DECL CallProc2 ;# rcx=SystemProc* edx=ParamCount
|
|||
jnz noparamalignpadding
|
||||
lea eax, [eax+8] ;# sizeof(params) + 8 will make us 16 byte aligned
|
||||
noparamalignpadding:
|
||||
cmp eax, 28h ;# The ABI guarantees shadow space for the 4 register parameters
|
||||
cmp eax, 40 ;# The ABI guarantees shadow space for the 4 register parameters
|
||||
ja computedstacksize
|
||||
mov eax, 28h ;# Minimum (4*8) + 8 to align
|
||||
mov eax, 40 ;# Minimum (4*8) + 8 to align
|
||||
computedstacksize:
|
||||
mov r12d, eax ;# Save stack size (Zero-extended mov)
|
||||
sub rsp, r12
|
||||
|
@ -170,10 +187,10 @@ capturegle_done:
|
|||
;# add/lea rsp and pop is valid in the epilog. Unwind might fail on our version?
|
||||
add rsp, r12 ;# Restore stack
|
||||
;# Restore nonvolatile registers:
|
||||
mov r12, [rsp+8h]
|
||||
mov r13, [rsp+10h]
|
||||
mov r14, [rsp+18h]
|
||||
;#mov r15, [rsp+20h]
|
||||
mov r12, [rsp+8]
|
||||
mov r13, [rsp+16]
|
||||
mov r14, [rsp+24]
|
||||
;#mov r15, [rsp+32]
|
||||
ret
|
||||
FUNC_END CallProc2
|
||||
|
||||
|
|
8
Contrib/System/Source/Call-amd64CPP.S
Normal file
8
Contrib/System/Source/Call-amd64CPP.S
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifdef _MSC_VER
|
||||
#error "MSVC is supposed to use the plain .S file!"
|
||||
#endif
|
||||
#if 0
|
||||
ERROR: assembler-with-cpp required!
|
||||
#else
|
||||
#include "Call-amd64.S"
|
||||
#endif
|
8
Contrib/System/Source/Call-amd64CPP.sx
Normal file
8
Contrib/System/Source/Call-amd64CPP.sx
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifdef _MSC_VER
|
||||
#error "MSVC is supposed to use the plain .S file!"
|
||||
#endif
|
||||
#if 0
|
||||
ERROR: assembler-with-cpp required!
|
||||
#else
|
||||
#include "Call-amd64CPP.S"
|
||||
#endif
|
|
@ -276,31 +276,8 @@ PLUGINFUNCTION(Get)
|
|||
|
||||
#ifdef _WIN64
|
||||
/*
|
||||
TODO: CallProc/Back 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
|
||||
BUGBUG: TODO: CallBack support not implemeted!
|
||||
*/
|
||||
#ifndef SYSTEM_PARTIALCALLSUPPORT
|
||||
SystemProc* CallProc(SystemProc *proc)
|
||||
{
|
||||
INT_PTR ret, *place;
|
||||
LastError = lstrcmp(proc->ProcName, sizeof(TCHAR) > 1 ? _T("LoadImageW") : _T("LoadImageA"));
|
||||
if (!LastError)
|
||||
{
|
||||
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;
|
||||
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_PARTIALCALLSUPPORT
|
||||
SystemProc* CallBack(SystemProc *proc)
|
||||
{
|
||||
proc->ProcResult = PR_ERROR;
|
||||
|
@ -461,7 +438,7 @@ SystemProc *PrepareProc(BOOL NeedForCall)
|
|||
TCHAR *ibuf, *ib, *sbuf, *cbuf, *cb;
|
||||
unsigned int UsedTString = 0;
|
||||
|
||||
#if defined(__GNUC__) && ((__GNUC__ * 1000) + __GNUC_MINOR__) < 4006
|
||||
#ifdef __GNUC__
|
||||
temp3 = 0; // "warning: 'temp3' may be used uninitialized in this function": temp3 is set to 0 when we start parsing a new parameter
|
||||
#endif
|
||||
|
||||
|
@ -692,14 +669,7 @@ SystemProc *PrepareProc(BOOL NeedForCall)
|
|||
case _T('0'): case _T('1'): case _T('2'): case _T('3'): case _T('4'):
|
||||
case _T('5'): case _T('6'): case _T('7'): case _T('8'): case _T('9'):
|
||||
// Numeric inline
|
||||
#if defined(__GNUC__) && ((__GNUC__ * 1000) + __GNUC_MINOR__) >= 4006
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wuninitialized" // temp3 is set to 0 when we start parsing a new parameter
|
||||
#endif
|
||||
if (temp3 == 0)
|
||||
#if defined(__GNUC__) && ((__GNUC__ * 1000) + __GNUC_MINOR__) >= 4006
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
{
|
||||
ib--;
|
||||
// It's stupid, I know, but I'm too lazy to do another thing
|
||||
|
@ -768,14 +738,7 @@ SystemProc *PrepareProc(BOOL NeedForCall)
|
|||
if (temp3 == 1)
|
||||
proc->Params[ParamIndex].Output = (int) temp4; // Note: As long as we never assign a pointer to temp4 when parsing a destination the cast to int is OK.
|
||||
// Next parameter is output or something else
|
||||
#if defined(__GNUC__) && ((__GNUC__ * 1000) + __GNUC_MINOR__) >= 4006
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wuninitialized"
|
||||
#endif
|
||||
temp3++;
|
||||
#if defined(__GNUC__) && ((__GNUC__ * 1000) + __GNUC_MINOR__) >= 4006
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
}
|
||||
|
||||
ChangesDone = PCD_DONE;
|
||||
|
@ -1384,7 +1347,7 @@ Returns offset for element Clone of SystemProc structure
|
|||
*/
|
||||
unsigned int GetCloneOffset(void)
|
||||
{
|
||||
return (unsigned int)(&(((SystemProc *)0)->Clone));
|
||||
return (unsigned int)(UINT_PTR) (&(((SystemProc *)0)->Clone));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1392,7 +1355,7 @@ Returns offset for element ProcName of SystemProc structure
|
|||
*/
|
||||
unsigned int GetProcNameOffset(void)
|
||||
{
|
||||
return (unsigned int)(&(((SystemProc *)0)->ProcName));
|
||||
return (unsigned int)(UINT_PTR) (&(((SystemProc *)0)->ProcName));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1400,7 +1363,7 @@ Returns offset for element ArgsSize of SystemProc structure
|
|||
*/
|
||||
unsigned int GetArgsSizeOffset(void)
|
||||
{
|
||||
return (unsigned int)(&(((SystemProc *)0)->ArgsSize));
|
||||
return (unsigned int)(UINT_PTR) (&(((SystemProc *)0)->ArgsSize));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1432,7 +1395,7 @@ Returns offset for element Size of ProcParameter structure
|
|||
*/
|
||||
unsigned int GetSizeOffsetParam(void)
|
||||
{
|
||||
return (unsigned int)(&(((ProcParameter *)0)->Size));
|
||||
return (unsigned int)(UINT_PTR) (&(((ProcParameter *)0)->Size));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -155,10 +155,8 @@ extern void ParamsDeAllocate(SystemProc *proc);
|
|||
extern void ParamsIn(SystemProc *proc);
|
||||
extern void ParamsOut(SystemProc *proc);
|
||||
#ifdef SYSTEM_AMD64
|
||||
#ifdef SYSTEM_PARTIALCALLSUPPORT
|
||||
extern SystemProc* CallProc2(SystemProc *proc, UINT_PTR ParamCount);
|
||||
#define CallProc(p) CallProc2((p), (p)->ParamCount) // ParamCount is passed as a parameter so CallProc2 can determine the required stack size without a function call
|
||||
#endif
|
||||
#else // !SYSTEM_AMD64
|
||||
extern SystemProc* CallProc(SystemProc *proc);
|
||||
#endif // ~SYSTEM_AMD64
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue