?
Solved

Why can't I get a full call stack

Posted on 2005-04-13
3
Medium Priority
?
1,565 Views
Last Modified: 2013-11-20
Hello,

I'm trying to get a call stack in my application (Visual C++ 6.0 with MFC, running on Windows XP SP2). I'm using StackWalk function, but I always get only the following stack:

ntdll!0x7C90EB94 : KiFastSystemCallRet
dbghelp!0x03030A90 : SymFunctionTableAccess

The question is: how to get full call stack on the current thread, why does it stop on SymFunctionTableAccess?

Here's my code:

      TCHAR          symInfo[BUFFERSIZE] = _T("?");
      TCHAR          srcInfo[BUFFERSIZE] = _T("?");
      CString strTemp, strMessage;
      DWORD    symOptions = SymGetOptions();
      symOptions |= SYMOPT_LOAD_LINES | SYMOPT_DEBUG;
      symOptions &= ~SYMOPT_UNDNAME;
      SymSetOptions(symOptions);
      SymInitialize(GetCurrentProcess(), "c:\\mysymbols", TRUE);

      CONTEXT        context;
      ::ZeroMemory(&context, sizeof(context));
      context.ContextFlags = CONTEXT_FULL;
      HANDLE hThread = GetCurrentThread();
      HANDLE hProcess = GetCurrentProcess();
      if (!GetThreadContext(hThread, &context))
            return;
      STACKFRAME callStack;
      ::ZeroMemory(&callStack, sizeof(callStack));
      callStack.AddrPC.Offset    = context.Eip;
      callStack.AddrStack.Offset = context.Esp;
      callStack.AddrFrame.Offset = context.Ebp;
      callStack.AddrPC.Mode      = AddrModeFlat;
      callStack.AddrStack.Mode   = AddrModeFlat;
      callStack.AddrFrame.Mode   = AddrModeFlat;
      for( ULONG index = 0; ; index++ )
      {
            if (!StackWalk(
                  IMAGE_FILE_MACHINE_I386,
                  hProcess,
                  hThread,
                  &callStack,
                  NULL,
                  NULL,
                  SymFunctionTableAccess,
                  SymGetModuleBase,
                  NULL))
                  break;
      
            GetFunctionInfoFromAddresses(callStack.AddrPC.Offset, callStack.AddrFrame.Offset, symInfo);
            GetSourceInfoFromAddress(callStack.AddrPC.Offset, srcInfo);

            strTemp.Format(_T("     %s : %s\n"), srcInfo, symInfo);
            strMessage += strTemp;
      }
      AfxMessageBox(strMessage);
0
Comment
Question by:Cezariusz
3 Comments
 
LVL 16

Expert Comment

by:nonubik
ID: 13770435
If you want to make a call stak crash reporter you mau want to check http://msdn.microsoft.com/msdnmag/issues/02/03/hood/default.aspx
0
 
LVL 86

Accepted Solution

by:
jkr earned 2000 total points
ID: 13772115
>>how to get full call stack on the current thread, why does it stop on SymFunctionTableAccess?

Because the thread is still running. You cannot obtain a valid CONTEXT record from a thread that is not in 'suspended' state. See http://msdn.microsoft.com/library/en-us/debug/base/getthreadcontext.asp ("GetThreadContext"):

----------------------------->8--------------------------

You cannot get a valid context for a running thread. Use the SuspendThread function to suspend the thread before calling GetThreadContext.

If you call GetThreadContext for the current thread, the function returns successfully; however, the context returned is not valid.

----------------------------->8--------------------------

What you can do is

LONG WINAPI DisplayCallStack (LPVOID p)
{
    HANDLE hThread = (HANDLE) p;
    TCHAR          symInfo[BUFFERSIZE] = _T("?");
    TCHAR          srcInfo[BUFFERSIZE] = _T("?");
    CString strTemp, strMessage;
    DWORD    symOptions = SymGetOptions();
    symOptions |= SYMOPT_LOAD_LINES | SYMOPT_DEBUG;
    symOptions &= ~SYMOPT_UNDNAME;
    SymSetOptions(symOptions);
    SymInitialize(GetCurrentProcess(), "c:\\mysymbols", TRUE);

    SuspendThread(hThread);
    CONTEXT        context;
    ::ZeroMemory(&context, sizeof(context));
    context.ContextFlags = CONTEXT_FULL;
    HANDLE hProcess = GetCurrentProcess();
    if (!GetThreadContext(hThread, &context))
         return;
    STACKFRAME callStack;
    ::ZeroMemory(&callStack, sizeof(callStack));
    callStack.AddrPC.Offset    = context.Eip;
    callStack.AddrStack.Offset = context.Esp;
    callStack.AddrFrame.Offset = context.Ebp;
    callStack.AddrPC.Mode      = AddrModeFlat;
    callStack.AddrStack.Mode   = AddrModeFlat;
    callStack.AddrFrame.Mode   = AddrModeFlat;
    for( ULONG index = 0; ; index++ )
     {
         if (!StackWalk(
              IMAGE_FILE_MACHINE_I386,
              hProcess,
              hThread,
              &callStack,
              NULL,
               NULL,
              SymFunctionTableAccess,
              SymGetModuleBase,
              NULL))
              break;
   
          GetFunctionInfoFromAddresses(callStack.AddrPC.Offset, callStack.AddrFrame.Offset, symInfo);
         GetSourceInfoFromAddress(callStack.AddrPC.Offset, srcInfo);

         strTemp.Format(_T("     %s : %s\n"), srcInfo, symInfo);
         strMessage += strTemp;
    }
    AfxMessageBox(strMessage);

    ResumeThread(hThread);

return 0;
}

//...
DWORD dwTID;
CreateThread(NULL, 0, DisplayCallStack ,(LPVOID) GetCurrentThread(), 0 &dwTID);

0
 
LVL 2

Author Comment

by:Cezariusz
ID: 13813556
Thanks jkr, you've saved me days of work. I was trying to dump other threads, to use ToolHelp to create snapshot but no avail. You would save me another couple of hours not forgetting, that GetCurrentThread returns pseudo-handle, which has to be duplicated prior to passing to any other thread, because it always points to the current thread.
Anyway the worker thread is the solution to my problem, thanks again.
0

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: Dialogs (1) modal - maintaining the database. Continuing from the ninth article about sudoku.   You might have heard of modal and modeless dialogs.  Here with this Sudoku application will we use one of each type: a modal dialog …
If you use Adobe Reader X it is possible you can't open OLE PDF documents in the standard. The reason is the 'save box mode' in adobe reader X. Many people think the protected Mode of adobe reader x is only to stop the write access. But this fe…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Integration Management Part 2
Suggested Courses

862 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question