如何使用Windows x64记录堆栈帧
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用Windows x64记录堆栈帧相关的知识,希望对你有一定的参考价值。
我在Win32上使用Stackdumps,将所有返回地址写入我的日志文件。稍后,我将它们与一个映射文件进行匹配(请参阅我的文章[Post Mortem Debugging] [1])。
编辑::问题已解决-请在下面查看我自己的答案。
对于Windows x64,我没有找到一种可靠的方式仅将返回地址写入日志文件。我尝试了几种方法:
试验1:指针算术:
CONTEXT Context;
RtlCaptureContext(&Context);
char *eNextBP = (char *)Context.Rdi;
for(ULONG Frame = 0; eNextBP ; Frame++)
{
char *pBP = eNextBP;
eNextBP = *(char **)pBP; // Next BP in Stack
fprintf(LogFile, "*** %2d called from %016LX (pBP at %016LX)
", Frame,
(ULONG64)*(char **)(pBP + 8), (ULONG64)pBP);
}
这在调试版本中工作正常-但在发行版本中崩溃。 Context.Rdi的值在那里没有可用的值。我确实检查了编译器设置(Visual Studio 2005)中的差异。我没有发现任何可疑的东西。
试用版2:使用StackWalk64
RtlCaptureContext(&Context);
STACKFRAME64 stk;
memset(&stk, 0, sizeof(stk));
stk.AddrPC.Offset = Context.Rip;
stk.AddrPC.Mode = AddrModeFlat;
stk.AddrStack.Offset = Context.Rsp;
stk.AddrStack.Mode = AddrModeFlat;
stk.AddrFrame.Offset = Context.Rbp;
stk.AddrFrame.Mode = AddrModeFlat;
for(ULONG Frame = 0; ; Frame++)
{
BOOL result = StackWalk64(
IMAGE_FILE_MACHINE_AMD64, // __in DWORD MachineType,
GetCurrentProcess(), // __in HANDLE hProcess,
GetCurrentThread(), // __in HANDLE hThread,
&stk, // __inout LP STACKFRAME64 StackFrame,
&Context, // __inout PVOID ContextRecord,
NULL, // __in_opt PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
SymFunctionTableAccess64, // __in_opt PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
SymGetModuleBase64, // __in_opt PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
NULL // __in_opt PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress
);
fprintf(gApplSetup.TraceFile, "*** %2d called from %016LX STACK %016LX FRAME %016LX
", Frame, (ULONG64)stk.AddrPC.Offset, (ULONG64)stk.AddrStack.Offset, (ULONG64)stk.AddrFrame.Offset);
if(! result)
break;
}
这不仅会转储返回地址,还会转储整个堆栈。使用这种方法,我的日志文件中收到大约1000行。我可以使用它,但是我必须搜索行,并且堆栈的一些数据恰好是有效的代码地址。
审判3:使用回溯
static USHORT (WINAPI
*s_pfnCaptureStackBackTrace)(ULONG, ULONG, PVOID*, PULONG) = 0;
if (s_pfnCaptureStackBackTrace == 0)
{
const HMODULE hNtDll = ::GetModuleHandle("ntdll.dll");
reinterpret_cast<void*&>(s_pfnCaptureStackBackTrace)
= ::GetProcAddress(hNtDll, "RtlCaptureStackBackTrace");
}
PVOID myFrames[128];
s_pfnCaptureStackBackTrace(0, 128, myFrames, NULL);
for(int ndx = 0; ndx < 128; ndx++)
fprintf(gApplSetup.TraceFile, "*** BackTrace %3d %016LX
", ndx, (ULONG64)myFrames[ndx]);
导致没有可用的信息。
有人在x64中实现了这样的堆栈遍历,它只写出堆栈中的返回地址吗?我见过方法[StackTrace64] [2],[StackWalker] [3]和其他方法。它们要么不编译,要么过于复杂。这基本上是一个简单的任务!
示例StackDump64.cpp
#include <Windows.h>
#include <DbgHelp.h>
#include <Winbase.h>
#include <stdio.h>
void WriteStackDump()
{
FILE *myFile = fopen("StackDump64.log", "w+t");
CONTEXT Context;
memset(&Context, 0, sizeof(Context));
RtlCaptureContext(&Context);
RtlCaptureContext(&Context);
STACKFRAME64 stk;
memset(&stk, 0, sizeof(stk));
stk.AddrPC.Offset = Context.Rip;
stk.AddrPC.Mode = AddrModeFlat;
stk.AddrStack.Offset = Context.Rsp;
stk.AddrStack.Mode = AddrModeFlat;
stk.AddrFrame.Offset = Context.Rbp;
stk.AddrFrame.Mode = AddrModeFlat;
for(ULONG Frame = 0; ; Frame++)
{
BOOL result = StackWalk64(
IMAGE_FILE_MACHINE_AMD64, // __in DWORD MachineType,
GetCurrentProcess(), // __in HANDLE hProcess,
GetCurrentThread(), // __in HANDLE hThread,
&stk, // __inout LP STACKFRAME64 StackFrame,
&Context, // __inout PVOID ContextRecord,
NULL, // __in_opt PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
SymFunctionTableAccess64, // __in_opt PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
SymGetModuleBase64, // __in_opt PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
NULL // __in_opt PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress
);
fprintf(myFile, "*** %2d called from %016I64LX STACK %016I64LX AddrReturn %016I64LX
", Frame, stk.AddrPC.Offset, stk.AddrStack.Offset, stk.AddrReturn.Offset);
if(! result)
break;
}
fclose(myFile);
}
void funcC()
{
WriteStackDump();
}
void funcB()
{
funcC();
}
void funcA()
{
funcB();
}
int main(int argc, char *argv[])
{
funcA();
}
运行此示例将导致以下日志文件内容:
*** 0 called from 000000014000109E STACK 000000000012F780 AddrReturn 0000000140005798
*** 1 called from 000000001033D160 STACK 000000000012F788 AddrReturn 00000001400057B0
*** 2 called from 00000001400057B0 STACK 000000000012F790 AddrReturn 0000000000000001
*** 3 called from 0000000000000002 STACK 000000000012F798 AddrReturn 00000001400057B0
*** 4 called from 0000000000000002 STACK 000000000012F7A0 AddrReturn 000000000012F7F0
*** 5 called from 000000000012F7F0 STACK 000000000012F7A8 AddrReturn 0000000000000000
*** 6 called from 0000000000000000 STACK 000000000012F7B0 AddrReturn 000007FF7250CF40
*** 7 called from 000007FF7250CF40 STACK 000000000012F7B8 AddrReturn 000007FF7250D390
*** 8 called from 000007FF7250D390 STACK 000000000012F7C0 AddrReturn 000007FF725B6950
*** 9 called from 000007FF725B6950 STACK 000000000012F7C8 AddrReturn CCCCCCCCCCCCCCCC
*** 10 called from CCCCCCCCCCCCCCCC STACK 000000000012F7D0 AddrReturn 000000001033D160
*** 11 called from 000000001033D160 STACK 000000000012F7D8 AddrReturn CCCCCCCCCCCCCCCC
*** 12 called from CCCCCCCCCCCCCCCC STACK 000000000012F7E0 AddrReturn CCCCCCCCCCCCCCCC
*** 13 called from CCCCCCCCCCCCCCCC STACK 000000000012F7E8 AddrReturn CCCCCCCCCCCCCCCC
*** 14 called from CCCCCCCCCCCCCCCC STACK 000000000012F7F0 AddrReturn 0000000000000000
*** 15 called from 0000000000000000 STACK 000000000012F7F8 AddrReturn 0000000000000000
*** 16 called from 0000000000000000 STACK 000000000012F800 AddrReturn 0000000000000000
*** 17 called from 0000000000000000 STACK 000000000012F808 AddrReturn 0000000000000000
*** 18 called from 0000000000000000 STACK 000000000012F810 AddrReturn 0000000000000000
*** 19 called from 0000000000000000 STACK 000000000012F818 AddrReturn 0000000000000000
*** 20 called from 0000000000000000 STACK 000000000012F820 AddrReturn 00001F800010000F
*** 21 called from 00001F800010000F STACK 000000000012F828 AddrReturn 0053002B002B0033
*** 22 called from 0053002B002B0033 STACK 000000000012F830 AddrReturn 00000206002B002B
*** 23 called from 00000206002B002B STACK 000000000012F838 AddrReturn 0000000000000000
*** 24 called from 0000000000000000 STACK 000000000012F840 AddrReturn 0000000000000000
*** 25 called from 0000000000000000 STACK 000000000012F848 AddrReturn 0000000000000000
*** 26 called from 0000000000000000 STACK 000000000012F850 AddrReturn 0000000000000000
*** 27 called from 0000000000000000 STACK 000000000012F858 AddrReturn 0000000000000000
*** 28 called from 0000000000000000 STACK 000000000012F860 AddrReturn 0000000000000000
*** 29 called from 0000000000000000 STACK 000000000012F868 AddrReturn 0000000000000246
*** 30 called from 0000000000000246 STACK 000000000012F870 AddrReturn 000000000012F7F0
*** 31 called from 000000000012F7F0 STACK 000000000012F878 AddrReturn 0000000000000000
*** 32 called from 0000000000000000 STACK 000000000012F880 AddrReturn 0000000000000000
*** 33 called from 0000000000000000 STACK 000000000012F888 AddrReturn 000000000012F888
*** 34 called from 000000000012F888 STACK 000000000012F890 AddrReturn 0000000000000000
*** 35 called from 0000000000000000 STACK 000000000012F898 AddrReturn 0000000000000000
*** 36 called from 0000000000000000 STACK 000000000012F8A0 AddrReturn 000000000012FE10
*** 37 called from 000000000012FE10 STACK 000000000012F8A8 AddrReturn 0000000000000000
*** 38 called from 0000000000000000 STACK 000000000012F8B0 AddrReturn 0000000000000000
*** 39 called from 0000000000000000 STACK 000000000012F8B8 AddrReturn 0000000000000000
*** 40 called from 0000000000000000 STACK 000000000012F8C0 AddrReturn 0000000000000246
*** 41 called from 0000000000000246 STACK 000000000012F8C8 AddrReturn 0000000000000000
*** 42 called from 0000000000000000 STACK 000000000012F8D0 AddrReturn 0000000000000000
*** 43 called from 0000000000000000 STACK 000000000012F8D8 AddrReturn 0000000000000000
*** 44 called from 0000000000000000 STACK 000000000012F8E0 AddrReturn 0000000000000000
*** 45 called from 0000000000000000 STACK 000000000012F8E8 AddrReturn 0000000000000000
*** 46 called from 0000000000000000 STACK 000000000012F8F0 AddrReturn 000000000000027F
*** 47 called from 000000000000027F STACK 000000000012F8F8 AddrReturn 0000000000000000
*** 48 called from 0000000000000000 STACK 000000000012F900 AddrReturn 0000000000000000
*** 49 called from 0000000000000000 STACK 000000000012F908 AddrReturn 0000FFFF00001F80
*** 50 called from 0000FFFF00001F80 STACK 000000000012F910 AddrReturn 0000000000000000
*** 51 called from 0000000000000000 STACK 000000000012F918 AddrReturn 0000000000000000
*** 52 called from 0000000000000000 STACK 000000000012F920 AddrReturn 0000000000000000
*** 53 called from 0000000000000000 STACK 000000000012F928 AddrReturn 0000000000000000
*** 54 called from 0000000000000000 STACK 000000000012F930 AddrReturn 0000000000000000
*** 55 called from 0000000000000000 STACK 000000000012F938 AddrReturn 0000000000000000
*** 56 called from 0000000000000000 STACK 000000000012F940 AddrReturn 0000000000000000
*** 57 called from 0000000000000000 STACK 000000000012F948 AddrReturn 0000000000000000
*** 58 called from 0000000000000000 STACK 000000000012F950 AddrReturn 0000000000000000
*** 59 called from 0000000000000000 STACK 000000000012F958 AddrReturn 0000000000000000
*** 60 called from 0000000000000000 STACK 000000000012F960 AddrReturn 0000000000000000
*** 61 called from 0000000000000000 STACK 000000000012F968 AddrReturn 0000000000000000
*** 62 called from 0000000000000000 STACK 000000000012F970 AddrReturn 0000000000000000
*** 63 called from 0000000000000000 STACK 000000000012F978 AddrReturn 0000000000000000
*** 64 called from 0000000000000000 STACK 000000000012F980 AddrReturn 0000000000000000
*** 65 called from 0000000000000000 STACK 000000000012F988 AddrReturn 0000000000000000
*** 66 called from 0000000000000000 STACK 000000000012F990 AddrReturn 0000000000000000
*** 67 called from 0000000000000000 STACK 000000000012F998 AddrReturn 0000000000000000
*** 68 called from 0000000000000000 STACK 000000000012F9A0 AddrReturn 0000000000000000
*** 69 called from 0000000000000000 STACK 000000000012F9A8 AddrReturn 0000000000000000
*** 70 called from 0000000000000000 STACK 000000000012F9B0 AddrReturn 0000000000000000
*** 71 called from 0000000000000000 STACK 000000000012F9B8 AddrReturn 0000000000000000
*** 72 called from 0000000000000000 STACK 000000000012F9C0 AddrReturn 0000000000000000
*** 73 called from 0000000000000000 STACK 000000000012F9C8 AddrReturn 0000000000000000
*** 74 called from 0000000000000000 STACK 000000000012F9D0 AddrReturn 0000000000000000
*** 75 called from 0000000000000000 STACK 000000000012F9D8 AddrReturn 0000000000000000
*** 76 called from 0000000000000000 STACK 000000000012F9E0 AddrReturn 0000000000000000
*** 77 called from 0000000000000000 STACK 000000000012F9E8 AddrReturn 0000000000000000
*** 78 called from 0000000000000000 STACK 000000000012F9F0 AddrReturn 0000000000000000
*** 79 called from 0000000000000000 STACK 000000000012F9F8 AddrReturn 0000000000000000
*** 80 called from 0000000000000000 STACK 000000000012FA00 AddrReturn 0000000000000000
*** 81 called from 0000000000000000 STACK 000000000012FA08 AddrReturn 0000000000000000
*** 82 called from 0000000000000000 STACK 000000000012FA10 AddrReturn 0000000000000000
*** 83 called from 0000000000000000 STACK 000000000012FA18 AddrReturn 0000000000000000
*** 84 called from 0000000000000000 STACK 000000000012FA20 AddrReturn 0000000000000000
*** 85 called from 0000000000000000 STACK 000000000012FA28 AddrReturn 0000000000000000
*** 86 called from 0000000000000000 STACK 000000000012FA30 AddrReturn 0000000000000000
*** 87 called from 0000000000000000 STACK 000000000012FA38 AddrReturn 0000000000000000
*** 88 called from 0000000000000000 STACK 000000000012FA40 AddrReturn 0000000000000000
*** 89 called from 0000000000000000 STACK 000000000012FA48 AddrReturn 0000000000000000
*** 90 called from 0000000000000000 STACK 000000000012FA50 AddrReturn 0000000000000000
*** 91 called from 0000000000000000 STACK 000000000012FA58 AddrReturn 0000000000000000
*** 92 called from 0000000000000000 STACK 000000000012FA60 AddrReturn 0000000000000000
*** 93 called from 0000000000000000 STACK 000000000012FA68 AddrReturn 0000000000000000
*** 94 called from 0000000000000000 STACK 000000000012FA70 AddrReturn 0000000000000000
*** 95 called from 0000000000000000 STACK 000000000012FA78 AddrReturn 0000000000000000
*** 96 called from 0000000000000000 STACK 000000000012FA80 AddrReturn 0000000000000000
*** 97 called from 0000000000000000 STACK 000000000012FA88 AddrReturn 0000000000000000
*** 98 called from 0000000000000000 STACK 000000000012FA90 AddrReturn 0000000000000000
*** 99 called from 0000000000000000 STACK 000000000012FA98 AddrReturn 0000000000000000
*** 100 called from 0000000000000000 STACK 000000000012FAA0 AddrReturn 0000000000000000
*** 101 called from 0000000000000000 STACK 000000000012FAA8 AddrReturn 0000000000000000
*** 102 called from 0000000000000000 STACK 000000000012FAB0 AddrReturn 0000000000000000
*** 103 called from 0000000000000000 STACK 000000000012FAB8 AddrReturn 0000000000000000
*** 104 called from 0000000000000000 STACK 000000000012FAC0 AddrReturn 0000000000000000
*** 105 called from 0000000000000000 STACK 000000000012FAC8 AddrReturn 0000000000000000
*** 106 called from 0000000000000000 STACK 000000000012FAD0 AddrReturn 0000000000000000
*** 107 called from 0000000000000000 STACK 000000000012FAD8 AddrReturn 0000000000000000
*** 108 called from 0000000000000000 STACK 000000000012FAE0 AddrReturn 0000000000000000
*** 109 called from 0000000000000000 STACK 000000000012FAE8 AddrReturn 0000000000000000
*** 110 called from 0000000000000000 STACK 000000000012FAF0 AddrReturn 0000000000000000
*** 111 called from 0000000000000000 STACK 000000000012FAF8 AddrReturn 0000000000000000
*** 112 called from 0000000000000000 STACK 000000000012FB00 AddrReturn 0000000000000000
*** 113 called from 0000000000000000 STACK 000000000012FB08 AddrReturn 0000000000000000
*** 114 called from 0000000000000000 STACK 000000000012FB10 AddrReturn 0000000000000000
*** 115 called from 0000000000000000 STACK 000000000012FB18 AddrReturn 0000000000000000
*** 116 called from 0000000000000000 STACK 000000000012FB20 AddrReturn 0000000000000000
*** 117 called from 0000000000000000 STACK 000000000012FB28 AddrReturn 0000000000000000
*** 118 called from 0000000000000000 STACK 000000000012FB30 AddrReturn 0000000000000000
*** 119 called from 0000000000000000 STACK 000000000012FB38 AddrReturn 0000000000000000
*** 120 called from 0000000000000000 STACK 000000000012FB40 AddrReturn 0000000000000000
*** 121 called from 0000000000000000 STACK 000000000012FB48 AddrReturn 0000000000000000
*** 122 called from 0000000000000000 STACK 000000000012FB50 AddrReturn 0000000000000000
*** 123 called from 0000000000000000 STACK 000000000012FB58 AddrReturn 0000000000000000
*** 124 called from 0000000000000000 STACK 000000000012FB60 AddrReturn 0000000000000000
*** 125 called from 0000000000000000 STACK 000000000012FB68 AddrReturn 0000000000000000
*** 126 called from 0000000000000000 STACK 000000000012FB70 AddrReturn 0000000000000000
*** 127 called from 0000000000000000 STACK 000000000012FB78 AddrReturn 0000000000000000
*** 128 called from 0000000000000000 STACK 000000000012FB80 AddrReturn 0000000000000000
*** 129 called from 0000000000000000 STACK 000000000012FB88 AddrReturn 0000000000000000
*** 130 called from 0000000000000000 STACK 000000000012FB90 AddrReturn 0000000000000000
*** 131 called from 0000000000000000 STACK 000000000012FB98 AddrReturn 0000000000000000
*** 132 called from 0000000000000000 STACK 000000000012FBA0 AddrReturn 0000000000000000
*** 133 called from 0000000000000000 STACK 000000000012FBA8 AddrReturn 0000000000000000
*** 134 called from 0000000000000000 STACK 000000000012FBB0 AddrReturn 0000000000000000
*** 135 called from 0000000000000000 STACK 000000000012FBB8 AddrReturn 0000000000000000
*** 136 called from 0000000000000000 STACK 000000000012FBC0 AddrReturn 0000000000000000
*** 137 called from 0000000000000000 STACK 000000000012FBC8 AddrReturn 0000000000000000
*** 138 called from 0000000000000000 STACK 000000000012FBD0 AddrReturn 0000000000000000
*** 139 called from 0000000000000000 STACK 000000000012FBD8 AddrReturn 0000000000000000
*** 140 called from 0000000000000000 STACK 000000000012FBE0 AddrReturn 0000000000000000
*** 141 called from 0000000000000000 STACK 000000000012FBE8 AddrReturn 0000000000000000
*** 142 called from 0000000000000000 STACK 000000000012FBF0 AddrReturn 0000000000000000
*** 143 called from 0000000000000000 STACK 000000000012FBF8 AddrReturn 0000000000000000
*** 144 called from 0000000000000000 STACK 000000000012FC00 AddrReturn 0000000000000000
*** 145 called from 0000000000000000 STACK 000000000012FC08 AddrReturn 0000000000000000
*** 146 called from 0000000000000000 STACK 000000000012FC10 AddrReturn 0000000000000000
*** 147 called from 0000000000000000 STACK 000000000012FC18 AddrReturn 0000000000000000
*** 148 called from 0000000000000000 STACK 000000000012FC20 AddrReturn 0000000000000000
*** 149 called from 0000000000000000 STACK 000000000012FC28 AddrReturn 0000000000000000
*** 150 called from 0000000000000000 STACK 000000000012FC30 AddrReturn 0000000000000000
*** 151 called from 0000000000000000 STACK 000000000012FC38 AddrReturn 0000000000000000
*** 152 called from 0000000000000000 STACK 000000000012FC40 AddrReturn 0000000000000000
*** 153 called from 0000000000000000 STACK 000000000012FC48 AddrReturn 0000000000000000
*** 154 called from 0000000000000000 STACK 000000000012FC50 AddrReturn 0000000000000000
*** 155 called from 0000000000000000 STACK 000000000012FC58 AddrReturn 0000000000000000
*** 156 called from 0000000000000000 STACK 000000000012FC60 AddrReturn 0000000000000000
*** 157 called from 0000000000000000 STACK 000000000012FC68 AddrReturn 0000000000000000
*** 158 called from 0000000000000000 STACK 000000000012FC70 AddrReturn 0000000000000000
*** 159 called from 0000000000000000 STACK 000000000012FC78 AddrReturn 0000000000000000
*** 160 called from 0000000000000000 STACK 000000000012FC80 AddrReturn 0000000000000000
*** 161 called from 0000000000000000 STACK 000000000012FC88 AddrReturn 0000000000000000
*** 162 called from 0000000000000000 STACK 000000000012FC90 AddrReturn 0000000000000000
*** 163 called from 0000000000000000 STACK 000000000012FC98 AddrReturn 0000000000000000
*** 164 called from 0000000000000000 STACK 000000000012FCA0 AddrReturn 0000000000000000
*** 165 called from 0000000000000000 STACK 000000000012FCA8 AddrReturn 0000000000000000
*** 166 called from 0000000000000000 STACK 000000000012FCB0 AddrReturn 0000000000000000
*** 167 called from 0000000000000000 STACK 000000000012FCB8 AddrReturn 0000000000000000
*** 168 called from 0000000000000000 STACK 000000000012FCC0 AddrReturn CCCCCCCCCCCCCCCC
*** 169 called from CCCCCCCCCCCCCCCC STACK 000000000012FCC8 AddrReturn CCCCCCCCCCCCCCCC
*** 170 called from CCCCCCCCCCCCCCCC STACK 000000000012FCD0 AddrReturn CCCCCCCCCCCCCCCC
*** 171 called from CCCCCCCCCCCCCCCC STACK 000000000012FCD8 AddrReturn CCCCCCCCCCCCCCCC
*** 172 called from CCCCCCCCCCCCCCCC STACK 000000000012FCE0 AddrReturn CCCCCCCCCCCCCCCC
*** 173 called from CCCCCCCCCCCCCCCC STACK 000000000012FCE8 AddrReturn 0000000300000000
*** 174 called from 0000000300000000 STACK 000000000012FCF0 AddrReturn 0000000300000000
*** 175 called from 0000000300000000 STACK 000000000012FCF8 AddrReturn 0000000300000000
*** 176 called from 0000000300000000 STACK 000000000012FD00 AddrReturn 000000000012FCF0
*** 177 called from 000000000012FCF8 STACK 000000000012FD08 AddrReturn 0000000300000000
*** 178 called from 0000000300000000 STACK 000000000012FD10 AddrReturn 000000000012FD10
*** 179 called from 000000000012FD18 STACK 000000000012FD18 AddrReturn 0000000300000000
*** 180 called from 0000000300000000 STACK 000000000012FD20 AddrReturn 0000000000000000
*** 181 called from 0000000000000000 STACK 000000000012FD28 AddrReturn 0000000000000000
*** 182 called from 0000000000000000 STACK 000000000012FD30 AddrReturn 0000000000000000
*** 183 called from 0000000000000000 STACK 000000000012FD38 AddrReturn 0000000000000000
*** 184 called from 0000000000000000 STACK 000000000012FD40 AddrReturn 0000000000000000
*** 185 called from 0000000100000000 STACK 000000000012FD48 AddrReturn 0000000100000000
*** 186 called from 0000000000000000 STACK 000000000012FD50 AddrReturn 0000000000000000
*** 187 called from 0000000000000000 STACK 000000000012FD58 AddrReturn 0000000100000000
*** 188 called from 0000000100000000 STACK 000000000012FD60 AddrReturn 0000000000000000
*** 189 called from 0000000000000000 STACK 000000000012FD68 AddrReturn 0000000000000000
*** 190 called from 0000000000000000 STACK 000000000012FD70 AddrReturn 0000000000000000
*** 191 called from 0000000000000000 STACK 000000000012FD78 AddrReturn 0000000000000000
*** 192 called from 0000000000000000 STACK 000000000012FD80 AddrReturn 0000000000000000
*** 193 called from 0000000000000000 STACK 000000000012FD88 AddrReturn 0000000000000000
*** 194 called from 0000000000000000 STACK 000000000012FD90 AddrReturn 0000000000000000
*** 195 called from 0000000000000000 STACK 000000000012FD98 AddrReturn 0000000000000000
*** 196 called from 0000000000000000 STACK 000000000012FDA0 AddrReturn 0000000000000000
*** 197 called from 0000000000000000 STACK 000000000012FDA8 AddrReturn 0000000000000000
*** 198 called from 0000000000000000 STACK 000000000012FDB0 AddrReturn 0000000000000000
*** 199 called from 0000000000000000 STACK 000000000012FDB8 AddrReturn 0000000000000000
*** 200 called from 0000000000000000 STACK 000000000012FDC0 AddrReturn 0000000000000000
*** 201 called from 0000000000000000 STACK 000000000012FDC8 AddrReturn 0000000000000000
*** 202 called from 0000000000000000 STACK 000000000012FDD0 AddrReturn 0000000000000000
*** 203 called from 0000000000000000 STACK 000000000012FDD8 AddrReturn 0000000000000000
*** 204 called from 0000000000000000 STACK 000000000012FDE0 AddrReturn 0000000000000000
*** 205 called from 0000000000000000 STACK 000000000012FDE8 AddrReturn CCCCCCCCCCCCCCCC
*** 206 called from CCCCCCCCCCCCCCCC STACK 000000000012FDF0 AddrReturn 000000CECCCCCCCC
*** 207 called from 000000CFCCCCCCCC STACK 000000000012FDF8 AddrReturn CCCCCCCC00000001
*** 208 called from CCCCCCCC00000001 STACK 000000000012FE00 AddrReturn FFFFFFFFFFFFFFFE
*** 209 called from FFFFFFFFFFFFFFFE STACK 000000000012FE08 AddrReturn CCCCCCCCCCCCCCCC
*** 210 called from CCCCCCCCCCCCCCCC STACK 000000000012FE10 AddrReturn 000000000012FE40
*** 211 called from 000000000012FE40 STACK 000000000012FE18 AddrReturn 000000014000122F
*** 212 called from 000000014000122F STACK 000000000012FE20 AddrReturn CCCCCCCCCCCCCCCC
*** 213 called from CCCCCCCCCCCCCCCC STACK 000000000012FE28 AddrReturn CCCCCCCCCCCCCCCC
*** 214 called from CCCCCCCCCCCCCCCC STACK 000000000012FE30 AddrReturn CCCCCCCCCCCCCCCC
*** 215 called from CCCCCCCCCCCCCCCC STACK 000000000012FE38 AddrReturn CCCCCCCCCCCCCCCC
*** 216 called from CCCCCCCCCCCCCCCC STACK 000000000012FE40 AddrReturn 000000000012FE70
*** 217 called from 000000000012FE70 STACK 000000000012FE48 AddrReturn 000000014000125F
*** 218 called from 000000014000125F STACK 000000000012FE50 AddrReturn CCCCCCCCCCCCCCCC
*** 219 called from CCCCCCCCCCCCCCCC STACK 000000000012FE58 AddrReturn CCCCCCCCCCCCCCCC
*** 220 called from CCCCCCCCCCCCCCCC STACK 000000000012FE60 AddrReturn CCCCCCCCCCCCCCCC
*** 221 called from CCCCCCCCCCCCCCCC STACK 000000000012FE68 AddrReturn CCCCCCCCCCCCCCCC
*** 222 called from CCCCCCCCCCCCCCCC STACK 000000000012FE70 AddrReturn 000000000012FEA0
*** 223 called from 000000000012FEA0 STACK 000000000012FE78 AddrReturn 000000014000128F
*** 224 called from 000000014000128F STACK 000000000012FE80 AddrReturn CCCCCCCCCCCCCCCC
*** 225 called from CCCCCCCCCCCCCCCC STACK 000000000012FE88 AddrReturn CCCCCCCCCCCCCCCC
*** 226 called from CCCCCCCCCCCCCCCC STACK 000000000012FE90 AddrReturn CCCCCCCCCCCCCCCC
*** 227 called from CCCCCCCCCCCCCCCC STACK 000000000012FE98 AddrReturn CCCCCCCCCCCCCCCC
*** 228 called from CCCCCCCCCCCCCCCC STACK 000000000012FEA0 AddrReturn 000000000012FED0
*** 229 called from 000000000012FED0 STACK 000000000012FEA8 AddrReturn 00000001400012CB
*** 230 called from 00000001400012CB STACK 000000000012FEB0 AddrReturn CCCCCCCCCCCCCCCC
*** 231 called from CCCCCCCCCCCCCCCC STACK 000000000012FEB8 AddrReturn CCCCCCCCCCCCCCCC
*** 232 called from CCCCCCCCCCCCCCCC STACK 000000000012FEC0 AddrReturn CCCCCCCCCCCCCCCC
*** 233 called from CCCCCCCCCCCCCCCC STACK 000000000012FEC8 AddrReturn CCCCCCCCCCCCCCCC
*** 234 called from CCCCCCCCCCCCCCCC STACK 000000000012FED0 AddrReturn 0000000000000000
*** 235 called from 0000000000000000 STACK 000000000012FED8 AddrReturn 000000014000190C
*** 236 called from 000000014000190C STACK 000000000012FEE0 AddrReturn 0000000100000001
*** 237 called from 0000000100000001 STACK 000000000012FEE8 AddrReturn 0000000000454B50
*** 238 called from 0000000000454B50 STACK 000000000012FEF0 AddrReturn 0000000000000000
*** 23
我终于找到了使用Windows函数CaptureStackBackTrace()
在x64中记录堆栈帧的可靠方法。由于我不想更新我的SDK,因此我通过GetProcAddress(LoadLibrary());
typedef USHORT (WINAPI *CaptureStackBackTraceType)(__in ULONG, __in ULONG, __out PVOID*, __out_opt PULONG);
CaptureStackBackTraceType func = (CaptureStackBackTraceType)(GetProcAddress(LoadLibrary("kernel32.dll"), "RtlCaptureStackBackTrace"));
if(func == NULL)
return; // WOE 29.SEP.2010
// Quote from Microsoft Documentation:
// ## Windows Server 2003 and Windows XP:
// ## The sum of the FramesToSkip and FramesToCapture parameters must be less than 63.
const int kMaxCallers = 62;
void* callers[kMaxCallers];
int count = (func)(0, kMaxCallers, callers, NULL);
for(i = 0; i < count; i++)
printf(TraceFile, "*** %d called from %016I64LX
", i, callers[i]);
拆卸RtlCaptureStackBackTrace()时,我注意到传递给RtlCaptureStackBackTrace()的最大值应为:framesToSkip + framesToCapture + 1应该小于64。否则返回0,并且没有其他错误代码。
[使用StackWalk64
时,您要遍历线程的整个堆栈,不管是否有有效数据。到达寄信人地址0后,您应该终止步行,例如:
for (ULONG Frame = 0; ; Frame++)
{
if (FALSE == StackWalk64(...))
{
printf("Stack walk failed!
");
break;
}
if (stackFrame.AddrPC.Offset == 0)
{
printf("Stack walk complete!
");
break;
}
do_something();
}
发现带有“ CaptureStackBackTraceType”的简短版本非常有用!
然后解析使用“ callers []”的函数名称SymFromAddr(),SymInitialize(),主要是Pedro Reis的版本
最后根据function to mangle/demangle functions
注意:GNU demangler函数abi::__cxa_demangle()
需要单个下划线前缀
我们仅在这里使用小型转储。您可以生成一个精简的堆栈,其中仅包含堆栈信息,并稍后从一个不错的调试器中转出堆栈跟踪。
它不能直接解决您的问题,但我认为它将为您提供更好的验尸报告机制。
在试用版3中,您可能使用了CaptureStackBackTrace()错误。根据文档,在Windows XP和Windows Server 2003上,第一和第二个参数的总和必须小于63,但是,在您的情况下,总和应为128。
http://msdn.microsoft.com/en-us/library/windows/desktop/bb204633%28v=vs.85%29.aspx
对于vs2008 x64:基于https://msdn.microsoft.com/en-us/library/windows/desktop/bb204633%28v=vs.85%29.aspx和RED SOFT ADAIR:
#if defined DEBUG_SAMPLES_MANAGEMENT
#include "DbgHelp.h"
#include <WinBase.h>
#pragma comment(lib, "Dbghelp.lib")
void printStack( void* sample_address, std::fstream& out )
{
typedef USHORT (WINAPI *CaptureStackBackTraceType)(__in ULONG, __in ULONG, __out PVOID*, __out_opt PULONG);
CaptureStackBackTraceType func = (CaptureStackBackTraceType)(GetProcAddress(LoadLibrary(L"kernel32.dll"), "RtlCaptureStackBackTrace"));
if(func == NULL)
return; // WOE 29.SEP.2010
// Quote from Microsoft Documentation:
// ## Windows Server 2003 and Windows XP:
// ## The sum of the FramesToSkip and FramesToCapture parameters must be less than 63.
const int kMaxCallers = 62;
void * callers_stack[ kMaxCallers ];
unsigned short frames;
SYMBOL_INFO * symbol;
HANDLE process;
process = GetCurrentProcess();
SymInitialize( process, NULL, TRUE );
frames = (func)( 0, kMaxCallers, callers_stack, NULL );
symbol = ( SYMBOL_INFO * )calloc( sizeof( SYMBOL_INFO ) + 256 * sizeof( char ), 1 );
symbol->MaxNameLen = 255;
symbol->SizeOfStruct = sizeof( SYMBOL_INFO );
out << "(" << sample_address << "): " << std::endl;
const unsigned short MAX_CALLERS_SHOWN = 6;
frames = frames < MAX_CALLERS_SHOWN? frames : MAX_CALLERS_SHOWN;
for( unsigned int i = 0; i < frames; i++ )
{
SymFromAddr( process, ( DWORD64 )( callers_stack[ i ] ), 0, symbol );
out << "*** " << i << ": " << callers_stack[i] << " " << symbol->Name << " - 0x" << symbol->Address << std::endl;
}
free( symbol );
}
#endif
这里叫:
#if defined DEBUG_SAMPLES_MANAGEMENT
if(owner_ != 0)
{
std::fstream& out = owner_->get_debug_file();
printStack( this, out );
}
#endif
观看,不知道是否相关:...使用汇编代码汇编代码可以直接移植到AMD64和64位Windows上,出于性能方面的考虑,值得付出努力!例如,您可以利用新的64位通用寄存器(r8-r15),新的浮点和128位SSE / SSE2 /浮点寄存器(xmm8-xmm15)。 ABI(应用程序二进制接口)规范中的However, there are new 64-bit stack frames and calling conventions you should learn about。...
技巧是在StackWalk64
中返回0时停止调用stk.AddrReturn.Offset
。这意味着堆栈上没有更多的帧。如果stk.AddrReturn.Offset
不为零,则可以将该值用作返回地址。
如果在此之后继续调用StackWalk64
,我的猜测是它将尝试将内存位置中的任何内容解释为堆栈,并且将返回不可预测的数据。
StackWalk64是正确的选择,第一个呼叫将为您提供呼叫者的地址。
您的问题可能是,在发行版中,您进行了大量内联。寄信人地址可能不是您所期望的。
编辑:您只需要设置AddrPC和AddrFrame。只需确保您的rbp和rip是与您的被调用者上下文相对应的即可。
关于第一个问题:在此发行版中禁用“忽略堆栈框架”,并且“平凡的”堆栈跟踪代码将起作用。
关于RtlCaptureStackBackTrace,我在32位Windows上注意到的一件事是,如果将太大的数字传递给FramesToCapture,它将失败。实验上,我已将61标识为最大值,无缘无故可以理解!
不确定x64中是否相同,但这可能解释了为什么您没有得到任何信息。
以上是关于如何使用Windows x64记录堆栈帧的主要内容,如果未能解决你的问题,请参考以下文章
在恢复C#异步方法时,System.Diagnostics.StackTrace中缺少Visual Studio 2017调用堆栈中可见的堆栈帧