Changeset 21999 for trunk/src/kernel32/seh
- Timestamp:
- Apr 18, 2012, 10:46:37 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kernel32/seh/sehutil.s
r21916 r21999 8 8 9 9 .global ___seh_handler 10 .global ___seh_get_prev_frame 10 .global ___seh_handler_filter 11 .global ___seh_handler_win32 12 .global ___seh_get_prev_frame_win32 13 14 #define sizeof_WINEXCEPTION_RECORD 80 15 #define sizeof_WINCONTEXT 296 11 16 12 17 /* 13 18 * extern "C" 14 * int __seh_handler(PEXCEPTION _RECORD pRec,19 * int __seh_handler(PEXCEPTIONREPORTRECORD pRec, 15 20 * struct ___seh_EXCEPTION_FRAME *pFrame, 16 * PCONTEXT pContext, PVOID)17 * 18 * Win32 structuredexception handler that implements the __try/__except19 * functionality for GCC .21 * PCONTEXTRECORD pContext, PVOID) 22 * 23 * OS/2 exception handler that implements the __try/__except 24 * functionality for GCC in non-ODIN_FORCE_WIN32_TIB mode. 20 25 * 21 26 * NOTE: This is a heavily platform specific stuff. The code depends on the … … 26 31 * the stack. 27 32 */ 28 29 33 ___seh_handler: 30 34 31 pushl %ebp 32 movl %esp, %ebp 35 /* call the common handler to do the job */ 36 jmp OS2ExceptionHandler2ndLevel 37 38 /* 39 * extern "C" 40 * BOOL __seh_handler_filter(PEXCEPTIONREPORTRECORD pRec, 41 * struct ___seh_EXCEPTION_FRAME *pFrame, 42 * PCONTEXTRECORD pContext) 43 * 44 * Calls the filter expression of the __try/__except block 45 * in non-ODIN_FORCE_WIN32_TIB mode. 46 * 47 * Return TRUE if the filter asks to continue execution and FALSE 48 * otherwise. Note that if the filter chooses to execute the __except block, 49 * this function does not return. 50 * 51 * NOTE: This is a heavily platform specific stuff. The code depends on the 52 * struct ___seh_EXCEPTION_FRAME layout so be very careful and keep both 53 * in sync! 54 * 55 * __cdecl: EAX/ECX/EDX are not preserved, result in EAX/EDX, caller cleans up 56 * the stack. 57 */ 58 59 ___seh_handler_filter: 33 60 34 61 /* … … 36 63 * 12(%ebp) - pFrame 37 64 * 16(%ebp) - pContext 38 * 20(%ebp) - pVoid39 65 */ 66 67 pushl %ebp 68 movl %esp, %ebp 40 69 41 70 /* preserve used registers */ … … 44 73 pushl %esi 45 74 46 movl %fs, %eax47 andl $0x0000FFFF, %eax48 cmpl $Dos32TIB, %eax /* Running along the OS/2 chain? */49 jne ___seh_handler_Win32 /* No, assume the Win32 chain */50 51 /* Note: Unwinding is disabled here since a) it is more correct to do52 * centralized unwinding from OS2ExceptionHandler2ndLevel() (i.e. not only53 * for SEH frames) and b) it crashes under SMP kernel due to stack being54 * corrupt by the time when unwinding happens. See comments in55 * OS2ExceptionHandler2ndLevel() for more details. */56 57 #if 058 59 movl 8(%ebp), %eax60 movl 4(%eax), %eax /* fHandlerFlags */61 testl $0x02, %eax /* EH_UNWINDING? */62 jne ___seh_handler_OS2_Unwind63 64 /* restore the OS/2 chain in our frame */65 movl 12(%ebp), %eax66 movl 44(%eax), %ecx /* pPrevFrameOS2 */67 movl %ecx, 0(%eax) /* pPrev */68 69 xorl %eax, %eax /* return XCPT_CONTINUE_SEARCH (0) */70 jmp ___seh_handler_Return71 72 ___seh_handler_OS2_Unwind:73 74 /* unwind the Win32 chain including our frame as someone's definitely75 * jumping outside it if we're being unwound by OS/2 */76 movl 12(%ebp), %eax77 cmpl $0, 64(%eax) /* Win32FS == 0? */78 je ___seh_handler_OS2_Unwind_End /* Yes, we already unwound this frame */79 80 /* restore the Win32 chain in our frame */81 movl 60(%eax), %ebx /* pPrevFrameWin32 */82 movl %ebx, 0(%eax) /* pPrev */83 84 pushl %fs85 86 pushl 64(%eax) /* Win32FS */87 popl %fs88 89 pushl $0 /* DWORD (unused) */90 pushl $0 /* PEXCEPTION_RECORD */91 pushl $0 /* LPVOID (unused) */92 pushl %ebx /* PEXCEPTION_FRAME */93 call _RtlUnwind@16 /* _stdcall, rtl, callee cleans stack */94 95 popl %fs96 97 /* restore the OS/2 chain in our frame */98 movl 12(%ebp), %eax99 movl 44(%eax), %ecx /* pPrevFrameOS2 */100 movl %ecx, 0(%eax) /* pPrev */101 102 ___seh_handler_OS2_Unwind_End:103 104 xor %eax, %eax /* return code is irrelevant for EH_UNWINDING */105 jmp ___seh_handler_Return106 107 #else108 109 /* restore the OS/2 chain in our frame */110 movl 12(%ebp), %eax111 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_Return116 117 #endif118 119 ___seh_handler_Win32:120 121 /* restore the Win32 chain in our frame */122 movl 12(%ebp), %eax123 movl 60(%eax), %ecx /* pPrevFrameWin32 */124 movl %ecx, 0(%eax) /* pPrev */125 126 /* skip EH_UNWINDING calls (for compatibility with MSVC) */127 movl 8(%ebp), %ebx128 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 0134 /* clear out the Win32FS field so that we will not attempt to unwind twice135 * (first, as a result of forced unwind from ExitProcess/ExitThread/etc and136 * then from the OS/2 EH_UNWINDING call of our handler) */137 movl 12(%ebp), %eax138 movl $0, 64(%eax) /* Win32FS */139 #endif140 141 movl $1, %eax /* ExceptionContinueSearch */142 jmp ___seh_handler_Return143 144 ___seh_handler_Win32_NotUnwinding:145 146 75 /* save handler's context */ 147 76 pushl %ebp … … 153 82 154 83 /* get the size of the handler's stack */ 155 movl 40(%ebx), %ecx /* pFrame-> pTryRegs[4] isESP */84 movl 40(%ebx), %ecx /* pFrame->ESP */ 156 85 subl %esp, %ecx 157 86 jle ___seh_handler_Error /* Invalid stack! */ 158 87 movl %ecx, 4(%esp) /* save length */ 159 88 160 /* check that EXCEPTION_RECORD and CONTEXT are on our stack161 * and save their offsets in pFrame */162 movl 8(%ebp), %eax163 subl %esp, %eax164 jl ___seh_handler_Error /* Invalid stack! */165 cmpl %ecx, %eax166 jg ___seh_handler_Error /* Invalid stack! */167 movl %eax, 48(%ebx) /* pFrame->Pointers.ExceptionRecord */168 169 movl 16(%ebp), %eax170 subl %esp, %eax171 jl ___seh_handler_Error /* Invalid stack! */172 cmpl %ecx, %eax173 jg ___seh_handler_Error /* Invalid stack! */174 movl %eax, 52(%ebx) /* pFrame->Pointers.ContextRecord */175 176 89 /* save the handler's stack on heap */ 177 90 movl %ecx, %eax /* size_t */ 91 /* also reserve space for Win32 exeption info structs */ 92 addl $(sizeof_WINEXCEPTION_RECORD + sizeof_WINCONTEXT), %eax 178 93 subl $4, %esp 179 94 movl %eax, 0(%esp) … … 188 103 rep movsb 189 104 190 /* correct Pointers offsets to point to the saved stack on heap */ 105 /* convert OS/2 exception info -> Win32 */ 106 movl 16(%ebx), %eax /* pFrame->pHandlerContext */ 107 addl 4(%esp), %eax /* + size of stack = ptr to WINCONTEXT */ 108 movl %eax, 48(%ebx) /* pFrame->Pointers.ContextRecord */ 109 addl $sizeof_WINCONTEXT, %eax/* = ptr to WINEXCEPTION_RECORD */ 110 movl %eax, 44(%ebx) /* pFrame->Pointers.ExceptionRecord */ 111 pushl $0 /* TEB* */ 112 pushl 48(%ebx) /* WINCONTEXT */ 113 pushl 44(%ebx) /* WINEXCEPTION_RECORD */ 114 pushl 16(%ebp) /* pContext */ 115 pushl 8(%ebp) /* pRec */ 116 call OSLibConvertExceptionInfo 117 addl $20, %esp 118 jne ___seh_handler_CallFilter/* conversion successful? */ 119 120 /* free heap block */ 191 121 movl 16(%ebx), %eax /* pFrame->pHandlerContext */ 192 addl %eax, 48(%ebx) /* pFrame->Pointers.ExceptionRecord */ 193 addl %eax, 52(%ebx) /* pFrame->Pointers.ContextRecord */ 122 subl $4, %esp 123 movl %eax, 0(%esp) 124 call _free /* __cdecl (and _Optlink compatible -> EAX/EDX/ECX-in) */ 125 addl $4, %esp 126 jmp ___seh_handler_Error /* Info conversion error! */ 127 128 ___seh_handler_CallFilter: 194 129 195 130 /* restore __try/__catch context */ 196 131 movl 12(%ebp), %eax 197 movl 24(%eax), %ebx /* pFrame-> pTryRegs*/198 movl 28(%eax), %esi 199 movl 32(%eax), %edi 200 movl 36(%eax), %ebp 201 movl 40(%eax), %esp 132 movl 24(%eax), %ebx /* pFrame->EBX */ 133 movl 28(%eax), %esi /* pFrame->ESI */ 134 movl 32(%eax), %edi /* pFrame->EDI */ 135 movl 36(%eax), %ebp /* pFrame->EBP */ 136 movl 40(%eax), %esp /* pFrame->ESP */ 202 137 203 138 /* jump to the filter callback */ 204 movl $1, 5 6(%eax) /* pFrame->state */139 movl $1, 52(%eax) /* pFrame->state */ 205 140 jmp *8(%eax) /* pFrame->pFilterCallback */ 206 141 … … 232 167 cmpl $-1, %eax /* EXCEPTION_CONTINUE_EXECUTION? */ 233 168 jne 1f 234 movl $0, 56(%ebx) /* pFrame->state */ 235 movl $0, %eax /* ExceptionContinueExecution */ 169 movl $0, 52(%ebx) /* pFrame->state */ 170 //movl $-1, %eax /* XCPT_CONTINUE_EXECUTION (-1) */ 171 movl $1, %eax 236 172 jmp ___seh_handler_Return 237 173 1: 238 174 /* assume EXCEPTION_CONTINUE_SEARCH (0) */ 175 xorl %eax, %eax /* return XCPT_CONTINUE_SEARCH (0) */ 176 jmp ___seh_handler_Return 177 178 ___seh_handler_Unwind: 179 180 /* unwind OS/2 exception chain up to ours */ 181 pushl $0 /* PEXCEPTIONREPORTRECORD */ 182 pushl $1f /* PVOID pTargetIP */ 183 pushl 12(%ebp) /* PEXCEPTIONREGISTRATIONRECORD */ 184 call _DosUnwindException /* _syscall, rtl, but stack is not restored! */ 185 1: 186 /* restore __try/__except context */ 187 movl 12(%ebp), %eax 188 movl 24(%eax), %ebx 189 movl 28(%eax), %esi 190 movl 32(%eax), %edi 191 movl 36(%eax), %ebp 192 movl 40(%eax), %esp 193 194 /* jump to __except */ 195 movl $2, 52(%eax) /* pFrame->state */ 196 jmp *8(%eax) /* pFrame->pFilterCallback */ 197 198 ___seh_handler_Error: 199 200 addl $8, %esp 201 popl %ebp 202 203 xorl %eax, %eax /* return XCPT_CONTINUE_SEARCH (0) */ 204 205 ___seh_handler_Return: 206 207 popl %esi 208 popl %edi 209 popl %ebx 210 211 popl %ebp 212 ret 213 214 /* 215 * extern "C" 216 * int __seh_handler_win32(PEXCEPTION_RECORD pRec, 217 * struct ___seh_EXCEPTION_FRAME *pFrame, 218 * PCONTEXT pContext, PVOID) 219 * 220 * Win32 structured exception handler that implements the __try/__except 221 * functionality for GCC in ODIN_FORCE_WIN32_TIB mode. 222 * 223 * NOTE: This is a heavily platform specific stuff. The code depends on the 224 * struct ___seh_EXCEPTION_FRAME layout so be very careful and keep both 225 * in sync! 226 * 227 * __cdecl: EAX/ECX/EDX are not preserved, result in EAX/EDX, caller cleans up 228 * the stack. 229 */ 230 231 ___seh_handler_win32: 232 233 pushl %ebp 234 movl %esp, %ebp 235 236 /* 237 * 8(%ebp) - pRec 238 * 12(%ebp) - pFrame 239 * 16(%ebp) - pContext 240 * 20(%ebp) - pVoid 241 */ 242 243 /* preserve used registers */ 244 pushl %ebx 245 pushl %edi 246 pushl %esi 247 248 movl %fs, %eax 249 andl $0x0000FFFF, %eax 250 cmpl $Dos32TIB, %eax /* Running along the OS/2 chain? */ 251 jne __seh_handler_win32_Win32 /* No, assume the Win32 chain */ 252 253 /* Note: Unwinding is disabled here since a) it is more correct to do 254 * centralized unwinding from OS2ExceptionHandler2ndLevel() (i.e. not only 255 * for SEH frames) and b) it crashes under SMP kernel due to stack being 256 * corrupt by the time when unwinding happens. See comments in 257 * OS2ExceptionHandler2ndLevel() for more details. */ 258 259 #if 0 260 261 movl 8(%ebp), %eax 262 movl 4(%eax), %eax /* fHandlerFlags */ 263 testl $0x02, %eax /* EH_UNWINDING? */ 264 jne __seh_handler_win32_OS2_Unwind 265 266 /* restore the OS/2 chain in our frame */ 267 movl 12(%ebp), %eax 268 movl 44(%eax), %ecx /* pPrevFrameOS2 */ 269 movl %ecx, 0(%eax) /* pPrev */ 270 271 xorl %eax, %eax /* return XCPT_CONTINUE_SEARCH (0) */ 272 jmp __seh_handler_win32_Return 273 274 __seh_handler_win32_OS2_Unwind: 275 276 /* unwind the Win32 chain including our frame as someone's definitely 277 * jumping outside it if we're being unwound by OS/2 */ 278 movl 12(%ebp), %eax 279 cmpl $0, 64(%eax) /* Win32FS == 0? */ 280 je __seh_handler_win32_OS2_Unwind_End /* Yes, we already unwound this frame */ 281 282 /* restore the Win32 chain in our frame */ 283 movl 60(%eax), %ebx /* pPrevFrameWin32 */ 284 movl %ebx, 0(%eax) /* pPrev */ 285 286 pushl %fs 287 288 pushl 64(%eax) /* Win32FS */ 289 popl %fs 290 291 pushl $0 /* DWORD (unused) */ 292 pushl $0 /* PEXCEPTION_RECORD */ 293 pushl $0 /* LPVOID (unused) */ 294 pushl %ebx /* PEXCEPTION_FRAME */ 295 call _RtlUnwind@16 /* _stdcall, rtl, callee cleans stack */ 296 297 popl %fs 298 299 /* restore the OS/2 chain in our frame */ 300 movl 12(%ebp), %eax 301 movl 44(%eax), %ecx /* pPrevFrameOS2 */ 302 movl %ecx, 0(%eax) /* pPrev */ 303 304 __seh_handler_win32_OS2_Unwind_End: 305 306 xor %eax, %eax /* return code is irrelevant for EH_UNWINDING */ 307 jmp __seh_handler_win32_Return 308 309 #else 310 311 /* restore the OS/2 chain in our frame */ 312 movl 12(%ebp), %eax 313 movl 44(%eax), %ecx /* pPrevFrameOS2 */ 314 movl %ecx, 0(%eax) /* pPrev */ 315 316 xorl %eax, %eax /* return XCPT_CONTINUE_SEARCH (0) */ 317 jmp __seh_handler_win32_Return 318 319 #endif 320 321 __seh_handler_win32_Win32: 322 323 /* restore the Win32 chain in our frame */ 324 movl 12(%ebp), %eax 325 movl 60(%eax), %ecx /* pPrevFrameWin32 */ 326 movl %ecx, 0(%eax) /* pPrev */ 327 328 /* skip EH_UNWINDING calls (for compatibility with MSVC) */ 329 movl 8(%ebp), %ebx 330 movl 4(%ebx), %eax /* pRec->ExceptionFlags */ 331 testl $0x2, %eax /* EH_UNWINDING? */ 332 je ___seh_handler_win32_Win32_NotUnwinding /* No, continue normally */ 333 334 /* See the comment above */ 335 #if 0 336 /* clear out the Win32FS field so that we will not attempt to unwind twice 337 * (first, as a result of forced unwind from ExitProcess/ExitThread/etc and 338 * then from the OS/2 EH_UNWINDING call of our handler) */ 339 movl 12(%ebp), %eax 340 movl $0, 64(%eax) /* Win32FS */ 341 #endif 342 239 343 movl $1, %eax /* ExceptionContinueSearch */ 240 jmp ___seh_handler_Return 241 242 ___seh_handler_Unwind: 344 jmp __seh_handler_win32_Return 345 346 ___seh_handler_win32_Win32_NotUnwinding: 347 348 /* save handler's context */ 349 pushl %ebp 350 pushl $0 /* reserve space for length, must be saved right before ESP! */ 351 pushl %esp /* ESP must be saved last! */ 352 353 movl 12(%ebp), %ebx 354 movl $0f, 12(%ebx) /* pFrame->pHandlerCallback */ 355 356 /* get the size of the handler's stack */ 357 movl 40(%ebx), %ecx /* pFrame->pTryRegs[4] is ESP */ 358 subl %esp, %ecx 359 jle __seh_handler_win32_Error /* Invalid stack! */ 360 movl %ecx, 4(%esp) /* save length */ 361 362 /* check that EXCEPTION_RECORD and CONTEXT are on our stack 363 * and save their offsets in pFrame */ 364 movl 8(%ebp), %eax 365 subl %esp, %eax 366 jl __seh_handler_win32_Error /* Invalid stack! */ 367 cmpl %ecx, %eax 368 jg __seh_handler_win32_Error /* Invalid stack! */ 369 movl %eax, 48(%ebx) /* pFrame->Pointers.ExceptionRecord */ 370 371 movl 16(%ebp), %eax 372 subl %esp, %eax 373 jl __seh_handler_win32_Error /* Invalid stack! */ 374 cmpl %ecx, %eax 375 jg __seh_handler_win32_Error /* Invalid stack! */ 376 movl %eax, 52(%ebx) /* pFrame->Pointers.ContextRecord */ 377 378 /* save the handler's stack on heap */ 379 movl %ecx, %eax /* size_t */ 380 subl $4, %esp 381 movl %eax, 0(%esp) 382 call _malloc /* __cdecl (and _Optlink compatible -> EAX/EDX/ECX-in) */ 383 addl $4, %esp 384 testl %eax, %eax 385 je __seh_handler_win32_Error /* No memory! */ 386 movl 4(%esp), %ecx 387 movl %eax, %edi 388 movl %edi, 16(%ebx) /* pFrame->pHandlerContext */ 389 movl %esp, %esi 390 rep movsb 391 392 /* correct Pointers offsets to point to the saved stack on heap */ 393 movl 16(%ebx), %eax /* pFrame->pHandlerContext */ 394 addl %eax, 48(%ebx) /* pFrame->Pointers.ExceptionRecord */ 395 addl %eax, 52(%ebx) /* pFrame->Pointers.ContextRecord */ 396 397 /* restore __try/__catch context */ 398 movl 12(%ebp), %eax 399 movl 24(%eax), %ebx /* pFrame->pTryRegs */ 400 movl 28(%eax), %esi 401 movl 32(%eax), %edi 402 movl 36(%eax), %ebp 403 movl 40(%eax), %esp 404 405 /* jump to the filter callback */ 406 movl $1, 56(%eax) /* pFrame->state */ 407 jmp *8(%eax) /* pFrame->pFilterCallback */ 408 409 0: 410 /* restore handler's context (we assume that the callback puts the address 411 * of pFrame back to EBX!) */ 412 movl 16(%ebx), %esi /* pFrame->pHandlerContext */ 413 movl 0(%esi), %esp /* restore saved ESP */ 414 movl 4(%esi), %ecx /* saved stack length */ 415 subl $4, %esp /* correct ESP to compensate for PUSH ESP logic */ 416 movl %esp, %edi 417 rep movsb 418 419 popl %esp 420 addl $4, %esp 421 popl %ebp 422 423 /* free heap block */ 424 movl 16(%ebx), %eax /* pFrame->pHandlerContext */ 425 subl $4, %esp 426 movl %eax, 0(%esp) 427 call _free /* __cdecl (and _Optlink compatible -> EAX/EDX/ECX-in) */ 428 addl $4, %esp 429 430 /* analyze filter result */ 431 movl 20(%ebx), %eax /* pFrame->filterResult */ 432 cmpl $1, %eax /* EXCEPTION_EXECUTE_HANDLER? */ 433 je __seh_handler_win32_Unwind 434 cmpl $-1, %eax /* EXCEPTION_CONTINUE_EXECUTION? */ 435 jne 1f 436 movl $0, 56(%ebx) /* pFrame->state */ 437 movl $0, %eax /* ExceptionContinueExecution */ 438 jmp __seh_handler_win32_Return 439 1: 440 /* assume EXCEPTION_CONTINUE_SEARCH (0) */ 441 movl $1, %eax /* ExceptionContinueSearch */ 442 jmp __seh_handler_win32_Return 443 444 __seh_handler_win32_Unwind: 243 445 244 446 /* unwind Win32 exception chain up to ours */ … … 282 484 jmp *8(%eax) /* pFrame->pFilterCallback */ 283 485 284 __ _seh_handler_Error:486 __seh_handler_win32_Error: 285 487 286 488 addl $8, %esp … … 289 491 movl $1, %eax /* ExceptionContinueSearch */ 290 492 291 __ _seh_handler_Return:493 __seh_handler_win32_Return: 292 494 293 495 popl %esi … … 300 502 /* 301 503 * extern "C" 302 * EXCEPTION_FRAME *__seh_get_prev_frame (EXCEPTION_FRAME *pFrame)504 * EXCEPTION_FRAME *__seh_get_prev_frame_win32(EXCEPTION_FRAME *pFrame) 303 505 * 304 506 * Returns the previous Win32 exception frame given an existing frame. … … 319 521 */ 320 522 321 ___seh_get_prev_frame :523 ___seh_get_prev_frame_win32: 322 524 323 525 /* … … 328 530 /*leal ___seh_handler, %ecx*/ 329 531 movl 4(%eax), %ecx /* pFrame->Handler */ 330 cmpl $___seh_handler , %ecx331 jne ___seh_get_prev_frame_ Normal532 cmpl $___seh_handler_win32, %ecx 533 jne ___seh_get_prev_frame_win32_Normal 332 534 333 535 movl 60(%eax), %eax /* pPrevFrameWin32 */ 334 536 ret 335 537 336 ___seh_get_prev_frame_ Normal:538 ___seh_get_prev_frame_win32_Normal: 337 539 338 540 movl 0(%eax), %eax /* pFrame->Prev */
Note:
See TracChangeset
for help on using the changeset viewer.