Delphi 5-使用RTLUnwind捕获所有异常
我今天在这里是因为我在使用Delphi5和RTLUnwind捕捉程序的每个异常时遇到了一些麻烦 问题是它捕捉到一个错误,但它在。。。 当我尝试调试时,会出现访问冲突 以下是我的全部捕获代码:Delphi 5-使用RTLUnwind捕获所有异常,delphi,exception,delphi-5,Delphi,Exception,Delphi 5,我今天在这里是因为我在使用Delphi5和RTLUnwind捕捉程序的每个异常时遇到了一些麻烦 问题是它捕捉到一个错误,但它在。。。 当我尝试调试时,会出现访问冲突 以下是我的全部捕获代码: unit ExceptLog; interface implementation uses SysUtils, Windows, U_Test, Dialogs; type PCardinal = ^Cardinal; PtrUInt = cardinal; PPtrUInt = ^Pt
unit ExceptLog;
interface
implementation
uses SysUtils, Windows, U_Test, Dialogs;
type
PCardinal = ^Cardinal;
PtrUInt = cardinal;
PPtrUInt = ^PtrUInt;
PExceptionRecord = ^TExceptionRecord;
TExceptionRecord =
record
ExceptionCode : LongWord;
ExceptionFlags : LongWord;
OuterException : PExceptionRecord;
ExceptionAddress : Pointer;
NumberParameters : Longint;
case {IsOsException:} Boolean of
True : (ExceptionInformation : array [0..14] of Longint);
False : (ExceptAddr: Pointer; ExceptObject: Pointer);
end;
var
// Declaration for Delphi 5
oldRTLUnwindProc: procedure; stdcall;
RTLUnWindProc: pointer;
procedure MyRtlUnwind; stdcall;
var
s : string;
PER : PExceptionRecord;
E: Exception;
begin
asm
mov eax, dword ptr [EBP+8+13*4]
mov PER, eax
end;
if PER^.ExceptionFlags and 1=1 then
begin
try
E := Exception(PER^.ExceptObject);
if (E is Exception) then
begin
s:= 'Delphi exception, type : ' + E.ClassName + ', message: ' + E.Message;
OutputDebugString(PChar(s));
_MessageDlg(s, mtInformation, [mbOk], 0);
end;
except
end;
end;
asm
mov esp, ebp
pop ebp
jmp oldRTLUnwindProc // here come the access violation
end;
end;
{--------------------------------------------------------------------------------------------------}
procedure PatchCodePtrUInt(Code: PPtrUInt; Value: PtrUInt);
var RestoreProtection, Ignore: DWORD;
begin
if VirtualProtect(Code, SizeOf(Code^), PAGE_EXECUTE_READWRITE, RestoreProtection) then
begin
Code^ := Value;
VirtualProtect(Code, SizeOf(Code^), RestoreProtection, Ignore);
FlushInstructionCache(GetCurrentProcess, Code, SizeOf(Code^));
end;
end;
{--------------------------------------------------------------------------------------------------}
procedure Patch(P: PAnsiChar);
var
i: Integer;
addr: PAnsiChar;
begin
for i:= 0 to 31 do
begin
if (PCardinal(P)^ = $6850006a) and (PWord(P+8)^ = $E852) then
begin
inc(P, 10);
if PInteger(P)^<0 then
begin
addr := P+4+PInteger(P)^;
if PWord(addr)^=$25FF then
begin
PatchCodePtrUInt(Pointer(addr+2),cardinal(@RTLUnwindProc));
exit;
end;
end;
end else
inc(P);
end;
end;
{--------------------------------------------------------------------------------------------------}
procedure PatchCallRtlUnWind;
asm
mov eax,offset System.@HandleAnyException+200
call Patch
end;
{--------------------------------------------------------------------------------------------------}
procedure InitExceptionLogging;
begin
oldRTLUnWindProc := RTLUnwindProc;
RTLUnwindProc := @MyRtlUnwind;
PatchCallRtlUnWind;
end;
{--------------------------------------------------------------------------------------------------}
initialization
InitExceptionLogging;
end.
unitexceptlog;
接口
实施
使用SysUtils、Windows、U_测试、对话框;
类型
PCardinal=^基数;
PtrUInt=基数;
PPtrUInt=^PtrUInt;
PExceptionRecord=^TExceptionRecord;
TExceptionRecord=
记录
例外代码:长单词;
例外标志:长单词;
OuterException:PExceptionRecord;
例外地址:指针;
数字参数:Longint;
案例{IsOsException:}的布尔值
True:(例外信息:Longint的数组[0..14];
False:(ExceptAddress:指针;ExceptObject:指针);
结束;
变量
//Delphi 5的声明
oldRTLUnwindProc:程序;stdcall;
RTLUnWindProc:指针;
桃金娘风;stdcall;
变量
s:字符串;
PER:PEExceptionRecord;
E:例外;
开始
asm
mov eax,dword ptr[EBP+8+13*4]
每分钟移动量
结束;
如果PER^.ExceptionFlags和1=1,则
开始
尝试
E:=异常(每个异常对象);
如果(E是例外),那么
开始
s:='Delphi异常,类型:'+E.ClassName+',消息:'+E.message;
OutputDebugString(PChar(s));
_MessageDlg(s,mtInformation,[mbOk],0);
结束;
除了
结束;
结束;
asm
电除尘器
流行ebp
jmp oldRTLUnwindProc//访问冲突来了
结束;
结束;
{--------------------------------------------------------------------------------------------------}
过程PATCHCODEPTRAINT(代码:PPtrUInt;值:ptraint);
var恢复保护,忽略:DWORD;
开始
如果是VirtualProtect(代码,SizeOf(代码^),PAGE\u EXECUTE\u READWRITE,RestoreProtection),那么
开始
代码^:=值;
虚拟保护(代码,SizeOf(代码^),恢复保护,忽略);
FlushInstructionCache(GetCurrentProcess,Code,SizeOf(Code^));
结束;
结束;
{--------------------------------------------------------------------------------------------------}
程序补片(P:PAnsiChar);
变量
i:整数;
地址:潘斯卡尔;
开始
对于i:=0到31 do
开始
如果(PCardinal(P)^=6850006a美元)和(PWord(P+8)^=E852美元),则
开始
公司(第10页);
如果PInteger(P)^更容易使用MadeExceptMadeExcept似乎很有趣,但对我来说有点太大了,如果我选择这样做,那就是限制第三方程序或大型实现。但如果我找不到任何回应,Madeexcept可能是一个解决方案。ThanksIt完全不需要花时间添加它,它被证明是有效的,它具有难以置信的能力,它的堆栈跟踪非常出色。你根本不可能想出任何有用的东西。这不是指个人。我知道除了疯狂,我不能做任何事情。不管怎样,祝你好运。你不是Delphi5的专家,你自己写的代码吗?我会听从大卫的建议,把它换成疯子。我并不惊讶你用一些魔法常数修补地址而得到AV。看起来它是从《幻影》中的莫莫特(mORMot)搬来的,@Lieven。原始代码更复杂;也许乔亚过于简单化了,不小心删除了一些重要的东西。Joja,原始代码编译和运行是否正确?在这附近可以看到那个图书馆的作者。MadeExceptMadeExcept看起来很有趣,但对我来说有点太大了,如果我选择这样做,那就是限制第三方程序或大型实现。但如果我找不到任何回应,Madeexcept可能是一个解决方案。ThanksIt完全不需要花时间添加它,它被证明是有效的,它具有难以置信的能力,它的堆栈跟踪非常出色。你根本不可能想出任何有用的东西。这不是指个人。我知道除了疯狂,我不能做任何事情。不管怎样,祝你好运。你不是Delphi5的专家,你自己写的代码吗?我会听从大卫的建议,把它换成疯子。我并不惊讶你用一些魔法常数修补地址而得到AV。看起来它是从《幻影》中的莫莫特(mORMot)搬来的,@Lieven。原始代码更复杂;也许乔亚过于简单化了,不小心删除了一些重要的东西。Joja,原始代码编译和运行是否正确?在这附近可以看到那个图书馆的作者。他也许能帮忙。