2009-02-26 19 views
22

Sto usando Stackdumps con Win32, per scrivere tutti gli indirizzi di ritorno nel mio file di registro. Li abbino più tardi con un mapfile (vedi il mio articolo [Post Mortem Debugging] [1]).Come registrare frame stack con Windows x64

EDIT :: Problema risolto: vedere la mia risposta qui sotto.

Con Windows x64 non trovo un modo affidabile per scrivere solo gli indirizzi di ritorno nel file di registro. Ho provato diversi modi:

Trial 1: l'aritmetica dei puntatori:

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); 

    } 

Questo funziona bene nella versione di debug -, ma si blocca nella versione. Il valore di Context.Rdi non ha alcun valore utilizzabile lì. Ho controllato le differenze nelle impostazioni del compilatore (Visual Studio 2005). Non ho trovato nulla di sospetto.

Trial 2: Uso 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; 
} 

Questo non solo eseguire il dump dei indirizzi di ritorno, ma lo STACK TUTTO. Ricevo circa 1000 righe nel mio file di registro utilizzando questo approccio. Posso usare questo, ma devo cercare attraverso le linee e alcuni dati delle pile capita di essere un indirizzo di codice valido.

Prova 3: Utilizzo Backtrace

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]); 

Risultati in nessun informazioni utilizzabili.

Qualcuno ha implementato tale stack walk in x64 che scrive solo gli indirizzi di ritorno nello stack? Ho visto gli approcci [StackTrace64] [2], [StackWalker] [3] e altri. Non si compilano o sono troppo complicati. Fondamentalmente è un compito semplice!

Esempio 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(); 
} 

di eseguire questo esempio determina il contenuto del file di registro follwing:

*** 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 
+0

errore LNK2019: simbolo esterno non risolto __imp_StackWalk64 di riferimento nella funzione "void __cdecl WriteStackDump (void)" (? WriteStackDump @@ YAXXZ) –

+0

È necessario collegare "DbgHe lp.lib". Vedi http://msdn.microsoft.com/en-us/library/windows/desktop/ms680650%28v=vs.85%29.aspx –

risposta

16

ho finalmente trovato un modo affidabile per registrare i stack frame a 64, utilizzando la funzione CaptureStackBackTrace di Windows(). Poiché non volevo aggiornare il mio SDK, lo chiamo tramite 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]); 

Questo funziona senza problemi.

+0

Non sono sicuro del motivo per cui si carica direttamente Kernal32.dll, quando si può semplicemente includere un file di intestazione. Inoltre solitamente kernal32.dll viene sempre caricato comunque per un processo ... ma se vuoi minimizzare i file include, allora la tua soluzione funziona. –

+1

Se si guarda http://msdn.microsoft.com/en-us/library/ff552119%28VS.85%29.aspx, si vede che RtlCaptureStackBackTrace non esisteva prima di Windows XP. Se includessi il file di intestazione, la nostra applicazione semplicemente non funzionerebbe su Win2000. Usando questo approccio lo fa - anche se (come ho appena notato) si bloccherà chiamando il StackDump come non ho verificato func per NULL (FIXED that). –

+0

Ottengo questi errori durante l'esecuzione del codice: 'errore C2664: 'GetModuleHandleW': impossibile convertire il parametro 1 da 'const char [10]' a 'LPCWSTR' I tipi indicati non sono correlati; la conversione richiede reinterpret_cast, cast in stile C o cast di stile errore C2065: 'gApplSetup': identificatore non dichiarato errore C2228: left di '.TraceFile' deve avere classe/struct/union' –

0

Il trucco è quello di smettere di chiamare StackWalk64 quando ritorna 0 in stk.AddrReturn.Offset. Ciò significa che non ci sono più frame nello stack. Se stk.AddrReturn.Offset è diverso da zero, è possibile utilizzare tale valore come indirizzo di ritorno.

Se si continua a chiamare StackWalk64 dopo questo, la mia ipotesi è che proverà a interpretare qualsiasi cosa sia nelle posizioni di memoria come uno stack e restituirà dati imprevedibili.

+0

staffan, ho aggiunto un campione per te sopra.Se si compila e si esegue ciò, risulta nel file di registro che ho incluso anche. Il file di registro ha 2833 voci di stack. Dovrebbe avere solo una mano piena di. Usi parametri diversi? Che cosa sto facendo di sbagliato? –

+0

Aggiornato la mia risposta dopo aver provato la fonte. – staffan

+0

No, gli indirizzi di restituzione non si trovano nei primi frame restituiti da StackWalk64. Guarda l'ultima colonna del file di registro: Stampa stk.AddrReturn.Offset. Il terzo valore è "1" !, il valore # 4 è uguale a # 2 sebbene non ci sia alcuna recessione nel campione. –

0

Guarda questo, non so se è rilevante:
...
Operazioni con il codice Assembly codice Assembly è semplice da porta per AMD64 e Windows a 64 bit, e vale la pena per motivi di prestazioni ! Ad esempio, è possibile usufruire dei nuovi registri general purpose a 64 bit (r8-r15) e dei nuovi registri floating point e SSE/SSE2/floating point a 128 bit (xmm8-xmm15). However, there are new 64-bit stack frames and calling conventions you should learn about nelle specifiche ABI (interfaccia binaria dell'applicazione).
...

1

Utilizziamo i minidump esclusivamente qui. È possibile generare uno stripped down che include solo informazioni sullo stack e scaricare una traccia stack da un debugger decente in seguito.

Non risolve il problema direttamente, ma penso che vi fornirà una migliore meccanismo di segnalazione post-mortem.

0

StackWalk64 è la scelta giusta, la prima chiamata vi darà l'indirizzo del chiamante.

Il tuo problema potrebbe essere che in fase di rilascio hai un sacco di inlining in corso. L'indirizzo del mittente potrebbe non essere quello che ti aspetti.

edit: avete solo bisogno di impostare AddrPC e AddrFrame. Assicurati che il tuo rbp e rip siano quelli corrispondenti al tuo contesto di chiamata.

+0

Inlining non è il problema. Il codice in linea non si presenta con un frame dello stack. Solo le funzioni realmente "chiamate". Lo uso da anni con 32 bit. –

0

quanto riguarda il primo problema: disattivare "Omettere stack frame" in thre versione di rilascio, e il codice di traccia di stack "banale" funzionerà.

+1

Ho aggiunto/Oy- alle opzioni del compilatore, che dovrebbero mantenere i puntatori Frame anche con l'ottimizzazione. Purtroppo non funziona. Quando si utilizza Trial 1 (aritmetica del puntatore) la versione di rilascio continua a bloccarsi. –

0

Per quanto riguarda RtlCaptureStackBackTrace, una cosa che ho notato su Windows a 32 bit è che non riesce se si immette un numero troppo grande in FramesToCapture. Sperimentalmente ho identificato 61 come valore massimo, senza alcun motivo che riesca a capire!

Non sono sicuro se è lo stesso in x64, ma ciò potrebbe spiegare il motivo per cui non si ottengono informazioni.

-1

Smontaggio RtlCaptureStackBackTrace() ho notato che valore massimo passato a RtlCaptureStackBackTrace() dovrebbe essere: framesToSkip + framesToCapture + 1 deve essere inferiore a 64. altrimenti restituisce 0 e non c'è altri codici di errore.

+0

Come [documentato] (http://msdn.microsoft.com/en-us/library/windows/hardware/ff552119%28v=vs.85%29.aspx). – AndiDog

0

Quando si utilizza StackWalk64 stai iterando attraverso l'intero stack del thread se ci sono dati validi o meno. Una volta che si colpisce un indirizzo di ritorno di 0 si dovrebbe terminare la passeggiata, in questo modo:

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(); 
} 
1

Per VS2008 x64: Basato su https://msdn.microsoft.com/en-us/library/windows/desktop/bb204633%28v=vs.85%29.aspx e 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 

dice qui,

#if defined DEBUG_SAMPLES_MANAGEMENT 
     if(owner_ != 0) 
     { 
      std::fstream& out = owner_->get_debug_file(); 
      printStack(this, out); 
     } 
#endif 
Problemi correlati