在阅读Win64结构化异常跟踪(从
Programming against the x64 exception handling support,part 7: Putting it all together,or building a stack walk routine开始)时,我转换了代码
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,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),LLineNumber{,LSEHType}])); end; until LContext.Rip = 0; end;
然后我用以下内容称呼它:
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;
当我运行应用程序(只是一个控制台应用程序)时,我只获得了Main的一个条目,但我期待有四个(三个嵌套异常,最后一个).
可能是我错误解释了,DumpExceptionStack只会在抛出异常时给出我感兴趣的结果吗?如果是这样,那么获得所有异常堆栈(如果可能)所需的更改是什么 – 即.主要有四个输出?