Mercurial > projects > ldc
comparison druntime/src/compiler/ldc/deh.c @ 1458:e0b2d67cfe7c
Added druntime (this should be removed once it works).
author | Robert Clipsham <robert@octarineparrot.com> |
---|---|
date | Tue, 02 Jun 2009 17:43:06 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
1456:7b218ec1044f | 1458:e0b2d67cfe7c |
---|---|
1 /** | |
2 * Implementation of exception handling support routines for Windows. | |
3 * | |
4 * Copyright: Copyright Digital Mars 1999 - 2009. | |
5 * License: <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>. | |
6 * Authors: Walter Bright | |
7 * | |
8 * Copyright Digital Mars 1999 - 2009. | |
9 * Distributed under the Boost Software License, Version 1.0. | |
10 * (See accompanying file LICENSE_1_0.txt or copy at | |
11 * http://www.boost.org/LICENSE_1_0.txt) | |
12 */ | |
13 #include <stdio.h> | |
14 #include <string.h> | |
15 #include <assert.h> | |
16 #include <stdlib.h> | |
17 | |
18 /* ======================== Win32 =============================== */ | |
19 | |
20 #if _WIN32 | |
21 | |
22 #include <excpt.h> | |
23 #include <windows.h> | |
24 | |
25 //#include "\sc\src\include\ehsup.h" | |
26 | |
27 /*** From Digital Mars C runtime library ***/ | |
28 EXCEPTION_DISPOSITION __cdecl _local_except_handler (EXCEPTION_RECORD *ExceptionRecord, | |
29 void* EstablisherFrame, | |
30 void *ContextRecord, | |
31 void *DispatcherContext | |
32 ); | |
33 void __cdecl _global_unwind(void *frame,EXCEPTION_RECORD *eRecord); | |
34 #define EXCEPTION_UNWIND 6 // Flag to indicate if the system is unwinding | |
35 | |
36 extern DWORD _except_list; | |
37 /*** ***/ | |
38 | |
39 #include "mars.h" | |
40 | |
41 extern ClassInfo D6object9Throwable7__ClassZ; | |
42 #define _Class_9Throwable D6object9Throwable7__ClassZ; | |
43 | |
44 extern ClassInfo D6object5Error7__ClassZ; | |
45 #define _Class_5Error D6object5Error7__ClassZ | |
46 | |
47 typedef int (__pascal *fp_t)(); // function pointer in ambient memory model | |
48 | |
49 // The layout of DEstablisherFrame is the same for C++ | |
50 | |
51 struct DEstablisherFrame | |
52 { | |
53 void *prev; // pointer to previous exception list | |
54 void *handler; // pointer to routine for exception handler | |
55 DWORD table_index; // current index into handler_info[] | |
56 DWORD ebp; // this is EBP of routine | |
57 }; | |
58 | |
59 struct DHandlerInfo | |
60 { | |
61 int prev_index; // previous table index | |
62 unsigned cioffset; // offset to DCatchInfo data from start of table (!=0 if try-catch) | |
63 void *finally_code; // pointer to finally code to execute | |
64 // (!=0 if try-finally) | |
65 }; | |
66 | |
67 // Address of DHandlerTable is passed in EAX to _d_framehandler() | |
68 | |
69 struct DHandlerTable | |
70 { | |
71 void *fptr; // pointer to start of function | |
72 unsigned espoffset; // offset of ESP from EBP | |
73 unsigned retoffset; // offset from start of function to return code | |
74 struct DHandlerInfo handler_info[1]; | |
75 }; | |
76 | |
77 struct DCatchBlock | |
78 { | |
79 ClassInfo *type; // catch type | |
80 unsigned bpoffset; // EBP offset of catch var | |
81 void *code; // catch handler code | |
82 }; | |
83 | |
84 // Create one of these for each try-catch | |
85 struct DCatchInfo | |
86 { | |
87 unsigned ncatches; // number of catch blocks | |
88 struct DCatchBlock catch_block[1]; // data for each catch block | |
89 }; | |
90 | |
91 // Macro to make our own exception code | |
92 #define MAKE_EXCEPTION_CODE(severity, facility, exception) \ | |
93 (((severity) << 30) | (1 << 29) | (0 << 28) | ((facility) << 16) | (exception)) | |
94 | |
95 #define STATUS_DIGITAL_MARS_D_EXCEPTION MAKE_EXCEPTION_CODE(3,'D',1) | |
96 | |
97 Object *_d_translate_se_to_d_exception(EXCEPTION_RECORD *exception_record); | |
98 void __cdecl _d_local_unwind(struct DHandlerTable *handler_table, struct DEstablisherFrame *frame, int stop_index); | |
99 | |
100 | |
101 /*********************************** | |
102 * The frame handler, this is called for each frame that has been registered | |
103 * in the OS except_list. | |
104 * Input: | |
105 * EAX the handler table for the frame | |
106 */ | |
107 | |
108 EXCEPTION_DISPOSITION _d_framehandler( | |
109 EXCEPTION_RECORD *exception_record, | |
110 struct DEstablisherFrame *frame, | |
111 CONTEXT context, | |
112 void *dispatcher_context) | |
113 { | |
114 struct DHandlerTable *handler_table; | |
115 | |
116 __asm { mov handler_table,EAX } | |
117 | |
118 if (exception_record->ExceptionFlags & EXCEPTION_UNWIND) | |
119 { | |
120 // Call all the finally blocks in this frame | |
121 _d_local_unwind(handler_table, frame, -1); | |
122 } | |
123 else | |
124 { | |
125 // Jump to catch block if matching one is found | |
126 | |
127 int ndx,prev_ndx,i; | |
128 struct DHandlerInfo *phi; | |
129 struct DCatchInfo *pci; | |
130 struct DCatchBlock *pcb; | |
131 unsigned ncatches; // number of catches in the current handler | |
132 Object *pti; | |
133 ClassInfo *ci; | |
134 | |
135 ci = NULL; // only compute it if we need it | |
136 | |
137 // walk through handler table, checking each handler | |
138 // with an index smaller than the current table_index | |
139 for (ndx = frame->table_index; ndx != -1; ndx = prev_ndx) | |
140 { | |
141 phi = &handler_table->handler_info[ndx]; | |
142 prev_ndx = phi->prev_index; | |
143 if (phi->cioffset) | |
144 { | |
145 // this is a catch handler (no finally) | |
146 pci = (struct DCatchInfo *)((char *)handler_table + phi->cioffset); | |
147 ncatches = pci->ncatches; | |
148 for (i = 0; i < ncatches; i++) | |
149 { | |
150 pcb = &pci->catch_block[i]; | |
151 | |
152 if (!ci) | |
153 { | |
154 // This code must match the translation code | |
155 if (exception_record->ExceptionCode == STATUS_DIGITAL_MARS_D_EXCEPTION) | |
156 { | |
157 //printf("ei[0] = %p\n", exception_record->ExceptionInformation[0]); | |
158 ci = **(ClassInfo ***)(exception_record->ExceptionInformation[0]); | |
159 } | |
160 else | |
161 ci = &_Class_9Throwable; | |
162 } | |
163 | |
164 if (_d_isbaseof(ci, pcb->type)) | |
165 { | |
166 // Matched the catch type, so we've found the handler. | |
167 int regebp; | |
168 | |
169 pti = _d_translate_se_to_d_exception(exception_record); | |
170 | |
171 // Initialize catch variable | |
172 regebp = (int)&frame->ebp; // EBP for this frame | |
173 *(void **)(regebp + (pcb->bpoffset)) = pti; | |
174 | |
175 // Have system call all finally blocks in intervening frames | |
176 _global_unwind(frame, exception_record); | |
177 | |
178 // Call all the finally blocks skipped in this frame | |
179 _d_local_unwind(handler_table, frame, ndx); | |
180 | |
181 frame->table_index = prev_ndx; // we are out of this handler | |
182 | |
183 // Jump to catch block. Does not return. | |
184 { | |
185 unsigned catch_esp; | |
186 fp_t catch_addr; | |
187 | |
188 catch_addr = (fp_t)(pcb->code); | |
189 catch_esp = regebp - handler_table->espoffset - sizeof(fp_t); | |
190 _asm | |
191 { | |
192 mov EAX,catch_esp | |
193 mov ECX,catch_addr | |
194 mov [EAX],ECX | |
195 mov EBP,regebp | |
196 mov ESP,EAX // reset stack | |
197 ret // jump to catch block | |
198 } | |
199 } | |
200 } | |
201 } | |
202 } | |
203 } | |
204 } | |
205 return ExceptionContinueSearch; | |
206 } | |
207 | |
208 /*********************************** | |
209 * Exception filter for use in __try..__except block | |
210 * surrounding call to Dmain() | |
211 */ | |
212 | |
213 int _d_exception_filter(struct _EXCEPTION_POINTERS *eptrs, | |
214 int retval, | |
215 Object **exception_object) | |
216 { | |
217 *exception_object = _d_translate_se_to_d_exception(eptrs->ExceptionRecord); | |
218 return retval; | |
219 } | |
220 | |
221 /*********************************** | |
222 * Throw a D object. | |
223 */ | |
224 | |
225 void __stdcall _d_throw(Object *h) | |
226 { | |
227 //printf("_d_throw(h = %p, &h = %p)\n", h, &h); | |
228 //printf("\tvptr = %p\n", *(void **)h); | |
229 RaiseException(STATUS_DIGITAL_MARS_D_EXCEPTION, | |
230 EXCEPTION_NONCONTINUABLE, | |
231 1, (DWORD *)&h); | |
232 } | |
233 | |
234 /*********************************** | |
235 * Create an exception object | |
236 */ | |
237 | |
238 Object *_d_create_exception_object(ClassInfo *ci, char *msg) | |
239 { | |
240 Throwable *exc; | |
241 | |
242 exc = (Throwable *)_d_newclass(ci); | |
243 // BUG: what if _d_newclass() throws an out of memory exception? | |
244 | |
245 if (msg) | |
246 { | |
247 exc->msglen = strlen(msg); | |
248 exc->msg = msg; | |
249 } | |
250 return (Object *)exc; | |
251 } | |
252 | |
253 /*********************************** | |
254 * Converts a Windows Structured Exception code to a D Exception Object. | |
255 */ | |
256 | |
257 Object *_d_translate_se_to_d_exception(EXCEPTION_RECORD *exception_record) | |
258 { | |
259 Object *pti; | |
260 | |
261 switch (exception_record->ExceptionCode) { | |
262 case STATUS_DIGITAL_MARS_D_EXCEPTION: | |
263 // Generated D exception | |
264 pti = (Object *)(exception_record->ExceptionInformation[0]); | |
265 break; | |
266 | |
267 case STATUS_INTEGER_DIVIDE_BY_ZERO: | |
268 pti = _d_create_exception_object(&_Class_5Error, "Integer Divide by Zero"); | |
269 break; | |
270 | |
271 case STATUS_FLOAT_DIVIDE_BY_ZERO: | |
272 pti = _d_create_exception_object(&_Class_5Error, "Float Divide by Zero"); | |
273 break; | |
274 | |
275 case STATUS_ACCESS_VIOLATION: | |
276 pti = _d_create_exception_object(&_Class_5Error, "Access Violation"); | |
277 break; | |
278 | |
279 case STATUS_STACK_OVERFLOW: | |
280 pti = _d_create_exception_object(&_Class_5Error, "Stack Overflow"); | |
281 break; | |
282 | |
283 case STATUS_DATATYPE_MISALIGNMENT: | |
284 pti = _d_create_exception_object(&_Class_5Error, "Datatype Misalignment"); | |
285 break; | |
286 | |
287 case STATUS_ARRAY_BOUNDS_EXCEEDED: | |
288 pti = _d_create_exception_object(&_Class_5Error, "Array Bounds Exceeded"); | |
289 break; | |
290 | |
291 case STATUS_FLOAT_INVALID_OPERATION: | |
292 pti = _d_create_exception_object(&_Class_5Error, "Invalid Floating Point Operation"); | |
293 break; | |
294 | |
295 case STATUS_FLOAT_DENORMAL_OPERAND: | |
296 pti = _d_create_exception_object(&_Class_5Error, "Floating Point Denormal Operand"); | |
297 break; | |
298 | |
299 case STATUS_FLOAT_INEXACT_RESULT: | |
300 pti = _d_create_exception_object(&_Class_5Error, "Floating Point Inexact Result"); | |
301 break; | |
302 | |
303 case STATUS_FLOAT_OVERFLOW: | |
304 pti = _d_create_exception_object(&_Class_5Error, "Floating Point Overflow"); | |
305 break; | |
306 | |
307 case STATUS_FLOAT_UNDERFLOW: | |
308 pti = _d_create_exception_object(&_Class_5Error, "Floating Point Underflow"); | |
309 break; | |
310 | |
311 case STATUS_FLOAT_STACK_CHECK: | |
312 pti = _d_create_exception_object(&_Class_5Error, "Floating Point Stack Check"); | |
313 break; | |
314 | |
315 case STATUS_PRIVILEGED_INSTRUCTION: | |
316 pti = _d_create_exception_object(&_Class_5Error, "Privileged Instruction"); | |
317 break; | |
318 | |
319 case STATUS_ILLEGAL_INSTRUCTION: | |
320 pti = _d_create_exception_object(&_Class_5Error, "Illegal Instruction"); | |
321 break; | |
322 | |
323 case STATUS_BREAKPOINT: | |
324 pti = _d_create_exception_object(&_Class_5Error, "Breakpoint"); | |
325 break; | |
326 | |
327 case STATUS_IN_PAGE_ERROR: | |
328 pti = _d_create_exception_object(&_Class_5Error, "Win32 In Page Exception"); | |
329 break; | |
330 /* | |
331 case STATUS_INTEGER_OVERFLOW: // not supported on any x86 processor | |
332 case STATUS_INVALID_DISPOSITION: | |
333 case STATUS_NONCONTINUABLE_EXCEPTION: | |
334 case STATUS_SINGLE_STEP: | |
335 case DBG_CONTROL_C: // only when a debugger is attached | |
336 // In DMC, but not in Microsoft docs | |
337 case STATUS_GUARD_PAGE_VIOLATION: | |
338 case STATUS_INVALID_HANDLE: | |
339 */ | |
340 // convert all other exception codes into a Win32Exception | |
341 default: | |
342 pti = _d_create_exception_object(&_Class_5Error, "Win32 Exception"); | |
343 break; | |
344 } | |
345 | |
346 return pti; | |
347 } | |
348 | |
349 /************************************** | |
350 * Call finally blocks in the current stack frame until stop_index. | |
351 * This is roughly equivalent to _local_unwind() for C in \src\win32\ehsup.c | |
352 */ | |
353 | |
354 void __cdecl _d_local_unwind(struct DHandlerTable *handler_table, | |
355 struct DEstablisherFrame *frame, int stop_index) | |
356 { | |
357 struct DHandlerInfo *phi; | |
358 struct DCatchInfo *pci; | |
359 int i; | |
360 | |
361 // Set up a special exception handler to catch double-fault exceptions. | |
362 __asm | |
363 { | |
364 push dword ptr -1 | |
365 push dword ptr 0 | |
366 push offset _local_except_handler // defined in src\win32\ehsup.c | |
367 push dword ptr fs:_except_list | |
368 mov FS:_except_list,ESP | |
369 } | |
370 | |
371 for (i = frame->table_index; i != -1 && i != stop_index; i = phi->prev_index) | |
372 { | |
373 phi = &handler_table->handler_info[i]; | |
374 if (phi->finally_code) | |
375 { | |
376 // Note that it is unnecessary to adjust the ESP, as the finally block | |
377 // accesses all items on the stack as relative to EBP. | |
378 | |
379 DWORD *catch_ebp = &frame->ebp; | |
380 void *blockaddr = phi->finally_code; | |
381 | |
382 _asm | |
383 { | |
384 push EBX | |
385 mov EBX,blockaddr | |
386 push EBP | |
387 mov EBP,catch_ebp | |
388 call EBX | |
389 pop EBP | |
390 pop EBX | |
391 } | |
392 } | |
393 } | |
394 | |
395 _asm | |
396 { | |
397 pop FS:_except_list | |
398 add ESP,12 | |
399 } | |
400 } | |
401 | |
402 /*********************************** | |
403 * external version of the unwinder | |
404 */ | |
405 | |
406 __declspec(naked) void __cdecl _d_local_unwind2() | |
407 { | |
408 __asm | |
409 { | |
410 jmp _d_local_unwind | |
411 } | |
412 } | |
413 | |
414 /*********************************** | |
415 * The frame handler, this is called for each frame that has been registered | |
416 * in the OS except_list. | |
417 * Input: | |
418 * EAX the handler table for the frame | |
419 */ | |
420 | |
421 EXCEPTION_DISPOSITION _d_monitor_handler( | |
422 EXCEPTION_RECORD *exception_record, | |
423 struct DEstablisherFrame *frame, | |
424 CONTEXT context, | |
425 void *dispatcher_context) | |
426 { | |
427 if (exception_record->ExceptionFlags & EXCEPTION_UNWIND) | |
428 { | |
429 _d_monitorexit((Object *)frame->table_index); | |
430 } | |
431 else | |
432 { | |
433 } | |
434 return ExceptionContinueSearch; | |
435 } | |
436 | |
437 /*********************************** | |
438 */ | |
439 | |
440 void _d_monitor_prolog(void *x, void *y, Object *h) | |
441 { | |
442 __asm | |
443 { | |
444 push EAX | |
445 } | |
446 //printf("_d_monitor_prolog(x=%p, y=%p, h=%p)\n", x, y, h); | |
447 _d_monitorenter(h); | |
448 __asm | |
449 { | |
450 pop EAX | |
451 } | |
452 } | |
453 | |
454 /*********************************** | |
455 */ | |
456 | |
457 void _d_monitor_epilog(void *x, void *y, Object *h) | |
458 { | |
459 //printf("_d_monitor_epilog(x=%p, y=%p, h=%p)\n", x, y, h); | |
460 __asm | |
461 { | |
462 push EAX | |
463 push EDX | |
464 } | |
465 _d_monitorexit(h); | |
466 __asm | |
467 { | |
468 pop EDX | |
469 pop EAX | |
470 } | |
471 } | |
472 | |
473 #endif | |
474 | |
475 /* ======================== linux =============================== */ | |
476 | |
477 #if linux | |
478 | |
479 #include "mars.h" | |
480 | |
481 extern ClassInfo D6object9Throwable7__ClassZ; | |
482 #define _Class_9Throwable D6object9Throwable7__ClassZ; | |
483 | |
484 extern ClassInfo D6object5Error7__ClassZ; | |
485 #define _Class_5Error D6object5Error7__ClassZ | |
486 | |
487 typedef int (*fp_t)(); // function pointer in ambient memory model | |
488 | |
489 struct DHandlerInfo | |
490 { | |
491 unsigned offset; // offset from function address to start of guarded section | |
492 int prev_index; // previous table index | |
493 unsigned cioffset; // offset to DCatchInfo data from start of table (!=0 if try-catch) | |
494 void *finally_code; // pointer to finally code to execute | |
495 // (!=0 if try-finally) | |
496 }; | |
497 | |
498 // Address of DHandlerTable, searched for by eh_finddata() | |
499 | |
500 struct DHandlerTable | |
501 { | |
502 void *fptr; // pointer to start of function | |
503 unsigned espoffset; // offset of ESP from EBP | |
504 unsigned retoffset; // offset from start of function to return code | |
505 unsigned nhandlers; // dimension of handler_info[] | |
506 struct DHandlerInfo handler_info[1]; | |
507 }; | |
508 | |
509 struct DCatchBlock | |
510 { | |
511 ClassInfo *type; // catch type | |
512 unsigned bpoffset; // EBP offset of catch var | |
513 void *code; // catch handler code | |
514 }; | |
515 | |
516 // Create one of these for each try-catch | |
517 struct DCatchInfo | |
518 { | |
519 unsigned ncatches; // number of catch blocks | |
520 struct DCatchBlock catch_block[1]; // data for each catch block | |
521 }; | |
522 | |
523 // One of these is generated for each function with try-catch or try-finally | |
524 | |
525 struct FuncTable | |
526 { | |
527 void *fptr; // pointer to start of function | |
528 struct DHandlerTable *handlertable; // eh data for this function | |
529 unsigned size; // size of function in bytes | |
530 }; | |
531 | |
532 extern struct FuncTable *table_start; | |
533 extern struct FuncTable *table_end; | |
534 | |
535 void terminate() | |
536 { | |
537 // _asm | |
538 // { | |
539 // hlt | |
540 // } | |
541 } | |
542 | |
543 /******************************************* | |
544 * Given address that is inside a function, | |
545 * figure out which function it is in. | |
546 * Return DHandlerTable if there is one, NULL if not. | |
547 */ | |
548 | |
549 struct DHandlerTable *__eh_finddata(void *address) | |
550 { | |
551 struct FuncTable *ft; | |
552 | |
553 for (ft = (struct FuncTable *)table_start; | |
554 ft < (struct FuncTable *)table_end; | |
555 ft++) | |
556 { | |
557 if (ft->fptr <= address && | |
558 address < (void *)((char *)ft->fptr + ft->size)) | |
559 { | |
560 return ft->handlertable; | |
561 } | |
562 } | |
563 return NULL; | |
564 } | |
565 | |
566 | |
567 /****************************** | |
568 * Given EBP, find return address to caller, and caller's EBP. | |
569 * Input: | |
570 * regbp Value of EBP for current function | |
571 * *pretaddr Return address | |
572 * Output: | |
573 * *pretaddr return address to caller | |
574 * Returns: | |
575 * caller's EBP | |
576 */ | |
577 | |
578 unsigned __eh_find_caller(unsigned regbp, unsigned *pretaddr) | |
579 { | |
580 unsigned bp = *(unsigned *)regbp; | |
581 | |
582 if (bp) // if not end of call chain | |
583 { | |
584 // Perform sanity checks on new EBP. | |
585 // If it is screwed up, terminate() hopefully before we do more damage. | |
586 if (bp <= regbp) | |
587 // stack should grow to smaller values | |
588 terminate(); | |
589 | |
590 *pretaddr = *(unsigned *)(regbp + sizeof(int)); | |
591 } | |
592 return bp; | |
593 } | |
594 | |
595 /*********************************** | |
596 * Throw a D object. | |
597 */ | |
598 | |
599 void __stdcall _d_throw(Object *h) | |
600 { | |
601 unsigned regebp; | |
602 | |
603 //printf("_d_throw(h = %p, &h = %p)\n", h, &h); | |
604 //printf("\tvptr = %p\n", *(void **)h); | |
605 | |
606 regebp = _EBP; | |
607 | |
608 while (1) // for each function on the stack | |
609 { | |
610 struct DHandlerTable *handler_table; | |
611 struct FuncTable *pfunc; | |
612 struct DHandlerInfo *phi; | |
613 unsigned retaddr; | |
614 unsigned funcoffset; | |
615 unsigned spoff; | |
616 unsigned retoffset; | |
617 int index; | |
618 int dim; | |
619 int ndx; | |
620 int prev_ndx; | |
621 | |
622 regebp = __eh_find_caller(regebp,&retaddr); | |
623 if (!regebp) | |
624 // if end of call chain | |
625 break; | |
626 | |
627 handler_table = __eh_finddata((void *)retaddr); // find static data associated with function | |
628 if (!handler_table) // if no static data | |
629 { | |
630 continue; | |
631 } | |
632 funcoffset = (unsigned)handler_table->fptr; | |
633 spoff = handler_table->espoffset; | |
634 retoffset = handler_table->retoffset; | |
635 | |
636 #ifdef DEBUG | |
637 printf("retaddr = x%x\n",(unsigned)retaddr); | |
638 printf("regebp=x%04x, funcoffset=x%04x, spoff=x%x, retoffset=x%x\n", | |
639 regebp,funcoffset,spoff,retoffset); | |
640 #endif | |
641 | |
642 // Find start index for retaddr in static data | |
643 dim = handler_table->nhandlers; | |
644 index = -1; | |
645 for (int i = 0; i < dim; i++) | |
646 { | |
647 phi = &handler_table->handler_info[i]; | |
648 | |
649 if ((unsigned)retaddr >= funcoffset + phi->offset) | |
650 index = i; | |
651 } | |
652 | |
653 // walk through handler table, checking each handler | |
654 // with an index smaller than the current table_index | |
655 for (ndx = index; ndx != -1; ndx = prev_ndx) | |
656 { | |
657 phi = &handler_table->handler_info[ndx]; | |
658 prev_ndx = phi->prev_index; | |
659 if (phi->cioffset) | |
660 { | |
661 // this is a catch handler (no finally) | |
662 struct DCatchInfo *pci; | |
663 int ncatches; | |
664 int i; | |
665 | |
666 pci = (struct DCatchInfo *)((char *)handler_table + phi->cioffset); | |
667 ncatches = pci->ncatches; | |
668 for (i = 0; i < ncatches; i++) | |
669 { | |
670 struct DCatchBlock *pcb; | |
671 ClassInfo *ci = **(ClassInfo ***)h; | |
672 | |
673 pcb = &pci->catch_block[i]; | |
674 | |
675 if (_d_isbaseof(ci, pcb->type)) | |
676 { // Matched the catch type, so we've found the handler. | |
677 | |
678 // Initialize catch variable | |
679 *(void **)(regebp + (pcb->bpoffset)) = h; | |
680 | |
681 // Jump to catch block. Does not return. | |
682 { | |
683 unsigned catch_esp; | |
684 fp_t catch_addr; | |
685 | |
686 catch_addr = (fp_t)(pcb->code); | |
687 catch_esp = regebp - handler_table->espoffset - sizeof(fp_t); | |
688 _asm | |
689 { | |
690 mov EAX,catch_esp | |
691 mov ECX,catch_addr | |
692 mov [EAX],ECX | |
693 mov EBP,regebp | |
694 mov ESP,EAX // reset stack | |
695 ret // jump to catch block | |
696 } | |
697 } | |
698 } | |
699 } | |
700 } | |
701 else if (phi->finally_code) | |
702 { // Call finally block | |
703 // Note that it is unnecessary to adjust the ESP, as the finally block | |
704 // accesses all items on the stack as relative to EBP. | |
705 | |
706 void *blockaddr = phi->finally_code; | |
707 | |
708 _asm | |
709 { | |
710 push EBX | |
711 mov EBX,blockaddr | |
712 push EBP | |
713 mov EBP,regebp | |
714 call EBX | |
715 pop EBP | |
716 pop EBX | |
717 } | |
718 } | |
719 } | |
720 } | |
721 } | |
722 | |
723 | |
724 #endif |