2011-12-04 1 views
0

Lorsque j'essaie d'obtenir la pile d'appel d'un thread d'un processus, je reçois toujours une seule et même image, bien qu'elle en ait certainement plus (au moins 5 images).StackWalk64() renvoie une seule image

StackWalk64() réussit toujours au premier appel - retour d'un cadre avec:

AddrPC.Offset = 18446744072850558156 

Mais, tout de suite au deuxième appel échoue avec l'identifiant d'erreur 998-ERROR_NOACCESS (il se pourrait que cette erreur n'est pas à cause de cet appel, comme dit MSDN). En outre, essayer de résoudre cette adresse dans son nom de symbole avec SymFromAddr() échoue avec l'erreur 126-ERROR_MOD_NOT_FOUND (après l'appel SymInitialize réussi (m_processHandler, NULL, TRUE)).

Voici le code:

#ifdef _M_IX86 
    // 
    // Disable global optimization and ignore /GS waning caused by 
    // inline assembly. 
    // 
    #pragma optimize("g", off) 
    #pragma warning(push) 
    #pragma warning(disable : 4748) 
#endif 

bool EchoProfiler::getThreadStackTrace(__in HANDLE h_thread, __out vector<DWORD64> &framesVec) 
{ 
CONTEXT threadContext; 
if (GetThreadContext(h_thread, &threadContext) == 0) 
{ 
    cout << "Error: GetThreadContext() failed with error ID " << GetLastError() << endl; 
    return false; 
} 

//initialize stack frame 
DWORD MachineType; 
STACKFRAME64 StackFrame; 
ZeroMemory(&StackFrame, sizeof(STACKFRAME64)); 

MachineType     = IMAGE_FILE_MACHINE_I386; 
StackFrame.AddrPC.Offset = threadContext.Eip; 
StackFrame.AddrPC.Mode  = AddrModeFlat; 
StackFrame.AddrFrame.Offset = threadContext.Ebp; 
StackFrame.AddrFrame.Mode = AddrModeFlat; 
StackFrame.AddrStack.Offset = threadContext.Esp; 
StackFrame.AddrStack.Mode = AddrModeFlat; 

PVOID contextRec = (MachineType == IMAGE_FILE_MACHINE_I386) ? NULL : &threadContext; 
int i=0; 
// enumerate all the frames in the stack 
for (i=1 ; ; i++) 
{ 
    if (StackWalk64(MachineType, targetProcessHandler, h_thread, &StackFrame, 
     contextRec, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL) == false) 
    { 
     // in case it failed or we have finished walking the stack. 
     cout << "Error: StackWalk64() failed with error ID " << GetLastError() << endl; 
     i--; 
     break; 
     // return false; 
    } 

    if (StackFrame.AddrPC.Offset != 0) 
    { 
     // Valid frame. 
     cout << "Frame #" << i << " address - " << StackFrame.AddrPC.Offset << endl; 
     framesVec.push_back(StackFrame.AddrPC.Offset); 
    } 
    else 
    { 
     // Base reached. 
     break; 
    } 
} 

//cout << "StackWalk64 found " << i << " stack frames:" << endl; 
//i = 1; 
//for (FramesConstItr itr=framesVec.begin() ; itr != framesVec.end() ; itr++ , i++) 
// cout << i << " - " << *itr << endl; 

return true; 
} 

#ifdef _M_IX86 
    #pragma warning(pop) 
    #pragma optimize("g", on) 
#endif 

ce qui pourrait-il être?

+0

Ce qui est targetProcessHandler et comment est-il initialisé? –

+0

Initialisé avec 'HANDLE targetProcessHandler = OpenProcess (PROCESS_ALL_ACCESS, false, pID)' –

Répondre

1

Solution:

J'ai raté la partie a déclaré que la structure de contexte doit être initialisé correctement. Ajout du résolu mon problème suivant:

memset(&threadContext, 0, sizeof(CONTEXT)); 
threadContext.ContextFlags = CONTEXT_FULL; 

Merci

+0

Pourquoi désactiver l'optimisation ici, Hagay? On dirait que vous avez parfaitement raison de le faire, mais pourquoi, est-ce nécessaire? Je reçois une pile incorrecte au cas où je ne désactiverais pas l'optimisation dans mon application. Je vois moins d'adresses de fonction dans la sortie de mon application d'imprimante de pile. Avez-vous une idée de ce que peut être la cause? –