如何使用Windows x64记录堆栈帧

我正在使用带有Win32的Stackdumps,将所有返回地址写入我的日志文件。 我稍后将这些与mapfile匹配(参见我的文章[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)\n", 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\n", Frame, (ULONG64)stk.AddrPC.Offset, (ULONG64)stk.AddrStack.Offset, (ULONG64)stk.AddrFrame.Offset); if(! result) break; } 

这不仅会转储返回地址,还会转储整个堆栈。 我使用这种方法在我的日志文件中收到大约1000行。 我可以使用它,但我必须通过行搜索,堆栈的一些数据恰好是一个有效的代码地址。

试验3:使用Backtrace

 static USHORT (WINAPI *s_pfnCaptureStackBackTrace)(ULONG, ULONG, PVOID*, PULONG) = 0; if (s_pfnCaptureStackBackTrace == 0) { const HMODULE hNtDll = ::GetModuleHandle("ntdll.dll"); reinterpret_cast(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\n", ndx, (ULONG64)myFrames[ndx]); 

结果没有可用的信息。

有没有人在x64中实现这样的堆栈遍历,只能写出堆栈中的返回地址? 我已经看过[StackTrace64] [2],[StackWalker] [3]和其他方法。 他们要么不编译,要么太复杂。 它基本上是一个简单的任务!

示例StackDump64.cpp

 #include  #include  #include  #include  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\n", 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\n", i, callers[i]); 

这没有问题。

我们在这里专门使用minidumps。 您可以生成一个仅包含堆栈信息的精简版,并在稍后从一个体面的调试器中转储堆栈跟踪。

它不能直接解决您的问题,但我认为它将为您提供更好的事后报告机制。

在试用版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  #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(应用程序二进制接口)规范中了解新的64位堆栈帧和调用约定 。

诀窍是在stk.AddrReturn.Offset返回0时停止调用StackWalk64 。 这意味着堆栈上不再有帧。 如果stk.AddrReturn.Offset不为零,则可以将该值用作返回地址。

如果在此之后继续调用StackWalk64 ,我的猜测是它会尝试将内存位置中的任何内容解释为堆栈并返回不可预测的数据。

StackWalk64 is the right choice, the first call will give you the caller’s address.

Your problem might be that in release you have a lot of inlining going on. The return address may not be what you expect.

edit : you only need to set AddrPC and AddrFrame. Just make sure that your rbp and rip are the ones corresponding to your callee context.

Regarding the first issue: disable “Omit stack frames” in thre release version, and the “trivial” stack tracing code will work.

Regarding RtlCaptureStackBackTrace, one thing I’ve noticed on 32-bit Windows is that it fails if you pass too large a number into it for FramesToCapture. Experimentally I’ve identified 61 as the maximum value, for no reason that I can fathom!

Not sure if it’s the same in x64, but that might explain why you’re getting no info out.

Disassembling RtlCaptureStackBackTrace() I noticed that maximum value passed to RtlCaptureStackBackTrace() should be: framesToSkip+framesToCapture+1 should be less than 64. otherwise it returns 0 and there is no other error codes.

When using StackWalk64 you are iterating through the thread’s entire stack whether there is valid data or not. Once you hit a return address of 0 you should terminate the walk, like so:

 for (ULONG Frame = 0; ; Frame++) { if (FALSE == StackWalk64(...)) { printf("Stack walk failed!\n"); break; } if (stackFrame.AddrPC.Offset == 0) { printf("Stack walk complete!\n"); break; } do_something(); }