Nic*_*ing 5 windows delphi winapi
在阅读 Win64 结构化异常跟踪(来自针对 x64 异常处理支持的编程,第 7 部分:将它们放在一起,或构建堆栈遍历例程)时,我转换了代码StackWalk64.cpp。
procedure DumpExceptionStack();
var
LContext : CONTEXT;
LUnwindHistoryTable : _UNWIND_HISTORY_TABLE;
LRuntimeFunction : Pointer;
LImageBase : ULONGLONG;
HandlerData : Pointer;
EstablisherFrame : ULONG64;
NvContext : KNONVOLATILE_CONTEXT_POINTERS;
LLineNumber : integer;
LModuleName : UnicodeString;
LPublicAddr : pointer;
LPublicName : UnicodeString;
LUnitName : UnicodeString;
begin
//
// First, we'll get the caller's context.
//
RtlCaptureContext(LContext);
//
// Initialize the (optional) unwind history table.
//
LUnwindHistoryTable := Default(_UNWIND_HISTORY_TABLE);
// LUnwindHistoryTable.Unwind := True;
//
// This unwind loop intentionally skips the first call frame, as it shall
// correspond to the call to StackTrace64, which we aren't interested in.
//
repeat
//
// Try to look up unwind metadata for the current function.
//
LRuntimeFunction := RtlLookupFunctionEntry(LContext.Rip,
LImageBase,
LUnwindHistoryTable);
NvContext := Default(KNONVOLATILE_CONTEXT_POINTERS);
if not Assigned(LRuntimeFunction) then
begin
//
// If we don't have a RUNTIME_FUNCTION, then we've encountered
// a leaf function. Adjust the stack approprately.
//
//LContext.Rip := (ULONG64)(*(PULONG64)Context.Rsp);
LContext.Rip := ULONG64(Pointer(LContext.Rsp)^);
LContext.Rsp := LContext.Rsp + 8;
end
else
begin
//
// Otherwise, call upon RtlVirtualUnwind to execute the unwind for
// us.
//
RtlVirtualUnwind(UNW_FLAG_NHANDLER,
LImageBase,
LContext.Rip,
LRuntimeFunction,
LContext,
HandlerData,
EstablisherFrame,
NvContext);
end;
//
// If we reach an RIP of zero, this means that we've walked off the end
// of the call stack and are done.
//
if LContext.Rip = 0 then
Break;
//
// Display the context. Note that we don't bother showing the XMM
// context, although we have the nonvolatile portion of it.
//
if madMapFile.GetMapFileInfos(Pointer(LContext.Rip),
LModuleName,
LUnitName,
LPublicName,
LPublicAddr,
LLineNumber) then
begin
Writeln(Format('%p %s.%s %d', [Pointer(LContext.Rip), LUnitName, LPublicName, LLineNumber{, LSEHType}]));
end;
until LContext.Rip = 0;
end;
Run Code Online (Sandbox Code Playgroud)
然后我用以下命令调用它:
procedure Main();
begin
try
try
try
try
DumpExceptionStack();
finally
//
end;
except
on E : Exception do
raise
end;
except
on E : Exception do
raise
end;
except
on E : Exception do
raise
end;
end;
Run Code Online (Sandbox Code Playgroud)
当我运行应用程序(只是一个控制台应用程序)时,我只得到一个条目,Main但我期望有四个(三个嵌套异常,最后一个)。
可能是我误解了,DumpExceptionStack并且只会在抛出异常时给出我感兴趣的结果?如果是这样,获取所有异常堆栈(如果可能)所需的更改是什么 - 即。有四个输出Main?
与基于堆栈的 x86 模型相比,x64 异常模型是基于表的。这意味着异常堆栈不存在。无论如何,我从未见过尝试包含异常和finally 块的stalk walk 例程。这个没什么不同。它遍历函数调用堆栈。
单个函数内的异常流由范围表控制。在您的函数中,如果您的代码在调用处引发异常DumpExceptionStack,则多个作用域表条目与异常位置匹配。异常由最里面的匹配范围处理。范围的开始地址和结束地址之间的距离可用于推断哪个范围是最里面的。如果最里面的作用域不处理异常,或者重新引发异常,则要求下一个最里面的作用域来处理它。依此类推,直到该函数的所有匹配范围都用尽。
| 归档时间: |
|
| 查看次数: |
524 次 |
| 最近记录: |