栈回溯,x86+x64

如果需要配合PDB符号展示栈信息,可以参考github  stackwalker项目,写的很详细了

调用的windows api,直接上代码如下:

  1 #include <iostream>
  2 #include <vector>
  3 #include <stdio.h>
  4 #include <stdlib.h>
  5 #include <windows.h>
  6 
  7 
  8 struct STACK_FRAME_INFO {
  9     PVOID returnAddress;
 10     PVOID functionAddress;
 11     PVOID callAddress;
 12     PVOID callTargetAddress;
 13 };
 14 
 15 struct CALL_STACK_INFO {
 16     PVOID stackBottom;
 17     PVOID stackTop;
 18     DWORD dwFrameCount;
 19     STACK_FRAME_INFO* pFrameList;
 20 };
 21 
 22 typedef ULONG(WINAPI *RTLWALKFRAMECHAIN)(OUT PVOID *Callers, IN ULONG Count, IN ULONG Flags);
 23 
 24 void GetCallStackInfo(CALL_STACK_INFO& callStack, DWORD dwMaxFrame)
 25 {
 26     std::vector<STACK_FRAME_INFO> vecFrames;
 27 #ifdef _M_IX86
 28     STACK_FRAME_INFO StackFrame;
 29     std::vector<PVOID> vecRetAddr;
 30     ULONG StackCount = 0;
 31     RTLWALKFRAMECHAIN pRtlWalkFrameChain =
 32         (RTLWALKFRAMECHAIN)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlWalkFrameChain");
 33 
 34     vecRetAddr.resize(50);
 35     StackCount = pRtlWalkFrameChain(&vecRetAddr[0], vecRetAddr.size(), 0);
 36 
 37     for (ULONG i = 0;i < StackCount;i++)
 38     {
 39         RtlZeroMemory(&StackFrame, sizeof(StackFrame));
 40 
 41         if (vecRetAddr[i] == nullptr)
 42         {
 43             break;
 44         }
 45 
 46         StackFrame.returnAddress = vecRetAddr[i];
 47 
 48         vecFrames.push_back(StackFrame);
 49     }
 50 
 51 #elif (_M_X64)
 52     CONTEXT                       Context;
 53     KNONVOLATILE_CONTEXT_POINTERS NvContext;
 54     UNWIND_HISTORY_TABLE          UnwindHistoryTable;
 55     PRUNTIME_FUNCTION             RuntimeFunction;
 56     PVOID                         HandlerData;
 57     ULONG64                       EstablisherFrame;
 58     ULONG64                       ImageBase;
 59     STACK_FRAME_INFO              StackFrame;
 60 
 61     RtlCaptureContext(&Context);
 62 
 63     RtlZeroMemory(&UnwindHistoryTable, sizeof(UNWIND_HISTORY_TABLE));
 64 
 65     for (ULONG Frame = 0; Frame <= dwMaxFrame; Frame++)
 66     {
 67         RuntimeFunction = RtlLookupFunctionEntry(
 68             Context.Rip,
 69             &ImageBase,
 70             &UnwindHistoryTable
 71         );
 72 
 73         RtlZeroMemory(
 74             &NvContext,
 75             sizeof(KNONVOLATILE_CONTEXT_POINTERS));
 76         
 77         PUNWIND_INFO pUnwindInfo = (PUNWIND_INFO)(ImageBase + RuntimeFunction->UnwindInfoAddress);
 78 
 79         if (!RuntimeFunction)
 80         {
 81             Context.Rip = (ULONG64)(*(PULONG64)Context.Rsp);
 82             Context.Rsp += 8;
 83         }
 84         else
 85         {
 86             RtlVirtualUnwind(
 87                 UNW_FLAG_NHANDLER,
 88                 ImageBase,
 89                 Context.Rip,
 90                 RuntimeFunction,
 91                 &Context,
 92                 &HandlerData,
 93                 &EstablisherFrame,
 94                 &NvContext);
 95         }
 96 
 97         if (!Context.Rip)
 98         {
 99             break;
100         }
101             
102         RtlZeroMemory(&StackFrame, sizeof(StackFrame));
103 
104         StackFrame.returnAddress = (PVOID)Context.Rip;
105         StackFrame.functionAddress = (PVOID)(ImageBase + RuntimeFunction->BeginAddress);
106 
107         vecFrames.push_back(StackFrame);
108     }
109 #endif
110     
111     callStack.pFrameList = (STACK_FRAME_INFO*)malloc(vecFrames.size() * sizeof(STACK_FRAME_INFO));
112     if (!callStack.pFrameList)
113     {
114         callStack.dwFrameCount = 0;
115         return;
116     }
117 
118     callStack.dwFrameCount = vecFrames.size();
119     for (DWORD dwFrame = 0; dwFrame < vecFrames.size(); dwFrame++)
120     {
121         RtlCopyMemory(&callStack.pFrameList[dwFrame], &vecFrames[dwFrame], sizeof(STACK_FRAME_INFO));
122     }
123 }
124 
125 void Func1()
126 {
127     CALL_STACK_INFO callStack;
128     GetCallStackInfo(callStack, 100);
129 
130     for (DWORD dwFrame = 0; dwFrame < callStack.dwFrameCount; dwFrame++)
131     {
132         printf(
133             "FRAME %02x: FuncAddrss=%p CallAddress=%p 
",
134             dwFrame,
135             callStack.pFrameList[dwFrame].functionAddress,
136             callStack.pFrameList[dwFrame].returnAddress);
137     }
138 
139 }
140 
141 void DumpCallStack()
142 {
143     Func1();
144 }
145 
146 int main()
147 {
148     DumpCallStack();
149 
150     ::system("pause");
151 }
原文地址:https://www.cnblogs.com/hanawasakuraki/p/13664214.html