- Timestamp:
- Jul 5, 2011, 7:52:42 PM (14 years ago)
- Location:
- trunk/src/kernel32
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kernel32/exceptions.cpp
r21647 r21662 462 462 { 463 463 PWINEXCEPTION_FRAME frame, prevFrame, dispatch; 464 WINEXCEPTION_RECORD record , newrec;464 WINEXCEPTION_RECORD record; //, newrec; 465 465 WINCONTEXT context; 466 466 DWORD rc; … … 471 471 if (!winteb) 472 472 { 473 /* We're being called from __seh_handler called upon unwinding the OS/2 474 * exception chain after the Win32 TIB structure is destroyed. This for 475 * example happens when we terminate the thread or the process from within 476 * the __try block. Just ignore this call retur (note that the Win32 477 * exception chain should be already unwound by this moment). */ 478 dprintf(("KERNEL32: RtlUnwind returning due to zero Win32 TEB.\n")); 473 dprintf(("KERNEL32: RtlUnwind TEB is NULL\n")); 474 DebugInt3(); 479 475 return 0; 480 476 } … … 526 522 if (pEndFrame && (frame > pEndFrame)) 527 523 { 524 #if 0 525 // TODO 528 526 newrec.ExceptionCode = STATUS_INVALID_UNWIND_TARGET; 529 527 newrec.ExceptionFlags = EH_NONCONTINUABLE; 530 528 newrec.ExceptionRecord = pRecord; 531 529 newrec.NumberParameters = 0; 530 RtlRaiseException(&newrec, NULL); 531 #else 532 532 dprintf(("KERNEL32: RtlUnwind terminating thread (invalid target).\n")); 533 533 DosExit(EXIT_THREAD, 0); 534 #endif 534 535 } 535 536 if (((void*)frame < winteb->stack_low) || … … 537 538 (int)frame & 3) 538 539 { 540 #if 0 541 // TODO 539 542 newrec.ExceptionCode = STATUS_BAD_STACK; 540 543 newrec.ExceptionFlags = EH_NONCONTINUABLE; 541 544 newrec.ExceptionRecord = pRecord; 542 545 newrec.NumberParameters = 0; 546 #else 543 547 dprintf(("KERNEL32: RtlUnwind terminating thread (bad stack).\n")); 544 548 DosExit(EXIT_THREAD, 0); 549 #endif 545 550 } 546 551 … … 548 553 dprintf(("KERNEL32: RtlUnwind - calling exception handler %08X", frame->Handler)); 549 554 if(frame->Handler) { 555 // ensure the Win32 FS (may be accessed directly in the handler) 556 DWORD oldsel = SetReturnFS(winteb->teb_sel); 550 557 rc = EXC_CallHandler(pRecord, frame, &context, &dispatch, frame->Handler, EXC_UnwindHandler ); 558 // restore FS 559 SetFS(oldsel); 551 560 } 552 561 else { … … 563 572 break; 564 573 default: 574 #if 0 575 // TODO 565 576 newrec.ExceptionCode = STATUS_INVALID_DISPOSITION; 566 577 newrec.ExceptionFlags = EH_NONCONTINUABLE; 567 578 newrec.ExceptionRecord = pRecord; 568 579 newrec.NumberParameters = 0; 569 dprintf(("KERNEL32: RtlUnwind terminating thread.\n")); 580 #else 581 dprintf(("KERNEL32: RtlUnwind terminating thread (invalid disposition).\n")); 570 582 DosExit(EXIT_THREAD, 0); 583 #endif 571 584 break; 572 585 } 573 586 dprintf(("KERNEL32: RtlUnwind (before)- frame=%08X, frame->Prev=%08X", frame, prevFrame)); 574 SetExceptionChain((DWORD)prevFrame);587 winteb->except = (void*)prevFrame; 575 588 frame = prevFrame; 576 589 dprintf(("KERNEL32: RtlUnwind (after) - frame=%08X, frame->Prev=%08X", frame, … … 1209 1222 #endif 1210 1223 1224 // borrowed from ntddk.h 1225 extern "C" 1226 void WIN32API RtlUnwind( 1227 LPVOID, 1228 LPVOID, 1229 LPVOID,DWORD); 1230 1211 1231 // Assembly wrapper for clearing the direction flag before calling our real 1212 1232 // exception handler … … 1234 1254 // sprintfException(pERepRec, pERegRec, pCtxRec, p, szTrapDump); 1235 1255 // } 1256 1257 // We have to disable unwinding of the Win32 exception handlers because 1258 // experiments have shown that when running under SMP kernel the stack 1259 // becomes corrupt at the time when unwinding takes place: attempts to 1260 // to follow the exception chain crash when accessing one of the the 1261 // previous frame. Although it may seem that performing unwinding here 1262 // (when we are definitely above any Win32 exception frames installed by 1263 // the application so that the OS could theoretically already discard lower 1264 // stack areas) is wrong, it's not the case of the crash. First, doing the 1265 // very same thing from the SEH handler (see comments in sehutil.s), i.e. 1266 // when the given Win32 stack frame (and all previous ones) is definitely 1267 // alive, crahes due to the same stack corruption too. Second, when running 1268 // under UNI kernel, BOTH approaches don't crash (i.e. the stack is fine). 1269 // This looks like the SMP kernel doesn't manage the stack right during 1270 // exception handling :( See also http://svn.netlabs.org/odin32/ticket/37. 1271 // 1272 // Note that disabling unwinding also breaks support for performing 1273 // setjmp()/lonjmp() that crosses the bounds of the __try {} block. 1274 #if 0 1275 if (pERepRec->fHandlerFlags & EH_UNWINDING) 1276 { 1277 // unwind the appropriate portion of the Win32 exception chain 1278 if (pERepRec->fHandlerFlags & EH_EXIT_UNWIND) 1279 { 1280 dprintf(("KERNEL32: OS2ExceptionHandler: EH_EXIT_UNWIND, " 1281 "unwinding all the Win32 exception chain")); 1282 RtlUnwind(NULL, 0, 0, 0); 1283 } 1284 else 1285 { 1286 dprintf(("KERNEL32: OS2ExceptionHandler: EH_UNWINDING, " 1287 "unwinding the Win32 exception chain up to 0x%p", pERegRec)); 1288 1289 // find a Win32 exception frame closest to the OS/2 one (pERegRec) 1290 // and unwind up to the previous one (to unwind the closest frame 1291 // itself too as we are definitely jumping out of it) 1292 TEB *winteb = GetThreadTEB(); 1293 PWINEXCEPTION_FRAME frame = (PWINEXCEPTION_FRAME)winteb->except; 1294 while (frame != NULL && ((ULONG)frame)!= 0xFFFFFFFF && 1295 ((ULONG)frame) <= ((ULONG)pERegRec)) 1296 frame = __seh_get_prev_frame(frame); 1297 if (((ULONG)frame) == 0xFFFFFFFF) 1298 frame = NULL; 1299 1300 RtlUnwind(frame, 0, 0, 0); 1301 } 1302 goto continuesearch; 1303 } 1304 #endif 1236 1305 1237 1306 /* Access violation at a known location */ … … 1517 1586 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == TRUE) 1518 1587 { 1588 dprintf(("KERNEL32: OS2ExceptionHandler: fix and continue\n")); 1519 1589 goto continueexecution; 1520 1590 } 1521 1591 else 1522 1592 { 1593 dprintf(("KERNEL32: OS2ExceptionHandler: continue search\n")); 1523 1594 goto continuesearch; 1524 1595 } -
trunk/src/kernel32/seh/sehutil.s
r21645 r21662 49 49 jne ___seh_handler_Win32 /* No, assume the Win32 chain */ 50 50 51 /* Note: Unwinding is disabled here since a) it is more correct to do 52 * centralized unwinding from OS2ExceptionHandler2ndLevel() (i.e. not only 53 * for SEH frames) and b) it crashes under SMP kernel due to stack being 54 * corrupt by the time when unwinding happens. See comments in 55 * OS2ExceptionHandler2ndLevel() for more details. */ 56 57 #if 0 58 51 59 movl 8(%ebp), %eax 52 60 movl 4(%eax), %eax /* fHandlerFlags */ … … 64 72 ___seh_handler_OS2_Unwind: 65 73 74 /* unwind the Win32 chain including our frame as someone's definitely 75 * jumping outside it if we're being unwound by OS/2 */ 76 movl 12(%ebp), %eax 77 cmpl $0, 64(%eax) /* Win32FS == 0? */ 78 je ___seh_handler_OS2_Unwind_End /* Yes, we already unwound this frame */ 79 66 80 /* restore the Win32 chain in our frame */ 67 movl 12(%ebp), %eax68 81 movl 60(%eax), %ebx /* pPrevFrameWin32 */ 69 82 movl %ebx, 0(%eax) /* pPrev */ 70 83 71 /* unwind the Win32 chain including our frame as someone's definitely72 * jumping outside it if we're being unwound */73 84 pushl %fs 74 85 … … 89 100 movl %ecx, 0(%eax) /* pPrev */ 90 101 102 ___seh_handler_OS2_Unwind_End: 103 91 104 xor %eax, %eax /* return code is irrelevant for EH_UNWINDING */ 92 105 jmp ___seh_handler_Return 106 107 #else 108 109 /* restore the OS/2 chain in our frame */ 110 movl 12(%ebp), %eax 111 movl 44(%eax), %ecx /* pPrevFrameOS2 */ 112 movl %ecx, 0(%eax) /* pPrev */ 113 114 xorl %eax, %eax /* return XCPT_CONTINUE_SEARCH (0) */ 115 jmp ___seh_handler_Return 116 117 #endif 93 118 94 119 ___seh_handler_Win32: … … 101 126 /* skip EH_UNWINDING calls (for compatibility with MSVC) */ 102 127 movl 8(%ebp), %ebx 103 movl 4(%ebx), %eax /* pRec->ExceptionFlags */ 104 testl $0x2, %eax /* EH_UNWINDING? */ 128 movl 4(%ebx), %eax /* pRec->ExceptionFlags */ 129 testl $0x2, %eax /* EH_UNWINDING? */ 130 je ___seh_handler_Win32_NotUnwinding /* No, continue normally */ 131 132 /* See the comment above */ 133 #if 0 134 /* clear out the Win32FS field so that we will not attempt to unwind twice 135 * (first, as a result of forced unwind from ExitProcess/ExitThread/etc and 136 * then from the OS/2 EH_UNWINDING call of our handler) */ 137 movl 12(%ebp), %eax 138 movl $0, 64(%eax) /* Win32FS */ 139 #endif 140 105 141 movl $1, %eax /* ExceptionContinueSearch */ 106 jne ___seh_handler_Return 142 jmp ___seh_handler_Return 143 144 ___seh_handler_Win32_NotUnwinding: 107 145 108 146 /* save handler's context */
Note:
See TracChangeset
for help on using the changeset viewer.