File: Call-amd64.S

package info (click to toggle)
nsis 3.04-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 12,076 kB
  • sloc: cpp: 36,735; ansic: 26,691; python: 1,282; asm: 712; xml: 511; pascal: 215; makefile: 205
file content (178 lines) | stat: -rwxr-xr-x 4,439 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
;# 
;# This file is a part of NSIS.
;#
;# Copyright (C) 2014-2018 Anders Kjersem
;#
;# Licensed under the zlib/libpng license (the "License");
;# you may not use this file except in compliance with the License.
;#
;# Licence details can be found in the file COPYING.
;#
;# This software is provided 'as-is', without any express or implied
;# warranty.
;# 
;#
;# 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

SECTION_DATA equ .data
SECTION_CODE equ .code

FUNC_DECL MACRO name
name PROC
ENDM
FUNC_END MACRO name
name ENDP
ENDM

;# ~MASM
IF 0
; .else
;# GNU
.intel_syntax noprefix
.set __GNU__,1

#define IFDEF .ifdef
#define ELSE  .else
#define ENDIF .endif

#define SECTION_DATA .data
#define SECTION_CODE .text

#define END          .end
#define EXTERN       .extern

.macro FUNC_DECL name
.global \name
.func   \name
\name:
.endm
.macro FUNC_END name
.endfunc
.endm

;# ~GNU
ENDIF


IFDEF SYSTEM_LOG_DEBUG
  EXTERN __imp_IsDebuggerPresent : PROC
ENDIF

EXTERN GetProcOffset       : PROC
EXTERN GetParamsOffset     : PROC
EXTERN GetSizeOfProcParam  : PROC
EXTERN GetValueOffsetParam : PROC
EXTERN SetCallProcResultValues   : PROC


SECTION_CODE


FUNC_DECL CallProc2 ;# rcx=SystemProc* edx=ParamCount
  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
  imul eax, edx, 8
  and edx, 1
  jnz noparamalignpadding
  lea eax, [eax+8] ;# sizeof(params) + 8 will make us 16 byte aligned
noparamalignpadding:
  cmp eax, 40 ;# The ABI guarantees shadow space for the 4 register parameters
  ja computedstacksize
  mov eax, 40 ;# Minimum (4*8) + 8 to align
computedstacksize:
  mov r12d, eax ;# Save stack size (Zero-extended mov)
  sub rsp, r12

IFDEF SYSTEM_LOG_DEBUG
  ;# BUGBUG: Remove this
  call qword ptr [__imp_IsDebuggerPresent]
  test eax, eax
  jz nodbgbrk
  int 3
  nodbgbrk:
ENDIF

  ;# We are going to set all stack parameters including the first 4, 
  ;# it does not hurt to do that and it allows us to copy them to 
  ;# their registers without reading pSystemProc->Params[1..3] again
  call GetSizeOfProcParam
  mov r9, rax ;# Store sizeof(ProcParameter)
  call GetValueOffsetParam
  mov r8, rax ;# Store FIELD_OFFSET(ProcParameter,Value)
  call GetParamsOffset
  lea r10, [pSystemProc+rax] ;# Store pSystemProc+FIELD_OFFSET(SystemProc,Params)
  mov ecx, r13d ;# Zero-extended mov
  test rcx, rcx
  jz callthefunc
setparameter:
  mov rax, r9
  mul rcx ;# rax = sizeof(ProcParameter) * paramidx (paramidx is 1 based because the return value is stored in Params[0])
  add rax, r10 ;# rax += pSystemProc->Params
  mov rax, qword ptr [rax+r8] ;# rax = pSystemProc->Params[paramidx].Value
  dec rcx
  mov [rsp+(8*rcx)], rax
  inc rcx
  loop setparameter
  ;# The 4 parameter registers are all volatile so we might as well assign all of them:
  ;# setparam4:
  ;#   cmp r13d, 4
  ;#   jb setparam3
  mov r9, [rsp+(8*3)]
  ;# setparam3:
  ;#   cmp r13d, 3
  ;#   jb setparam2
  mov r8, [rsp+(8*2)]
  ;# setparam2:
  ;#   cmp r13d, 2
  ;#   jb setparam1
  mov rdx, [rsp+(8*1)]
  ;# setparam1:
  ;#   cmp r13d, 1
  ;#   jb callthefunc
  mov rcx, [rsp+(8*0)]

callthefunc:
  call GetProcOffset
  mov r10, qword ptr [pSystemProc+rax]
  xor rax, rax ;# Fix bug #1535007
  call r10
  mov rcx, pSystemProc
  mov rdx, rax ;# Return value
  call SetCallProcResultValues ;# Store GetLastError() and return value
  ;# mov rax, pSystemProc has been performed by SetCallProcResultValues

  ;# Epilog:
  ;# http://msdn.microsoft.com/en-us/library/tawsa7cb claims that only 
  ;# 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+8]
  mov r13, [rsp+16]
  mov r14, [rsp+24]
  ;#mov r15, [rsp+32]
  ret
FUNC_END CallProc2


END