#include "StackTrace.h"
#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
#include "DbgHelp.h"
#include <WinBase.h>
#pragma comment(lib, "Dbghelp.lib")
void PrintStackTrace()
{
HANDLE process = GetCurrentProcess();
SymInitialize(process, NULL, TRUE);
void* stack[60];
unsigned short frames = CaptureStackBackTrace(0, 60, stack, NULL);
SYMBOL_INFO *symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1);
symbol->MaxNameLen = 255;
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
for(int i = 0; i < frames; i++)
{
SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol);
printf("%i: %016I64LX %s - 0x%0X\n", frames - i - 1, stack[i], symbol->Name, symbol->Address);
}
free(symbol);
}
#else
#include <unistd.h>
#include <execinfo.h>
#include <cxxabi.h>
char* SplitStringNext(char* str, char ch)
{
if (!str)
return 0;
int i = 0;
while (str[i] && str[i] != ch)
i++;
if (!str[i])
return 0;
str[i] = 0;
return &str[i + 1];
}
void PrintStackTrace()
{
#ifdef USE_PSTACK
if (FILE* f = popen(std::string("pstack " + std::to_string(getpid()) + " | c++filt").c_str(), "r"))
{
char ch;
while (fread(&ch, 1, 1, f) > 0)
std::cout << ch;
pclose(f);
}
#else
void *array[128];
int size = backtrace(array, 128);
char** messages = backtrace_symbols(array, size);
for (int i = 0; i < size && messages != NULL; ++i)
{
// messages[i] looks something like this: "./test(_ZN1DC1Ev+0x18) [0x415974]"
char *progName = messages[i];
char *funcName = SplitStringNext(progName,'(');
char *offsetStr = SplitStringNext(funcName,'+');
char *addrStr = SplitStringNext(SplitStringNext(offsetStr, ')'), '[');
char *endStr = SplitStringNext(addrStr,']');
fprintf(stderr, "[bt]: (%d) %s [%s] %s offset: %s \n", i, progName, addrStr, abi::__cxa_demangle(funcName, 0, 0, 0), offsetStr );
}
free(messages);
#endif
}
#endif