Sign in to follow this  
mat buckland

Call Stack

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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this