web-dev-qa-db-ja.com

Windowsx64でスタックフレームをログに記録する方法

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)\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:バックトレースの使用

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\n", 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\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
25
RED SOFT ADAIR

私はついに、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]);
18
RED SOFT ADAIR

トライアル3では、CaptureStackBackTrace()を誤って使用している可能性があります。ドキュメントによると、Windows XPおよびWindowsServer 2003では、最初と2番目のパラメーターの合計は63未満である必要がありますが、この場合、合計は128になります。

http://msdn.Microsoft.com/en-us/library/windows/desktop/bb204633%28v=vs.85%29.aspx

1
MikeW

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
1
Pedro Reis

ここではミニダンプのみを使用します。スタック情報だけを含むストリップダウンされたものを生成し、後で適切なデバッガーからスタックトレースをダンプすることができます。

それはあなたの問題を直接解決するわけではありませんが、それはあなたにはるかに優れた事後報告メカニズムを提供すると思います。

1
MSN

StackWalk64を使用する場合、有効なデータがあるかどうかに関係なく、スレッドのスタック全体を反復処理します。リターンアドレス0に到達したら、次のようにウォークを終了する必要があります。

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();
}
0
Ben Russell

StackWalk64は正しい選択です。最初の呼び出しで、発信者のアドレスがわかります。

あなたの問題は、リリースで多くのインライン化が行われていることかもしれません。差出人住所は、期待したものとは異なる場合があります。

編集:AddrPCとAddrFrameを設定するだけで済みます。 rbpとripが呼び出し先のコンテキストに対応するものであることを確認してください。

0
Edouard A.

「CaptureStackBackTraceType」の短いバージョンが本当に便利であることがわかりました。

次に、 SymFromAddr()SymInitialize() を使用して、「callers []」の関数名を解決しました。これは、主にPedroReisのバージョンです。

そして最後に 関数をマングル/デマングルする関数 に従って関数シグネチャをデマングルしました

注:GNU demangler function abi::__cxa_demangle()は単一のアンダースコアプレフィックスを想定しています

0
Sam Ginrich

RtlCaptureStackBackTrace()の分解RtlCaptureStackBackTrace()に渡される最大値は次のようになります。framesToSkip+ framesToCapture + 1は64未満である必要があります。それ以外の場合は0を返し、他のエラーコードはありません。

0
KeRneL

秘訣は、StackWalk64で0が返されたときにstk.AddrReturn.Offsetの呼び出しを停止することです。これは、スタックにこれ以上フレームがないことを意味します。 stk.AddrReturn.Offsetがゼロ以外の場合、その値をリターンアドレスとして使用できます。

この後もStackWalk64を呼び出し続けると、メモリ位置にあるものはすべてスタックであると解釈しようとし、予測できないデータが返されると思います。

0
staffan

RtlCaptureStackBackTraceに関して、32ビットWindowsで気付いたのは、FramesToCaptureに対して大きすぎる数値を渡すと失敗することです。実験的に、61を最大値として特定しましたが、理解できる理由はありません。

X64でも同じかどうかはわかりませんが、情報が得られない理由を説明している可能性があります。

0
Sam Deane

最初の問題について:リリースバージョンで「スタックフレームの省略」を無効にすると、「簡単な」スタックトレースコードが機能します。

0
c2j2

これを見てください、それが関連しているかどうかはわかりません:
.。
アセンブリコードの操作アセンブリコードは、AMD64および64ビットWindowsに簡単に移植でき、パフォーマンス上の理由から努力する価値があります。たとえば、新しい64ビット汎用レジスタ(r8-r15)、および新しい浮動小数点レジスタと128ビットSSE/SSE2 /浮動小数点レジスタ(xmm8-xmm15)を利用できます。 ただし、新しい64ビットスタックフレームと呼び出し規約について学ぶ必要があります ABI(アプリケーションバイナリインターフェイス)仕様。
.。

0
lsalamon