140 строки
4.3 KiB
C++
140 строки
4.3 KiB
C++
//
|
|
// <copyright file="DebugUtil.cpp" company="Microsoft">
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// </copyright>
|
|
//
|
|
// DebugUtil.cpp : Defines the debug util functions.
|
|
//
|
|
#ifndef _CRT_SECURE_NO_WARNINGS
|
|
#define _CRT_SECURE_NO_WARNINGS // "secure" CRT not available on all platforms --add this at the top of all CPP files that give "function or variable may be unsafe" warnings
|
|
#endif
|
|
|
|
#include "Basics.h"
|
|
#include "DebugUtil.h"
|
|
|
|
namespace Microsoft { namespace MSR { namespace CNTK {
|
|
|
|
using namespace std;
|
|
|
|
void DebugUtil::PrintCallStack()
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
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;
|
|
|
|
void* callStack[MAX_CALLERS];
|
|
unsigned short frames;
|
|
SYMBOL_INFO* symbolInfo;
|
|
HANDLE process;
|
|
|
|
process = GetCurrentProcess();
|
|
if (!SymInitialize(process, NULL, TRUE))
|
|
{
|
|
DWORD error = GetLastError();
|
|
std::cerr << "Failed to print CALL STACK! SymInitialize error : " << msra::strfun::utf8(FormatWin32Error(error)) << std::endl;
|
|
return;
|
|
}
|
|
|
|
frames = (func)(0, MAX_CALLERS, callStack, NULL);
|
|
symbolInfo = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO)+256 * sizeof(char), 1);
|
|
symbolInfo->MaxNameLen = 255;
|
|
symbolInfo->SizeOfStruct = sizeof(SYMBOL_INFO);
|
|
frames = min(frames, MAX_CALL_STACK_DEPTH);
|
|
|
|
std::cerr << std::endl << "[CALL STACK]" << std::endl;
|
|
|
|
for (unsigned int i = 1; i < frames; i++)
|
|
{
|
|
if (i == 1)
|
|
{
|
|
std::cerr << " >";
|
|
}
|
|
else
|
|
{
|
|
std::cerr << " -";
|
|
}
|
|
|
|
if (SymFromAddr(process, (DWORD64)(callStack[i]), 0, symbolInfo))
|
|
{
|
|
std::cerr << symbolInfo->Name << std::endl;
|
|
}
|
|
else
|
|
{
|
|
DWORD error = GetLastError();
|
|
std::cerr << callStack[i] << " (SymFromAddr error : " << msra::strfun::utf8(FormatWin32Error(error)) << ")" << std::endl;
|
|
}
|
|
}
|
|
|
|
std::cerr << std::endl;
|
|
|
|
free(symbolInfo);
|
|
|
|
SymCleanup(process);
|
|
#else
|
|
std::cerr << std::endl << "[CALL STACK]" << std::endl;
|
|
|
|
unsigned int MAX_NUM_FRAMES= 1024;
|
|
void* backtraceAddresses[MAX_NUM_FRAMES];
|
|
unsigned int numFrames = backtrace(backtraceAddresses, MAX_NUM_FRAMES);
|
|
char** symbolList = backtrace_symbols(backtraceAddresses, numFrames);
|
|
|
|
for (unsigned int i = 0; i < numFrames; i++)
|
|
{
|
|
char* beginName = NULL;
|
|
char* beginOffset = NULL;
|
|
char* endOffset = NULL;
|
|
|
|
// Find parentheses and +address offset surrounding the mangled name
|
|
for (char* p = symbolList[i]; *p; ++p)
|
|
{
|
|
if (*p == '(')
|
|
beginName = p;
|
|
else if (*p == '+')
|
|
beginOffset = p;
|
|
else if ((*p == ')') && (beginOffset || beginName))
|
|
endOffset = p;
|
|
}
|
|
|
|
if (beginName && endOffset && (beginName < endOffset))
|
|
{
|
|
*beginName++ = '\0';
|
|
*endOffset++ = '\0';
|
|
if (beginOffset)
|
|
*beginOffset++ = '\0';
|
|
|
|
// Mangled name is now in [beginName, beginOffset) and caller offset in [beginOffset, endOffset).
|
|
int status = 0;
|
|
unsigned int MAX_FUNCNAME_SIZE= 4096;
|
|
size_t funcNameSize = MAX_FUNCNAME_SIZE;
|
|
char funcName[MAX_FUNCNAME_SIZE];
|
|
char* ret = abi::__cxa_demangle(beginName, funcName, &funcNameSize, &status);
|
|
char* fName = beginName;
|
|
if (status == 0)
|
|
fName = ret;
|
|
|
|
if (beginOffset)
|
|
{
|
|
fprintf(stderr, " %-30s ( %-40s + %-6s) %s\n", symbolList[i], fName, beginOffset, endOffset);
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, " %-30s ( %-40s %-6s) %s\n", symbolList[i], fName, "", endOffset);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Couldn't parse the line. Print the whole line.
|
|
fprintf(stderr, " %-30s\n", symbolList[i]);
|
|
}
|
|
}
|
|
|
|
free(symbolList);
|
|
#endif
|
|
|
|
}
|
|
|
|
}}} |