summaryrefslogtreecommitdiffstats
path: root/src/kash/shforkA-win.asm
blob: 6db4f28231cc995410099857d30743c3d346ab3e (plain)
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
; $Id: shforkA-win.asm 2416 2010-09-14 00:30:30Z bird $
;; @file
; shforkA-win.asm - assembly routines used when forking on Windows.
;

;
; Copyright (c) 2009-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
;
; This file is part of kBuild.
;
; kBuild is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 3 of the License, or
; (at your option) any later version.
;
; kBuild is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with kBuild.  If not, see <http://www.gnu.org/licenses/>
;
;

;*******************************************************************************
;*      Defined Constants And Macros                                           *
;*******************************************************************************
%ifdef KBUILD_ARCH_AMD64
 %define NAME(name) name
%else
 %define NAME(name) _ %+ name
%endif

;; The stack size. This is also defined in shfork-win.c.
%define SHFORK_STACK_SIZE (1*1024*1024)


;*******************************************************************************
;*      External Symbols                                                       *
;*******************************************************************************
extern NAME(real_main)
extern NAME(shfork_maybe_forked)
extern NAME(shfork_body)


[section .text]

;;
; C main() wrapper.
;
NAME(main):
global NAME(main)
%ifdef KBUILD_ARCH_AMD64
[proc_frame main]
%endif

        ;
        ; Prolog, spilling parameters from registers.
        ;
%ifdef KBUILD_ARCH_AMD64
        [pushreg rbp]
        push    rbp
        [setframe rbp, 0]
        mov     rbp, rsp
        [allocstack 0x40]
        sub     rsp, 40h
        and     rsp, ~1fh
        mov     [rbp-08h], rcx          ; argc
        mov     [rbp-10h], rdx          ; argv
        mov     [rbp-18h], r8           ; envp
        [endprolog]
%else
        push    ebp
        mov     ebp, esp
        sub     esp, 40h
        and     esp, ~1fh
%endif

        ;
        ; Call shfork_maybe_forked. This will not return if we're forking.
        ;
%ifndef KBUILD_ARCH_AMD64
        mov     ecx, [ebp +  8h]        ; argc
        mov     edx, [ebp + 0ch]        ; argv
        mov     eax, [ebp + 10h]        ; envp
        mov     [esp     ], ecx
        mov     [esp + 4h], edx
        mov     [esp + 8h], eax
%endif
        call    NAME(shfork_maybe_forked)

        ;
        ; Ok, it returned which means we're not forking.
        ;
        ; The accumulator register is now pointing to the top of the
        ; stack we're going to call real_main on. Switch and call it.
        ;
        ; The TIB adjustments is required or we'll crash in longjmp/unwind.
        ;
%ifdef KBUILD_ARCH_AMD64
        mov     [rsp + 18h], rax
        mov     [rax -  8h], rsp

        mov     r10, [gs:08h]           ; StackBase  (the higher value)
        mov     r11, [gs:10h]           ; StackLimit (the lower value)
        mov     [rax - 10h], r10
        mov     [rax - 18h], r11
        cmp     rax, r10
        jb      .below
        mov     [gs:08h], rax
.below:
        lea     r9, [rax - SHFORK_STACK_SIZE]
        cmp     r9, r11
        ja      .above
        mov     [gs:10h], r9
.above:

        mov     rcx, [rbp - 08h]        ; argc
        mov     rdx, [rbp - 10h]        ; argv
        mov     r8,  [rbp - 18h]        ; envp

        lea     rsp, [rax - 40h]        ; Switch!
%else
        mov     [esp + 18h], eax
        mov     [eax - 4], esp
        lea     esp, [eax - 40h]        ; Switch!

        mov     edx, [fs:04h]           ; StackBase  (the higher value)
        mov     ecx, [fs:08h]           ; StackLimit (the lower value)
        mov     [eax - 10h], edx
        mov     [eax - 18h], ecx
        cmp     eax, edx
        jb      .below
        mov     [fs:04h], eax
.below:
        lea     edx, [eax - SHFORK_STACK_SIZE]
        cmp     edx, ecx
        ja      .above
        mov     [fs:08h], edx
.above:

        mov     ecx, [ebp +  8h]        ; argc
        mov     edx, [ebp + 0ch]        ; argv
        mov     eax, [ebp + 10h]        ; envp

        mov     [esp     ], ecx
        mov     [esp + 4h], edx
        mov     [esp + 8h], eax
%endif
        call    NAME(real_main)

        ;
        ; Switch back the stack, restore the TIB fields and we're done.
        ;
%ifdef KBUILD_ARCH_AMD64
        lea     r11, [rsp + 40h]
        mov     rsp, [rsp + 38h]
        mov     r8, [r11 - 10h]
        mov     r9, [r11 - 18h]
        mov     [gs:08h], r8
        mov     [gs:10h], r9
%else
        lea     edx, [esp + 40h]
        mov     esp, [esp + 2ch]
        mov     ecx, [edx - 10h]
        mov     edx, [edx - 18h]
        mov     [fs:04h], ecx
        mov     [fs:08h], edx
%endif
        leave
        ret
%ifdef KBUILD_ARCH_AMD64
[endproc_frame main]
%endif


;;
; sh_fork() worker
;
; @returns      See fork().
; @param        psh
;
NAME(shfork_do_it):
global NAME(shfork_do_it)
%ifdef KBUILD_ARCH_AMD64
        [proc_frame shfork_do_it]
        [pushreg rbp]
        push    rbp
        [setframe rbp, 0]
        mov     rbp, rsp
        [allocstack 0x400]
        sub     rsp, 400h
        and     rsp, ~1ffh
[endprolog]
%else
        push    ebp
        mov     ebp, esp
        sub     esp, 400h
        and     esp, ~1ffh
%endif

        ;
        ; Save most registers so they can be restored in the child.
        ;
%ifdef KBUILD_ARCH_AMD64
        fxsave  [rsp]
        mov     [rsp + 200h], rbp
        mov     [rsp + 208h], rax
        mov     [rsp + 210h], rbx
        mov     [rsp + 218h], rcx
        mov     [rsp + 220h], rdx
        mov     [rsp + 228h], rsi
        mov     [rsp + 230h], rdi
        mov     [rsp + 238h],  r8
        mov     [rsp + 240h],  r9
        mov     [rsp + 248h], r10
        mov     [rsp + 250h], r11
        mov     [rsp + 258h], r12
        mov     [rsp + 260h], r13
        mov     [rsp + 268h], r14
        mov     [rsp + 270h], r15
%else
        fxsave  [esp]
        mov     [esp + 200h], ebp
        mov     [esp + 208h], eax
        mov     [esp + 210h], ebx
        mov     [esp + 218h], ecx
        mov     [esp + 220h], edx
        mov     [esp + 228h], esi
        mov     [esp + 230h], edi
%endif

        ;
        ; Call the shfork_body that will spawn the child and all that.
        ;
%ifdef KBUILD_ARCH_AMD64
        ;mov     rcx, rcx               ; psh
        mov     rdx, rsp                ; stack_ptr
        sub     rsp, 20h
        call    NAME(shfork_body)
        lea     rsp, [rsp + 20h]
%else
        mov     edx, esp
        mov     ecx, [ebp + 8h]         ; psh
        sub     esp, 20h
        mov     [esp    ], ecx
        mov     [esp + 4], edx          ; stack_ptr
        call    NAME(shfork_body)
        lea     esp, [esp + 20h]
%endif

        ;
        ; Just leave the function, no need to restore things.
        ;
        leave
        ret
%ifdef KBUILD_ARCH_AMD64
[endproc_frame shfork_do_it]
%endif


;;
; Switch the stack, restore the register and leave as if we'd called shfork_do_it.
;
; @param        cur     Current stack pointer.
; @param        base    The stack base  (higher value).
; @param        limit   The stack limit (lower value).
;
NAME(shfork_resume):
global NAME(shfork_resume)
%ifdef KBUILD_ARCH_AMD64
        mov     rsp, rcx
%else
        mov     ecx, [esp + 4]
        mov     edx, [esp + 8]
        mov     eax, [esp + 12]
        mov     esp, ecx
%endif

        ;
        ; Adjust stack stuff in the TIB (longjmp/unwind).
        ;
%ifdef KBUILD_ARCH_AMD64
        cmp     rdx, [gs:08h]           ; StackBase  (the higher value)
        jb      .below
        mov     [gs:08h], rdx
.below:
        cmp     r8,  [gs:10h]           ; StackLimit
        ja      .above
        mov     [gs:10h], r8
.above:
%else
        cmp     edx, [fs:04h]           ; StackBase  (the higher value)
        jb      .below
        mov     [fs:04h], edx
.below:
        cmp     eax, [fs:08h]           ; StackLimit
        ja      .above
        mov     [fs:08h], eax
.above:
%endif

        ;
        ; Restore most of the registers.
        ;
        ;; @todo xmm registers may require explicit saving/restoring...
%ifdef KBUILD_ARCH_AMD64
        frstor  [rsp]
        mov     rbp, [rsp + 200h]
        mov     rax, [rsp + 208h]
        mov     rbx, [rsp + 210h]
        mov     rcx, [rsp + 218h]
        mov     rdx, [rsp + 220h]
        mov     rsi, [rsp + 228h]
        mov     rdi, [rsp + 230h]
        mov      r8, [rsp + 238h]
        mov      r9, [rsp + 240h]
        mov     r10, [rsp + 248h]
        mov     r11, [rsp + 250h]
        mov     r12, [rsp + 258h]
        mov     r13, [rsp + 260h]
        mov     r14, [rsp + 268h]
        mov     r15, [rsp + 270h]
%else
        frstor  [esp]
        mov     ebp, [esp + 200h]
        mov     eax, [esp + 208h]
        mov     ebx, [esp + 210h]
        mov     ecx, [esp + 218h]
        mov     edx, [esp + 220h]
        mov     esi, [esp + 228h]
        mov     edi, [esp + 230h]
%endif
        xor     eax, eax                ; the child returns 0.
        leave
        ret