Delphi 的 Exception 机制浅探(2)

2019-08-30 15:37

{ keep exception raising compatible between Delphi and C++, so } { when you make changes here, consult with the relevant C++ } { exception handling engineer. The C++ code is in xx.cpp, in } { the RTL sources, in function tossAnException. }

{ -> EAX Pointer to exception object } { [ESP] Error address }

OR EAX, EAX JNE @@GoAhead

MOV EAX, 216 // reMap 数组: 216 = reAccessViolation CALL _RunError @@GoAhead:

POP EDX // ESP 的值 ??

PUSH ESP PUSH EBP PUSH EDI PUSH ESI PUSH EBX

PUSH EAX { pass class argument } PUSH EDX { pass address argument }

PUSH ESP { pass pointer to arguments } PUSH 7 { there are seven arguments } PUSH cNonContinuable { we can't continue execution } PUSH cDelphiException { our magic exception code } PUSH EDX { pass the user's return address } JMP RaiseExceptionProc // 实际上是呼叫 RaiseException API end;

=============================================================================== ⊙ _RaiseAgain procedure

=============================================================================== procedure _RaiseAgain; asm

{ -> [ESP ] return address to user program } { [ESP+ 4 ] raise list entry (4 dwords) } { [ESP+ 4+ 4*4] saved topmost frame } { [ESP+ 4+ 5*4] saved registers (4 dwords) } { [ESP+ 4+ 9*4] return address to OS } { -> [ESP+ 4+10*4] excPtr: PExceptionRecord } { [ESP+ 8+10*4] errPtr: PExcFrame }

{ Point the error handler of the exception frame to something harmless }

MOV EAX,[ESP+8+10*4]

MOV [EAX].TExcFrame.desc,offset @@exit

{ Pop the RaiseList }

CALL SysInit.@GetTLS

MOV EDX,[EAX].RaiseListPtr

MOV ECX,[EDX].TRaiseFrame.NextRaise MOV [EAX].RaiseListPtr,ECX

{ Destroy any objects created for non-delphi exceptions }

MOV EAX,[EDX].TRaiseFrame.ExceptionRecord

AND [EAX].TExceptionRecord.ExceptionFlags,NOT cUnwinding CMP [EAX].TExceptionRecord.ExceptionCode,cDelphiException JE @@delphiException

MOV EAX,[EDX].TRaiseFrame.ExceptObject CALL TObject.Free CALL NotifyReRaise

@@delphiException:

XOR EAX,EAX ADD ESP,5*4

MOV EDX,FS:[EAX] POP ECX

MOV EDX,[EDX].TExcFrame.next MOV [ECX].TExcFrame.next,EDX

POP EBP POP EDI POP ESI POP EBX @@exit:

MOV EAX,1 end;

=============================================================================== ⊙ _HandleFinally procedure

===============================================================================

{ System.pas }

procedure _HandleFinally; asm

{ -> [ESP+ 4] excPtr: PExceptionRecord } { [ESP+ 8] errPtr: PExcFrame } { [ESP+12] ctxPtr: Pointer } { [ESP+16] dspPtr: Pointer } { <- EAX return value - always one }

MOV EAX,[ESP+4] // EAX <- TExceptionRecord 指针 MOV EDX,[ESP+8] // EDX <- TExcFrame 指针 TEST [EAX].TExceptionRecord.ExceptionFlags,cUnwindInProgress JE @@exit

MOV ECX,[EDX].TExcFrame.desc // ECX <- 异常处理函数地址 MOV [EDX].TExcFrame.desc,offset @@exit

// 替换当前异常处理函数为 @@exit // 说明已经 finally 块已经调用过

PUSH EBX // 保存堆栈 PUSH ESI PUSH EDI PUSH EBP

MOV EBP,[EDX].TExcFrame.hEBP // 恢复异常发生前的 EBP

ADD ECX,TExcDesc.instructions // ECX <- finally 跳转的地址 CALL NotifyExceptFinally

CALL ECX // 调用 finally 函数块中的指针

POP EBP // 恢复堆栈 POP EDI POP ESI

POP EBX

@@exit:

MOV EAX,1 end;

=============================================================================== ⊙ _HandleAnyException procedure

===============================================================================

procedure _HandleAnyException; asm

{$IFDEF PC_MAPPED_EXCEPTIONS}

CMP ECX, UW_EXC_CLASS_BORLANDCPP // C++ exception? JNE @@handleIt // nope, handle it // C++ exceptions aren't wanted here. Retoss them as is CALL SysRaiseCPPException

@@handleIt:

PUSH EAX PUSH EDX

CALL UnblockOSExceptions POP EDX POP EAX

// If the exception is a Delphi exception thrown from C++, coopt it. CALL MaybeCooptException

OR [EAX].TRaisedException.Flags, excIsBeingHandled CALL LinkException MOV ESI, EBX MOV EDX, [ESP] CALL NotifyExcept MOV EBX, ESI {$ENDIF}

{$IFNDEF PC_MAPPED_EXCEPTIONS}

{ -> [ESP+ 4] excPtr: PExceptionRecord } { [ESP+ 8] errPtr: PExcFrame } { [ESP+12] ctxPtr: Pointer } { [ESP+16] dspPtr: Pointer } { <- EAX return value - always one }

MOV EAX,[ESP+4]

TEST [EAX].TExceptionRecord.ExceptionFlags,cUnwindInProgress JNE @@exit

CMP [EAX].TExceptionRecord.ExceptionCode,cDelphiException MOV EDX,[EAX].TExceptionRecord.ExceptObject MOV ECX,[EAX].TExceptionRecord.ExceptAddr JE @@DelphiException CLD

CALL _FpuInit

MOV EDX,ExceptObjProc TEST EDX,EDX JE @@exit CALL EDX TEST EAX,EAX JE @@exit

MOV EDX,[ESP+12]

MOV ECX,[ESP+4]

CMP [ECX].TExceptionRecord.ExceptionCode,cCppException JE @@CppException

CALL NotifyNonDelphiException {$IFDEF MSWINDOWS}

CMP BYTE PTR JITEnable,0 JBE @@CppException

CMP BYTE PTR DebugHook,0

JA @@CppException // Do not JIT if debugging LEA ECX,[ESP+4] PUSH EAX PUSH ECX

CALL UnhandledExceptionFilter

CMP EAX,EXCEPTION_CONTINUE_SEARCH POP EAX JE @@exit MOV EDX,EAX MOV EAX,[ESP+4]

MOV ECX,[EAX].TExceptionRecord.ExceptionAddress JMP @@GoUnwind {$ENDIF}

@@CppException:

MOV EDX,EAX MOV EAX,[ESP+4]

MOV ECX,[EAX].TExceptionRecord.ExceptionAddress

@@DelphiException: {$IFDEF MSWINDOWS}

CMP BYTE PTR JITEnable,1 JBE @@GoUnwind

CMP BYTE PTR DebugHook,0 { Do not JIT if debugging } JA @@GoUnwind PUSH EAX

LEA EAX,[ESP+8] PUSH EDX PUSH ECX PUSH EAX

CALL UnhandledExceptionFilter

CMP EAX,EXCEPTION_CONTINUE_SEARCH POP ECX POP EDX POP EAX JE @@exit {$ENDIF}

@@GoUnwind:

OR [EAX].TExceptionRecord.ExceptionFlags,cUnwinding

PUSH EBX XOR EBX,EBX PUSH ESI PUSH EDI PUSH EBP

MOV EBX,FS:[EBX]

PUSH EBX { Save pointer to topmost frame } PUSH EAX { Save OS exception pointer } PUSH EDX { Save exception object } PUSH ECX { Save exception address }

MOV EDX,[ESP+8+8*4]

PUSH 0 PUSH EAX

PUSH offset @@returnAddress PUSH EDX

CALL RtlUnwindProc @@returnAddress:

MOV EDI,[ESP+8+8*4]

{ Make the RaiseList entry on the stack }

CALL SysInit.@GetTLS PUSH [EAX].RaiseListPtr

MOV [EAX].RaiseListPtr,ESP

MOV EBP,[EDI].TExcFrame.hEBP MOV EBX,[EDI].TExcFrame.desc

MOV [EDI].TExcFrame.desc,offset @@exceptFinally

ADD EBX,TExcDesc.instructions CALL NotifyAnyExcept JMP EBX

@@exceptFinally:

JMP _HandleFinally

@@destroyExcept:

{ we come here if an exception handler has thrown yet another exception } { we need to destroy the exception object and pop the raise list. }

CALL SysInit.@GetTLS

MOV ECX,[EAX].RaiseListPtr

MOV EDX,[ECX].TRaiseFrame.NextRaise MOV [EAX].RaiseListPtr,EDX

MOV EAX,[ECX].TRaiseFrame.ExceptObject JMP TObject.Free

@@exit:

MOV EAX,1

{$ENDIF} { not PC_MAPPED_EXCEPTIONS } end;

=============================================================================== ⊙ _HandleOnException procedure

=============================================================================== { System._HandleOnException }

procedure _HandleOnException; asm

{ -> [ESP+ 4] excPtr: PExceptionRecord } { [ESP+ 8] errPtr: PExcFrame } { [ESP+12] ctxPtr: Pointer } { [ESP+16] dspPtr: Pointer } { <- EAX return value - always one }

// 如果 ExceptionFlags 是 cUnwindInProgress 则退出


Delphi 的 Exception 机制浅探(2).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:滇池调研报告

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: