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
|
;***
;longjmp.asm
;
; Copyright (C) 1994 Microsoft Corporation. All rights reserved.
;
;Purpose:
; Contains setjmp(), longjmp() & raisex() routines;
; split from exsup.asm for granularity purposes.
;
;Notes:
;
;Revision History:
; 01-12-94 PML Split from setjmp.asm, added C9.0 generic EH
; callback for unwind.
;
;*******************************************************************************
;hnt = -D_WIN32_ -Dsmall32 -Dflat32 -Mx $this;
;Define small32 and flat32 since these are not defined in the NT build process
small32 equ 1
flat32 equ 1
.xlist
include pversion.inc
?DFDATA = 1
?NODATA = 1
include cmacros.mas
include exsup.inc
.list
BeginDATA
COMM __setjmpexused:dword
EndDATA
assumes DS,DATA
assumes FS,DATA
BeginCODE
if @Version LT 600
;this needs to go here to work around a masm5 bug. (emits wrong fixup)
assumes CS,FLAT
endif
; Following symbols defined in exsup.asm, sehsupp.c
extrn __except_list:near
extrn __global_unwind2:near
extrn __local_unwind2:near
extrn __rt_probe_read4@4:near
; int
; longjmp (
; IN jmp_buf env
; IN int val)
;
; Routine Description:
;
; Restore the stack and register environment saved by _setjmp.
; Reloads callee-save registers and stack pointer to that saved in
; the jmp_buf, then returns to the point of the _setjmp call.
;
; If exception unwinding is enabled, also reload the exception state
; from the jmp_buf by doing an unwind (both global and local) back
; to the old state. Do so by checking for a new-format (C9.0)
; jmp_buf, and call the EH longjmp unwinder saved therein if
; found, else assume a C8.0-vintage jmp_buf and SEH.
;
; Arguments:
;
; env - Address of the buffer holding the reload state
; val - Value to return from the _setjmp callsite (if nonzero)
;
; Return Value:
;
; None. longjmp does not return directly, but instead continues
; execution from the point of the _setjmp used to initialize the
; jmp_buf. That call will return the 'val' parameter if nonzero,
; else a one.
cProc longjmp,<C,PUBLIC>
cBegin
mov ebx, [esp+4] ;get jmp_buf
;restore ebp before possible call to local_unwind-er
; the call to global/local unwind will preserve this (callee save).
mov ebp, [ebx.saved_ebp] ;set up bp
ifdef _NTSDK
cmp __setjmpexused, 0
je short _lj_no_unwind
endif
mov esi, [ebx.saved_xregistration]
cmp esi, dword ptr fs:__except_list
je short _lj_local_unwind
push esi
call __global_unwind2
add esp,4
_lj_local_unwind:
cmp esi, 0
je short _lj_no_unwind
; Check if called with old or new format jmp_buf. Look for the
; version cookie that's only present in the new format.
lea eax, [ebx.version_cookie]
push eax
call __rt_probe_read4@4
or eax, eax
jz short _lj_old_unwind
mov eax, [ebx.version_cookie]
cmp eax, JMPBUF_COOKIE
jnz short _lj_old_unwind
; Called with a new-format jmp_buf. Call unwind function supplied
; to the jmp_buf at setjmp time.
mov eax, [ebx.unwind_func]
or eax, eax
jz short _lj_no_unwind ;no local unwind necessary
push ebx
call eax
jmp short _lj_no_unwind
; Called with an old-format jmp_buf. Duplicate old longjmp behavior,
; assuming there's a C8.0 SEH node at top.
_lj_old_unwind:
mov eax, [ebx.saved_trylevel]
push eax
push esi
call __local_unwind2
add esp, 8
_lj_no_unwind:
mov edx, ebx
mov ebx, [edx.saved_ebx] ;recover registers...
mov edi, [edx.saved_edi]
mov esi, [edx.saved_esi]
mov eax, [esp+8] ;load the return value
cmp eax, 1 ;make sure it's not 0
adc eax, 0
mov esp, [edx.saved_esp] ;here, sp gets scorched
add esp, 4 ;punt the (old) return address
jmp [edx.saved_return] ;return
cEnd
EndCODE
END
|