Qucs-S S-parameter Viewer & RF Synthesis Tools
Loading...
Searching...
No Matches
switch_x86_msvc.h
1/*
2 * this is the internal transfer function.
3 *
4 * HISTORY
5 * 24-Nov-02 Christian Tismer <tismer@tismer.com>
6 * needed to add another magic constant to insure
7 * that f in slp_eval_frame(PyFrameObject *f)
8 * STACK_REFPLUS will probably be 1 in most cases.
9 * gets included into the saved stack area.
10 * 26-Sep-02 Christian Tismer <tismer@tismer.com>
11 * again as a result of virtualized stack access,
12 * the compiler used less registers. Needed to
13 * explicit mention registers in order to get them saved.
14 * Thanks to Jeff Senn for pointing this out and help.
15 * 17-Sep-02 Christian Tismer <tismer@tismer.com>
16 * after virtualizing stack save/restore, the
17 * stack size shrunk a bit. Needed to introduce
18 * an adjustment STACK_MAGIC per platform.
19 * 15-Sep-02 Gerd Woetzel <gerd.woetzel@GMD.DE>
20 * slightly changed framework for sparc
21 * 01-Mar-02 Christian Tismer <tismer@tismer.com>
22 * Initial final version after lots of iterations for i386.
23 */
24
25#define alloca _alloca
26
27#define STACK_REFPLUS 1
28
29#ifdef SLP_EVAL
30
31#define STACK_MAGIC 0
32
33/* Some magic to quell warnings and keep slp_switch() from crashing when built
34 with VC90. Disable global optimizations, and the warning: frame pointer
35 register 'ebp' modified by inline assembly code.
36
37 We used to just disable global optimizations ("g") but upstream stackless
38 Python, as well as stackman, turn off all optimizations.
39
40References:
41https://github.com/stackless-dev/stackman/blob/dbc72fe5207a2055e658c819fdeab9731dee78b9/stackman/platforms/switch_x86_msvc.h
42https://github.com/stackless-dev/stackless/blob/main-slp/Stackless/platf/switch_x86_msvc.h
43*/
44#define WIN32_LEAN_AND_MEAN
45#include <windows.h>
46
47#pragma optimize("", off) /* so that autos are stored on the stack */
48#pragma warning(disable:4731)
49#pragma warning(disable:4733) /* disable warning about modifying FS[0] */
50
124#define GREENLET_NEEDS_EXCEPTION_STATE_SAVED
125
126
127typedef struct _GExceptionRegistration {
128 struct _GExceptionRegistration* prev;
129 void* handler_f;
130} GExceptionRegistration;
131
132static void
133slp_set_exception_state(const void *const seh_state)
134{
135 // Because the stack from from which we do this is ALSO a handler, and
136 // that one we want to keep, we need to relink the current SEH handler
137 // frame to point to this one, cutting out the middle men, as it were.
138 //
139 // Entering a try block doesn't change the SEH frame, but entering a
140 // function containing a try block does.
141 GExceptionRegistration* current_seh_state = (GExceptionRegistration*)__readfsdword(FIELD_OFFSET(NT_TIB, ExceptionList));
142 current_seh_state->prev = (GExceptionRegistration*)seh_state;
143}
144
145
146static GExceptionRegistration*
147x86_slp_get_third_oldest_handler()
148{
149 GExceptionRegistration* a = NULL; /* Closest to the top */
150 GExceptionRegistration* b = NULL; /* second */
151 GExceptionRegistration* c = NULL;
152 GExceptionRegistration* seh_state = (GExceptionRegistration*)__readfsdword(FIELD_OFFSET(NT_TIB, ExceptionList));
153 a = b = c = seh_state;
154
155 while (seh_state && seh_state != (GExceptionRegistration*)0xFFFFFFFF) {
156 if ((void*)seh_state->prev < (void*)100) {
157 fprintf(stderr, "\tERROR: Broken SEH chain.\n");
158 return NULL;
159 }
160 a = b;
161 b = c;
162 c = seh_state;
163
164 seh_state = seh_state->prev;
165 }
166 return a ? a : (b ? b : c);
167}
168
169
170static void*
171slp_get_exception_state()
172{
173 // XXX: There appear to be three SEH handlers on the stack already at the
174 // start of the thread. Is that a guarantee? Almost certainly not. Yet in
175 // all observed cases it has been three. This is consistent with
176 // faulthandler off or on, and optimizations off or on. It may not be
177 // consistent with other operating system versions, though: we only have
178 // CI on one or two versions (don't ask what there are).
179 // In theory we could capture the number of handlers on the chain when
180 // PyInit__greenlet is called: there are probably only the default
181 // handlers at that point (unless we're embedded and people have used
182 // __try/__except or a C++ handler)?
183 return x86_slp_get_third_oldest_handler();
184}
185
186static int
187slp_switch(void)
188{
189 /* MASM syntax is typically reversed from other assemblers.
190 It is usually <instruction> <destination> <source>
191 */
192 int *stackref, stsizediff;
193 /* store the structured exception state for this stack */
194 DWORD seh_state = __readfsdword(FIELD_OFFSET(NT_TIB, ExceptionList));
195 __asm mov stackref, esp;
196 /* modify EBX, ESI and EDI in order to get them preserved */
197 __asm mov ebx, ebx;
198 __asm xchg esi, edi;
199 {
200 SLP_SAVE_STATE(stackref, stsizediff);
201 __asm {
202 mov eax, stsizediff
203 add esp, eax
204 add ebp, eax
205 }
206 SLP_RESTORE_STATE();
207 }
208 __writefsdword(FIELD_OFFSET(NT_TIB, ExceptionList), seh_state);
209 return 0;
210}
211
212/* re-enable ebp warning and global optimizations. */
213#pragma optimize("", on)
214#pragma warning(default:4731)
215#pragma warning(default:4733) /* disable warning about modifying FS[0] */
216
217
218#endif
219
220/*
221 * further self-processing support
222 */
223
224/* we have IsBadReadPtr available, so we can peek at objects */
225#define STACKLESS_SPY
226
227#ifdef GREENLET_DEBUG
228
229#define CANNOT_READ_MEM(p, bytes) IsBadReadPtr(p, bytes)
230
231static int IS_ON_STACK(void*p)
232{
233 int stackref;
234 int stackbase = ((int)&stackref) & 0xfffff000;
235 return (int)p >= stackbase && (int)p < stackbase + 0x00100000;
236}
237
238static void
239x86_slp_show_seh_chain()
240{
241 GExceptionRegistration* seh_state = (GExceptionRegistration*)__readfsdword(FIELD_OFFSET(NT_TIB, ExceptionList));
242 fprintf(stderr, "====== SEH Chain ======\n");
243 while (seh_state && seh_state != (GExceptionRegistration*)0xFFFFFFFF) {
244 fprintf(stderr, "\tSEH_chain addr: %p handler: %p prev: %p\n",
245 seh_state,
246 seh_state->handler_f, seh_state->prev);
247 if ((void*)seh_state->prev < (void*)100) {
248 fprintf(stderr, "\tERROR: Broken chain.\n");
249 break;
250 }
251 seh_state = seh_state->prev;
252 }
253 fprintf(stderr, "====== End SEH Chain ======\n");
254 fflush(NULL);
255 return;
256}
257
258//addVectoredExceptionHandler constants:
259//CALL_FIRST means call this exception handler first;
260//CALL_LAST means call this exception handler last
261#define CALL_FIRST 1
262#define CALL_LAST 0
263
264LONG WINAPI
265GreenletVectorHandler(PEXCEPTION_POINTERS ExceptionInfo)
266{
267 // We get one of these for every C++ exception, with code
268 // E06D7363
269 // This is a special value that means "C++ exception from MSVC"
270 // https://devblogs.microsoft.com/oldnewthing/20100730-00/?p=13273
271 //
272 // Install in the module init function with:
273 // AddVectoredExceptionHandler(CALL_FIRST, GreenletVectorHandler);
274 PEXCEPTION_RECORD ExceptionRecord = ExceptionInfo->ExceptionRecord;
275
276 fprintf(stderr,
277 "GOT VECTORED EXCEPTION:\n"
278 "\tExceptionCode : %p\n"
279 "\tExceptionFlags : %p\n"
280 "\tExceptionAddr : %p\n"
281 "\tNumberparams : %ld\n",
282 ExceptionRecord->ExceptionCode,
283 ExceptionRecord->ExceptionFlags,
284 ExceptionRecord->ExceptionAddress,
285 ExceptionRecord->NumberParameters
286 );
287 if (ExceptionRecord->ExceptionFlags & 1) {
288 fprintf(stderr, "\t\tEH_NONCONTINUABLE\n" );
289 }
290 if (ExceptionRecord->ExceptionFlags & 2) {
291 fprintf(stderr, "\t\tEH_UNWINDING\n" );
292 }
293 if (ExceptionRecord->ExceptionFlags & 4) {
294 fprintf(stderr, "\t\tEH_EXIT_UNWIND\n" );
295 }
296 if (ExceptionRecord->ExceptionFlags & 8) {
297 fprintf(stderr, "\t\tEH_STACK_INVALID\n" );
298 }
299 if (ExceptionRecord->ExceptionFlags & 0x10) {
300 fprintf(stderr, "\t\tEH_NESTED_CALL\n" );
301 }
302 if (ExceptionRecord->ExceptionFlags & 0x20) {
303 fprintf(stderr, "\t\tEH_TARGET_UNWIND\n" );
304 }
305 if (ExceptionRecord->ExceptionFlags & 0x40) {
306 fprintf(stderr, "\t\tEH_COLLIDED_UNWIND\n" );
307 }
308 fprintf(stderr, "\n");
309 fflush(NULL);
310 for(DWORD i = 0; i < ExceptionRecord->NumberParameters; i++) {
311 fprintf(stderr, "\t\t\tParam %ld: %lX\n", i, ExceptionRecord->ExceptionInformation[i]);
312 }
313
314 if (ExceptionRecord->NumberParameters == 3) {
315 fprintf(stderr, "\tAbout to traverse SEH chain\n");
316 // C++ Exception records have 3 params.
317 x86_slp_show_seh_chain();
318 }
319
320 return EXCEPTION_CONTINUE_SEARCH;
321}
322
323
324
325
326#endif