Skip to content

Small change for GetBacktrace on Windows ARM64.

Based on: https://chromium.googlesource.com/chromium/src/base/+/master/profiler/win32_stack_frame_unwinder.cc#116

function GetBacktrace(Context: TContext; StartingFrame: Pointer; out Frames: PPointer): Longint;
const
  CONTEXT_UNWOUND_TO_CALL   = $20000000;
var
  UnwindHistory: UNWIND_HISTORY_TABLE;
  RuntimeFunction: PRUNTIME_FUNCTION;
  HandlerData: Pointer;
  EstablisherFrame: QWord;
  ImageBase: QWord;
  FrameCount,FrameBufSize: Longint;
  CP: KNONVOLATILE_CONTEXT_POINTERS;
begin
  FillChar(UnwindHistory,sizeof(UNWIND_HISTORY_TABLE),0);
  UnwindHistory.Unwind:=1;

  FrameCount:=0;
  FrameBufSize:=0;
  Frames:=nil;
  repeat
    RuntimeFunction:=RtlLookupFunctionEntry(ContextGetIP(Context), ImageBase, @UnwindHistory);

    if Assigned(RuntimeFunction) then
      RtlVirtualUnwind(UNW_FLAG_NHANDLER, ImageBase, ContextGetIP(Context),
        RuntimeFunction, Context, @HandlerData, @EstablisherFrame, @CP)
    else  { a leaf function }
    begin
{$if defined(CPUX86_64)}
      Context.Rip:=PQWord(Context.Rsp)^;
      Inc(Context.Rsp, sizeof(Pointer));
{$elseif defined(CPUAARCH64)}
      // For leaf function on Windows ARM64, return address is at LR(X30).  Add
      // CONTEXT_UNWOUND_TO_CALL flag to avoid unwind ambiguity for tailcall on
      // ARM64, because padding after tailcall is not guaranteed.
      // Source: https://chromium.googlesource.com/chromium/src/base/+/master/profiler/win32_stack_frame_unwinder.cc#116
      Context.Pc:=Context.Lr;
      Context.ContextFlags := Context.ContextFlags OR CONTEXT_UNWOUND_TO_CALL;
{$else}
Edited by Alfred Glänzer
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information