Jump to content
  • Advertisement
Sign in to follow this  
mat buckland

Call Stack

This topic is 4085 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Can anyone tell me how to write the call stack to a file if an assert triggers? (we need this so we can examine problems occurring on our play-testers' machines)

Share this post


Link to post
Share on other sites
Advertisement
Large chunk of code from my memory manager code:

void PMemory::DetermineCaller(Allocation* pAllocation)
{
// Get the current thread context
DWORD dwMachineType;
CONTEXT theContext;
memset(&theContext, 0, sizeof(theContext));
RtlCaptureContext(&theContext);

// Init the stack frame for this function
STACKFRAME64 theStackFrame;
memset(&theStackFrame, 0, sizeof(theStackFrame));
#ifdef _M_IX86
dwMachineType = IMAGE_FILE_MACHINE_I386;
theStackFrame.AddrPC.Offset = theContext.Eip;
theStackFrame.AddrPC.Mode = AddrModeFlat;
theStackFrame.AddrFrame.Offset = theContext.Ebp;
theStackFrame.AddrFrame.Mode = AddrModeFlat;
theStackFrame.AddrStack.Offset = theContext.Esp;
theStackFrame.AddrStack.Mode = AddrModeFlat;
#elif _M_X64
dwMachineType = IMAGE_FILE_MACHINE_AMD64;
theStackFrame.AddrPC.Offset = theContext.Rip;
theStackFrame.AddrPC.Mode = AddrModeFlat;
theStackFrame.AddrFrame.Offset = theContext.Rsp;
theStackFrame.AddrFrame.Mode = AddrModeFlat;
theStackFrame.AddrStack.Offset = theContext.Rsp;
theStackFrame.AddrStack.Mode = AddrModeFlat;
#elif _M_IA64
dwMachineType = IMAGE_FILE_MACHINE_IA64;
theStackFrame.AddrPC.Offset = theContext.StIIP;
theStackFrame.AddrPC.Mode = AddrModeFlat;
theStackFrame.AddrFrame.Offset = theContext.IntSp;
theStackFrame.AddrFrame.Mode = AddrModeFlat;
theStackFrame.AddrBStore.Offset = theContext.RsBSP;
theStackFrame.AddrBStore.Mode = AddrModeFlat;
theStackFrame.AddrStack.Offset = theContext.IntSp;
theStackFrame.AddrStack.Mode = AddrModeFlat;
#else
# error "Platform not supported!"
#endif

// Walk up the stack to the caller
for(int i=0; i<s_nFramesToWalk; ++i)
{
if(!StackWalk64(dwMachineType, GetCurrentProcess(), GetCurrentThread(), &theStackFrame,
&theContext, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
{
strcpy(pAllocation->szFile, "??");
pAllocation->nLine = 0;
return;
}
}

// Get file/line number
{
IMAGEHLP_LINE64 theLine;
DWORD dwDisplacement;
memset(&theLine, 0, sizeof(theLine));
theLine.SizeOfStruct = sizeof(theLine);
if(!SymGetLineFromAddr64(GetCurrentProcess(), theStackFrame.AddrPC.Offset, &dwDisplacement, &theLine))
{
strcpy(pAllocation->szFile, "??");
pAllocation->nLine = 0;
strcpy(pAllocation->szFunc, "??");
}
else
{
const char* pszFile = strrchr(theLine.FileName, '\\');
if(!pszFile) pszFile = theLine.FileName;
else ++pszFile;
strncpy(pAllocation->szFile, pszFile, Allocation::cnBufferSize);
pAllocation->nLine = theLine.LineNumber;
}
}

// Get function name
{
unsigned char byBuffer[sizeof(IMAGEHLP_SYMBOL64) + Allocation::cnBufferSize];
IMAGEHLP_SYMBOL64* pSymbol = (IMAGEHLP_SYMBOL64*)byBuffer;
DWORD64 dwDisplacement;
memset(pSymbol, 0, sizeof(IMAGEHLP_SYMBOL64) + Allocation::cnBufferSize);
pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
pSymbol->MaxNameLength = Allocation::cnBufferSize;
if(!SymGetSymFromAddr64(GetCurrentProcess(), theStackFrame.AddrPC.Offset, &dwDisplacement, pSymbol))
strcpy(pAllocation->szFunc, "??");
else
{
pSymbol->Name[Allocation::cnBufferSize-1] = '\0';
strcpy(pAllocation->szFunc, pSymbol->Name);
}
}
}


Obviously the symbol names won't exist in a release build, but you can still use the stack walking mechanism to walk the callstack and record return addresses, which you can then deal with on a dev machine. See StackWalk64 for more information.

Share this post


Link to post
Share on other sites
Thanks Steve,

Where is RtlCaptureContext on your machine? MSDN tells me it's in <winNT.h>

http://msdn2.microsoft.com/en-us/library/ms680591.aspx

but it's not anywhere to be found on my machine...

Are you using MSVC7?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!