VirtualBox

source: vbox/trunk/include/iprt/ntwrap.mac@ 18364

Last change on this file since 18364 was 13445, checked in by vboxsync, 16 years ago

ntwrap.mac: undid header damange.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.8 KB
Line 
1;; @file
2; IPRT - Unwind hacks for Windows x64.
3;
4
5;
6; Copyright (C) 2006-2007 Sun Microsystems, Inc.
7;
8; This file is part of VirtualBox Open Source Edition (OSE), as
9; available from http://www.virtualbox.org. This file is free software;
10; you can redistribute it and/or modify it under the terms of the GNU
11; General Public License (GPL) as published by the Free Software
12; Foundation, in version 2 as it comes in the "COPYING" file of the
13; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15;
16; The contents of this file may alternatively be used under the terms
17; of the Common Development and Distribution License Version 1.0
18; (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19; VirtualBox OSE distribution, in which case the provisions of the
20; CDDL are applicable instead of those of the GPL.
21;
22; You may elect to license modified versions of this file under the
23; terms and conditions of either the GPL or the CDDL or both.
24;
25; Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
26; Clara, CA 95054 USA or visit http://www.sun.com if you need
27; additional information or have any questions.
28;
29
30%ifndef ___iprt_ntwrap_mac
31%define ___iprt_ntwrap_mac
32
33%include "iprt/asmdefs.mac"
34
35%ifdef RT_WITH_W64_UNWIND_HACK
36%ifdef RT_ARCH_AMD64
37
38
39;;
40; Common prolog, take the proc name as argument.
41; This creates a 0x80 byte stack frame.
42;
43%macro NtWrapProlog 1
44[proc_frame %1]
45 push rbp
46 [pushreg rbp]
47 mov rbp, rsp
48 [setframe rbp, 0]
49 sub rsp, 0x80
50 [allocstack 0x80]
51
52 ; save rdi and load rbp into it
53 mov [rbp - 8h], rdi
54 [savereg rdi, 0x78]
55 mov rdi, rbp
56[endprolog]
57%endmacro
58
59;;
60; Common epilog, take the proc name as argument.
61%macro NtWrapEpilog 1
62 ; restore rbp and rdi then return.
63 mov rbp, rdi
64 mov rdi, [rdi - 8h]
65 leave
66 ret
67[endproc_frame %1]
68%endmacro
69
70;;
71; Create a stack marker with the rbp. The marker is 32 byte big.
72; This is 32-byte aligned and 32 byte in size.
73;
74; Trashes r10
75%macro NtWrapCreateMarker 0
76 lea r10, [rbp - 30h]
77 and r10, ~1fh ; 32-byte align it.
78 mov dword [r10 ], 0x20080901
79 mov dword [r10 + 04h], 0x20080902
80 mov qword [r10 + 08h], rbp
81 mov dword [r10 + 10h], 0x20080903
82 mov dword [r10 + 14h], 0x20080904
83 mov qword [r10 + 18h], rbp
84%endmacro
85
86;;
87; Destroys the stack marker.
88;
89; Trashes r10
90%macro NtWrapDestroyMarker 0
91 lea r10, [rbp - 30h]
92 and r10, ~1fh ; 32-byte align it.
93 mov [r10 ], rbp
94 mov [r10 + 08h], rbp
95 mov [r10 + 10h], rbp
96 mov [r10 + 18h], rbp
97%endmacro
98
99;;
100; Wraps a function with 4 or less argument that will go into registers.
101%macro NtWrapDrv2DynFunctionWithAllRegParams 2
102extern NAME(%2)
103BEGINPROC %1%2
104 NtWrapProlog %1%2
105 NtWrapCreateMarker
106
107 call NAME(%2)
108
109 NtWrapDestroyMarker
110 NtWrapEpilog %1%2
111ENDPROC %1%2
112%endmacro
113
114BEGINCODE
115
116;
117; The following is not used when we're in the dynamically loaded code
118; and we wish to avoid it because it drags in a dependency on IoGetStackLimits.
119;
120; (Could perhaps fix this differently by instantiating NtWrapLocateMarkerHelper
121; in some way, but this works just the same...)
122;
123%ifndef IN_DYNAMICLOAD_CODE
124
125;;
126; Find the stack marker with the rbp of the entry frame.
127;
128; Search the current stack page inline, call a helper function
129; which does a safe search of any further stack pages.
130;
131; Trashes rax, r10 and r11.
132; Modifies rbp
133;
134%macro NtWrapLocateMarker 0
135 mov rax, rbp
136 and rax, ~1fh ; 32-byte align it.
137
138 ;
139 ; Calc remainig space in the current page. If we're on a
140 ; page boundrary, we'll search the entire previous page.
141 ;
142 mov r10, rax
143 neg r10
144 and r10, 0fffh
145 inc r10
146 shr r10, 5 ; /= 32 bytes
147 jz %%not_found ; If zero, take the slow path
148
149 ;
150 ; The search loop.
151 ;
152%%again:
153 dec r10
154 lea rax, [rax + 20h]
155 jz %%not_found
156 cmp dword [rax ], 0x20080901
157 je %%candidate
158 jmp %%again
159
160%%not_found:
161 call NAME(NtWrapLocateMarkerHelper)
162 jmp %%done
163
164%%candidate:
165 cmp dword [rax + 04h], 0x20080902
166 jne %%again
167 cmp dword [rax + 10h], 0x20080903
168 jne %%again
169 cmp dword [rax + 14h], 0x20080904
170 jne %%again
171 mov r11, [rax + 08h]
172 cmp r11, [rax + 18h]
173 jne %%again
174
175 ; found it, change rbp.
176 mov rbp, r11
177%%done:
178%endmacro
179
180;;
181; Wraps a function with 4 or less argument that will go into registers.
182%macro NtWrapDyn2DrvFunctionWithAllRegParams 2
183extern NAME(%2)
184BEGINPROC %1%2
185 NtWrapProlog %1%2
186 NtWrapLocateMarker
187
188 call NAME(%2)
189
190 NtWrapEpilog %1%2
191ENDPROC %1%2
192%endmacro
193
194;;
195; Wraps a function with 5 argument, where the first 4 goes into registers.
196%macro NtWrapDyn2DrvFunctionWith5Params 2
197extern NAME(%2)
198BEGINPROC %1%2
199 NtWrapProlog %1%2
200 NtWrapLocateMarker
201
202 mov r11, [rdi + 30h]
203 mov [rsp + 20h], r11
204 call NAME(%2)
205
206 NtWrapEpilog %1%2
207ENDPROC %1%2
208%endmacro
209
210;;
211; Wraps a function with 6 argument, where the first 4 goes into registers.
212%macro NtWrapDyn2DrvFunctionWith6Params 2
213extern NAME(%2)
214BEGINPROC %1%2
215 NtWrapProlog %1%2
216 NtWrapLocateMarker
217
218 mov r11, [rdi + 30h]
219 mov [rsp + 20h], r11
220 mov r10, [rdi + 38h]
221 mov [rsp + 28h], r10
222 call NAME(%2)
223
224 NtWrapEpilog %1%2
225ENDPROC %1%2
226%endmacro
227
228;;
229; Wraps a function with 7 argument, where the first 4 goes into registers.
230%macro NtWrapDyn2DrvFunctionWith7Params 2
231extern NAME(%2)
232BEGINPROC %1%2
233 NtWrapProlog %1%2
234 NtWrapLocateMarker
235
236 mov r11, [rdi + 30h]
237 mov [rsp + 20h], r11
238 mov r10, [rdi + 38h]
239 mov [rsp + 28h], r10
240 mov rax, [rdi + 40h]
241 mov [rsp + 30h], rax
242 call NAME(%2)
243
244 NtWrapEpilog %1%2
245ENDPROC %1%2
246%endmacro
247
248
249extern IoGetStackLimits
250
251;;
252; Helper that cautiously continues the stack marker search
253; NtWrapLocateMarker started.
254;
255; The stack layout at the time is something like this.
256; rbp+08h callers return address.
257; rbp-00h saved rbp
258; rbp-08h saved rdi
259; rbp-09h
260; thru unused.
261; rbp-80h
262; rbp-88h our return address.
263; rbp-89h
264; thru callee register dump zone.
265; rbp-a0h
266;
267; @param rax Current stack location.
268; @param rdi Parent stack frame pointer. (This should equal rbp on entry.)
269;
270; Trashes: rax, r10, r11.
271; Will use the callers stack frame for register saving ASSUMING that
272; rbp-80h thru rbp-09h is unused.
273;
274; Modifies: rbp
275;
276BEGINPROC NtWrapLocateMarkerHelper
277 ;
278 ; Prolog. Save volatile regs and reserve callee space.
279 ;
280 sub rsp, 20h ; For IoGetStackLimits().
281 mov [rdi - 80h], rax
282 mov [rdi - 78h], rcx
283 mov [rdi - 70h], rdx
284 mov [rdi - 68h], r8
285 mov [rdi - 60h], r9
286
287 ;
288 ; Call VOID IoGetStackLimits(OUT PULONG_PTR LowLimit, OUT PULONG_PTR HighLimit);
289 ;
290 ; Use rdi-40h for the high limit and rdi-50h for the low one, we're only
291 ; interested in the high one.
292 ;
293 lea rcx, [rdi - 40h] ; arg #1 LowLimit
294 lea rdx, [rdi - 50h] ; arg #2 HighLimit
295 mov [rdx], eax ; paranoia - init to end of current search.
296 call IoGetStackLimits
297
298 ;
299 ; Move the top address into r10, restore rax and continue
300 ; the search. Check that r10 is less than 3 pages from rax.
301 ;
302 mov rax, [rdi - 80h] ; Restore eax (see prolog)
303 mov r10, [rdi - 50h] ; HighLimit
304 and r10, ~1fh ; 32-byte align it (downwards)
305 sub r10, rax
306 jz .not_found ; If already at the top of the stack.
307 cmp r10, 3000h
308 jae .out_of_bounds ; If too far away, something is busted.
309 shr r10, 5 ; /= 32.
310
311 ; The loop body.
312.search_loop:
313 cmp dword [rax ], 0x20080901
314 je .candidate
315.continue_searching:
316 dec r10
317 jz .not_found
318 lea rax, [rax + 20h]
319 jmp .search_loop
320
321 ; Found the first marker, check for the rest.
322.candidate:
323 cmp dword [rax + 04h], 0x20080902
324 jne .continue_searching
325 cmp dword [rax + 10h], 0x20080903
326 jne .continue_searching
327 cmp dword [rax + 14h], 0x20080904
328 jne .continue_searching
329 mov r11, [rax + 08h]
330 cmp r11, [rax + 18h]
331 jne .continue_searching
332
333 ; found it, change rbp.
334 mov rbp, r11
335
336 ;
337 ; Restore registers and pop the stack frame.
338 ;
339.epilog:
340 mov r9, [rdi - 60h]
341 mov r8, [rdi - 68h]
342 mov rdx, [rdi - 70h]
343 mov rcx, [rdi - 78h]
344 ; mov rax, [rdi - 80h]
345 add rsp, 20h
346 ret
347
348 ;
349 ; Needless to say, this isn't supposed to happen. Thus the int3.
350 ; Note down r10 and rax.
351 ;
352.out_of_bounds:
353%ifdef DEBUG
354 int3
355%endif
356.not_found:
357%ifdef DEBUG
358 int3
359%endif
360 jmp .epilog
361ENDPROC NtWrapLocateMarkerHelper
362
363%endif ; !IN_DYNAMICLOAD_CODE
364
365%endif ; RT_ARCH_AMD64
366%endif ; RT_WITH_W64_UNWIND_HACK
367
368%endif ; !___iprt_ntwrap_mac
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette