Exemplo n.º 1
0
//==============================================================================
String SystemStats::getStackBacktrace()
{
    String result;

   #if JUCE_ANDROID || JUCE_MINGW
    jassertfalse; // sorry, not implemented yet!

   #elif JUCE_WINDOWS
    HANDLE process = GetCurrentProcess();
    SymInitialize (process, nullptr, TRUE);

    void* stack[128];
    int frames = (int) CaptureStackBackTrace (0, numElementsInArray (stack), stack, nullptr);

    HeapBlock<SYMBOL_INFO> symbol;
    symbol.calloc (sizeof (SYMBOL_INFO) + 256, 1);
    symbol->MaxNameLen = 255;
    symbol->SizeOfStruct = sizeof (SYMBOL_INFO);

    for (int i = 0; i < frames; ++i)
    {
        DWORD64 displacement = 0;

        if (SymFromAddr (process, (DWORD64) stack[i], &displacement, symbol))
        {
            result << i << ": ";

            IMAGEHLP_MODULE64 moduleInfo;
            zerostruct (moduleInfo);
            moduleInfo.SizeOfStruct = sizeof (moduleInfo);

            if (::SymGetModuleInfo64 (process, symbol->ModBase, &moduleInfo))
                result << moduleInfo.ModuleName << ": ";

            result << symbol->Name << " + 0x" << String::toHexString ((int64) displacement) << newLine;
        }
    }

   #else
    void* stack[128];
    int frames = backtrace (stack, numElementsInArray (stack));
    char** frameStrings = backtrace_symbols (stack, frames);

    for (int i = 0; i < frames; ++i)
        result << frameStrings[i] << newLine;

    ::free (frameStrings);
   #endif

    return result;
}
Exemplo n.º 2
0
    void print_backtrace(char* out, int len, int max_depth)
    {
        typedef USHORT (*RtlCaptureStackBackTrace_t)(
            __in ULONG FramesToSkip,
            __in ULONG FramesToCapture,
            __out PVOID *BackTrace,
            __out_opt PULONG BackTraceHash);

        static RtlCaptureStackBackTrace_t RtlCaptureStackBackTrace = 0;

        if (RtlCaptureStackBackTrace == 0)
        {
            // we don't actually have to free this library, everyone has it loaded
            HMODULE lib = LoadLibrary(TEXT("kernel32.dll"));
            RtlCaptureStackBackTrace = (RtlCaptureStackBackTrace_t)GetProcAddress(lib, "RtlCaptureStackBackTrace");
            if (RtlCaptureStackBackTrace == 0)
            {
                out[0] = 0;
                return;
            }
        }

        int i;
        void* stack[50];
        int size = CaptureStackBackTrace(0, 50, stack, 0);

        SYMBOL_INFO* symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR), 1);
        symbol->MaxNameLen = MAX_SYM_NAME;
        symbol->SizeOfStruct = sizeof(SYMBOL_INFO);

        HANDLE p = GetCurrentProcess();
        static bool sym_initialized = false;
        if (!sym_initialized)
        {
            sym_initialized = true;
            SymInitialize(p, NULL, true);
        }
        for (i = 0; i < size && len > 0; ++i)
        {
            int ret;
            if (SymFromAddr(p, uintptr_t(stack[i]), 0, symbol))
                ret = libed2k::snprintf(out, len, "%d: %s\n", i, symbol->Name);
            else
                ret = libed2k::snprintf(out, len, "%d: <unknown>\n", i);

            out += ret;
            len -= ret;
            if (i == max_depth && max_depth > 0) break;
        }
        free(symbol);
    }
Exemplo n.º 3
0
LIBXSMM_API
#if defined(_WIN32)
/*TODO: no inline*/
#elif defined(__GNUC__)
/*LIBXSMM_ATTRIBUTE(noinline)*/
#endif
unsigned int libxsmm_backtrace(void* buffer[], unsigned int size)
{
#if defined(_WIN32) || defined(__CYGWIN__)
  return CaptureStackBackTrace(0, size, buffer, NULL);
#else
  return (unsigned int)backtrace(buffer, (int)size);
#endif
}
Exemplo n.º 4
0
const std::string PXL_stack_trace(int num_traces) {
#if defined(_DEBUG)
    uint32 i;
    DWORD* stacks = new DWORD[num_traces];
    uint16 frames_captured;
    SYMBOL_INFO* symbol;
    HANDLE process;

    process = GetCurrentProcess();
    SymInitialize(process, NULL, TRUE);
    frames_captured = CaptureStackBackTrace(0, num_traces, (PVOID*)stacks, NULL);

    //needs to be allocated on heap
    symbol = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1);
    symbol->MaxNameLen = 192;
    symbol->SizeOfStruct = sizeof(SYMBOL_INFO);

    IMAGEHLP_LINE line;
    DWORD disp;

    std::string output = "";
    char* char_output = new char[255];
    for (i = 0; i < frames_captured; i++) {
        SymFromAddr(process, stacks[i], NULL, symbol);
        SymGetLineFromAddr(process, stacks[i], &disp, &line);

        //convert file name to string and remove everything in the string before src or include
        std::string file_name = line.FileName;
        int id;
        if ((id = file_name.rfind("src")) != -1) {
            file_name = file_name.substr(id + 4, file_name.length());
        } else if ((id = file_name.rfind("include")) != -1) {
            file_name = file_name.substr(id, file_name.length());
        }

        if (id != -1) {
            sprintf(char_output, "%i: %s (%s, line %i)\n", frames_captured - i - 1, symbol->Name, file_name.c_str(), line.LineNumber);
            output += char_output;
        }
    }

    delete symbol;
    delete[] stacks;

    return output;
#endif

    return "";
}
Exemplo n.º 5
0
void printBacktrace(std::ostream * os) {
  if(os == 0)
    os = &std::cout;

  const int SIZE = 100;
  const int NAME_SIZE = 256;
#if defined(_WIN32)
  HANDLE process = GetCurrentProcess();
  SymSetOptions(SYMOPT_LOAD_LINES);
  SymInitialize(process, NULL, TRUE);

  void * stack[SIZE];
  unsigned short frames = CaptureStackBackTrace(0, SIZE, stack, NULL);
  SYMBOL_INFO * symbol = (SYMBOL_INFO * )calloc(sizeof(SYMBOL_INFO) + NAME_SIZE * sizeof(char), 1);
  symbol->MaxNameLen = NAME_SIZE;
  symbol->SizeOfStruct = sizeof(SYMBOL_INFO);

  for(unsigned short i = 0; i < frames; i++ ) {
    SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol);
    IMAGEHLP_LINE64 line;
    line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
    DWORD  dwDisplacement;
    if(!strstr(symbol->Name, __FUNCTION__) && !strstr(symbol->Name,"pgr::debugCallback") && SymGetLineFromAddr64(process, (DWORD64)(stack[i]), &dwDisplacement, &line)) {
      *os << symbol->Name << "():" << line.LineNumber << std::endl;
    }
    if(strcmp(symbol->Name, "main") == 0)
      break;
  }

  free(symbol);
#elif defined(__linux__)
  int j;
  void *buffer[SIZE];
  char **strings;

  int nptrs = backtrace(buffer, SIZE);
  strings = backtrace_symbols(buffer, nptrs);
  if(strings == NULL) {
    *os << "error in backtrace_symbols" << std::endl;
    return;
  }
  for (j = 0; j < nptrs; j++)
    *os << strings[j] << std::endl;
  free(strings);
#else
  *os << "backtrace not supported on this platform" << std::endl;
#endif
}
Exemplo n.º 6
0
    std::string Exception::btCallStack(const int maxCalls) {
        std::ostringstream btStream;
#ifdef FL_UNIX
        int bufferSize = maxCalls;
        void* buffer[bufferSize];
        int backtraceSize = backtrace(buffer, bufferSize);
        char **btSymbols = backtrace_symbols(buffer, backtraceSize);
        if (btSymbols == NULL) {
            btStream << "[backtrace error] no symbols could be retrieved";
        } else {
            if (backtraceSize == 0) btStream << "[backtrace is empty]";
            for (int i = 0; i < backtraceSize; ++i) {
                btStream << btSymbols[i] << "\n";
            }
        }
        free(btSymbols);
        /**
         *	WINDOWS:
         */
#elif defined FL_WINDOWS
        (void) maxCalls; //Can't allocate an with non-constant size in Windows
        const int bufferSize = 30;
        void* buffer[bufferSize];
        SymInitialize(GetCurrentProcess(), NULL, TRUE);

        int backtraceSize = CaptureStackBackTrace(0, bufferSize, buffer, NULL);
        SYMBOL_INFO* btSymbol = (SYMBOL_INFO *) calloc(sizeof ( SYMBOL_INFO) + 256 * sizeof ( char), 1);
        btSymbol->MaxNameLen = 255;
        btSymbol->SizeOfStruct = sizeof ( SYMBOL_INFO);

        if (not btSymbol) {
            btStream << "[backtrace error] no symbols could be retrieved";
        } else {
            if (backtraceSize == 0) btStream << "[backtrace is empty]";
            for (int i = 0; i < backtraceSize; ++i) {
                SymFromAddr(GetCurrentProcess(), (DWORD64) (buffer[ i ]), 0, btSymbol);
                btStream << (backtraceSize - i - 1) << ": " <<
                        btSymbol->Name << " at 0x" << btSymbol->Address << "\n";
            }
        }
        free(btSymbol);
#else
        btStream << "[backtrace error] backtrace not implemented for your operating system";
#endif
        return btStream.str();
    }
static bool GetStackWalk(std::string &outWalk)
{
    #ifdef USE_STACK_WALKER
    StackWalkerToString x(outWalk);
    x.ShowCallstack();
    #else
    //
    // http://blog.aaronballman.com/2011/04/generating-a-stack-crawl/
    //

    // Set up the symbol options so that we can gather information from the current
    // executable's PDB files, as well as the Microsoft symbol servers.  We also want
    // to undecorate the symbol names we're returned.  If you want, you can add other
    // symbol servers or paths via a semi-colon separated list in SymInitialized.
    ::SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_INCLUDE_32BIT_MODULES | SYMOPT_UNDNAME);

    if(!::SymInitialize(::GetCurrentProcess(), "http://msdl.microsoft.com/download/symbols", TRUE)) return false;

    // Capture up to 25 stack frames from the current call stack.  We're going to
    // skip the first stack frame returned because that's the GetStackWalk function
    // itself, which we don't care about.
    PVOID addrs[ 400 ] = { 0 };
    USHORT frames = CaptureStackBackTrace(1, 400, addrs, nullptr);

    for(USHORT i = 0; i < frames; i++)
    {
        // Allocate a buffer large enough to hold the symbol information on the stack and get
        // a pointer to the buffer.  We also have to set the size of the symbol structure itself
        // and the number of bytes reserved for the name.
        ULONG64 buffer[(sizeof(SYMBOL_INFO) + 1024 + sizeof(ULONG64) - 1) / sizeof(ULONG64) ] = { 0 };
        SYMBOL_INFO *info = (SYMBOL_INFO *)buffer;
        info->SizeOfStruct = sizeof(SYMBOL_INFO);
        info->MaxNameLen = 1024;
        // Attempt to get information about the symbol and add it to our output parameter.
        DWORD64 displacement = 0;

        if(::SymFromAddr(::GetCurrentProcess(), (DWORD64)addrs[ i ], &displacement, info))
        {
            outWalk.append(info->Name, info->NameLen);
            outWalk.append("\n");
        }
    }
    ::SymCleanup(::GetCurrentProcess());
    #endif
    return true;
}
void JKG_AssertFunction(char *file, int linenum, const char *expression)
{
	// This is different from the Win32 version of assert in that it dumps a stack crawl. Highly useful.
	DWORD stack[MAX_JKG_ASSERT_STACK_CRAWL];
	fileHandle_t f;


	//MessageBeep(MB_ICONERROR);	// BEEP

	memset(stack, 0, sizeof(DWORD)*MAX_JKG_ASSERT_STACK_CRAWL);

	CaptureStackBackTrace(0, MAX_JKG_ASSERT_STACK_CRAWL, (PVOID *)stack, NULL);

	// K, next we create an assert log
	trap_FS_FOpenFile(JKG_Asset_GetAssertlogName(), &f, FS_WRITE);
	JKG_WriteToAssertLogEasy(	"========================================\r\n"
								" Jedi Knight Galaxies Assertion Failure \r\n"
								"========================================\r\n\r\n", &f);
	JKG_WriteToAssertLogEasy(va("Version: %s (Windows)\r\n", GAMEVERSION), &f);
	JKG_WriteToAssertLogEasy(va("Side: Server-side\r\n"), &f);
	JKG_WriteToAssertLogEasy(va("Build Date/Time: %s %s\r\n", __DATE__, __TIME__), &f);

	JKG_WriteToAssertLogEasy("\r\n\r\n", &f);
	JKG_WriteToAssertLogEasy("Assertion Failure!\r\n", &f);
	JKG_WriteToAssertLogEasy(va("File: %s\r\n", file), &f);
	JKG_WriteToAssertLogEasy(va("Line: %i\r\n", linenum), &f);
	JKG_WriteToAssertLogEasy(va("Expression: %s\r\n\r\n", expression), &f);



	JKG_WriteToAssertLogEasy(	"========================================\r\n"
								"              Stack Crawl \r\n"
								"========================================\r\n", &f);

	JKG_WriteStackCrawl(&f, stack);

	JKG_WriteToAssertLogEasy(	"========================================\r\n"
								"           Module Information \r\n"
								"========================================\r\n", &f);

	JKG_Assert_ListModules(&f);

	trap_FS_FCloseFile(f);
	SymCleanup(GetCurrentProcess());
}
Exemplo n.º 9
0
void logvisorAbort()
{
    unsigned int i;
    void* stack[100];
    unsigned short frames;
    SYMBOL_INFO* symbol;
    HANDLE process;

    process = GetCurrentProcess();
    SymInitialize(process, NULL, TRUE);
    frames = CaptureStackBackTrace(0, 100, stack, NULL);
    symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1);
    symbol->MaxNameLen = 255;
    symbol->SizeOfStruct = sizeof(SYMBOL_INFO);

    for (i = 0; i < frames; i++)
    {
        SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol);

        fprintf(stderr, "%i: %s - 0x%0llX", frames - i - 1, symbol->Name, symbol->Address);

        DWORD dwDisplacement;
        IMAGEHLP_LINE64 line;
        SymSetOptions(SYMOPT_LOAD_LINES);

        line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
        if (SymGetLineFromAddr64(process, (DWORD64)(stack[i]), &dwDisplacement, &line))
        {
            // SymGetLineFromAddr64 returned success
            fprintf(stderr, " LINE %d\n", line.LineNumber);
        }
        else
        {
            fprintf(stderr, "\n");
        }
    }

    fflush(stderr);
    free(symbol);

    // If you caught one of the above signals, it is likely you just
    // want to quit your program right now.
    system("PAUSE");
    exit(1);
}
Exemplo n.º 10
0
QString CrashHandler::getStacktrace()
{
    #ifdef _WIN32
        unsigned int   i;
        void         * stack[ 100 ];
        unsigned short frames;
        SYMBOL_INFO  * symbol;
        HANDLE         process;

        process = GetCurrentProcess();

        SymInitialize( process, NULL, TRUE );

        frames               = CaptureStackBackTrace( 0, 100, stack, NULL );
        symbol               = ( SYMBOL_INFO * )calloc( sizeof( SYMBOL_INFO ) + 256 * sizeof( char ), 1 );
        symbol->MaxNameLen   = 255;
        symbol->SizeOfStruct = sizeof( SYMBOL_INFO );

        QString bkTrace("");
        for( i = 0; i < frames; i++ )
        {
            char buf[500];
            SymFromAddr( process, ( DWORD64 )( stack[ i ] ), 0, symbol );

            sprintf(buf, "%i: %s - 0x%0llx\n", frames - i - 1, symbol->Name, symbol->Address );
            bkTrace += buf;
        }
        return bkTrace;
    #elif __linux__
        void *array[400];
        size_t size;

        char **strings;
        size = backtrace(array, 10);

        strings = backtrace_symbols(array, size);

        QString bkTrace("");
        for(int j = 0; j < size; j++)
             bkTrace += QString(strings[j])+"\n";
        return bkTrace;
    #else
        return QString("");
    #endif
}
void capture() {
    const ULONG framesToSkip = 0;
    const ULONG framesToCapture = 64;
    void* backTrace[framesToCapture] {};
    ULONG backTraceHash = 0;

    const USHORT nFrame = CaptureStackBackTrace(
          framesToSkip
        , framesToCapture
        , backTrace
        , &backTraceHash
    );

    for(USHORT iFrame = 0; iFrame < nFrame; ++iFrame) {
        printf("[%3d] = %p\n", iFrame, backTrace[iFrame]);
    }
    printf("backTraceHash = %08x\n", backTraceHash);
}
Exemplo n.º 12
0
void BaseException::CreateStacktrace()
{
	std::stringstream ss;
#ifdef _MSC_VER
	void *stack[60];
	USHORT frames = CaptureStackBackTrace(3, MAX_STACK_FRAMES, stack, NULL);
	HANDLE process = GetCurrentProcess();
	if (SymInitialize(process, NULL, TRUE) == FALSE) {
		*_stacktrace = "Could not generate stack trace";
		return;
	}
	size_t symbolLength = sizeof(SYMBOL_INFO) + (MAX_FUNCTION_NAME_LENGTH - 1) * sizeof(TCHAR);
	SYMBOL_INFO *symbol = (SYMBOL_INFO *)malloc(symbolLength);
	ZeroMemory(symbol, symbolLength);
	symbol->MaxNameLen = MAX_FUNCTION_NAME_LENGTH;
	symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
	DWORD displacement;
	IMAGEHLP_LINE64 line;
	ZeroMemory(&line, sizeof(IMAGEHLP_LINE64));
	line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
	for (int i = 0; i < frames; ++i) {
		DWORD64 address = (DWORD64)(stack[i]);
		SymFromAddr(process, address, NULL, symbol);
		if (SymGetLineFromAddr64(process, address, &displacement, &line)) {
			ss << "\tat " << symbol->Name;
			ss << " in " << line.FileName;
			ss << ":" << line.LineNumber; 
			ss << "(address: 0x";
			ss << std::setfill('0') << std::setw(sizeof(ULONG64) * 2) << std::hex;
			ss << symbol->Address << std::dec << ")" << std::endl;
		}
		else {
			ss << "\tat " << symbol->Name << "(address: 0x";
			ss << std::setfill('0') << std::setw(sizeof(ULONG64) * 2) << std::hex;
			ss << symbol->Address << ")" << std::endl;
		}
	}
	SymCleanup(process);
	free(symbol);
	*_stacktrace = ss.str();
#else 
	*_stacktrace = "Not implemented";
#endif
}
Exemplo n.º 13
0
static void print_backtrace(FILE *f)
{
	static bool initialised = false;
	static HANDLE process;

	unsigned int frames;
	void *ip[MAX_STACK_FRAMES];
	SYMBOL_INFO *sym;

	if (!initialised)
	{
		process = GetCurrentProcess();
		SymInitialize(process, NULL, true);
		initialised = true;
	}

	if (!process)
	{
		fprintf(f, "Failed to get process for backtrace\n");
		return;
	}

	sym = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO) + MAX_SYMBOL_LENGTH * (sizeof(char)), 1);
	if (!sym)
	{
		fprintf(f, "Failed to allocate symbol info for backtrace\n");
		return;
	}
	sym->MaxNameLen = MAX_SYMBOL_LENGTH;
	sym->SizeOfStruct = sizeof(SYMBOL_INFO);

	/* Skip 2 frames (print_backtrace and the LogError function itself) */
	frames = CaptureStackBackTrace(2, MAX_STACK_FRAMES, ip, NULL);

	for (unsigned int frame = 0; frame < frames; frame++)
	{
		SymFromAddr(process, (DWORD64)(ip[frame]), 0, sym);
		fprintf(f, "  0x%p %s+0x%Ix\n", ip[frame], sym->Name,
		        (uintptr_t)ip[frame] - (uintptr_t)sym->Address);
	}

	free(sym);
}
Exemplo n.º 14
0
        void crash_handler::create_log_file_for_hockey_app(EXCEPTION_POINTERS* /* pExcPtrs */)
        {   
            const int max_stack_trace_depth = 48;
            void *stack[max_stack_trace_depth];
            USHORT count = CaptureStackBackTrace(0, max_stack_trace_depth, stack, NULL);

            std::stringstream stack_trace_stream;
            for (USHORT c = 0; c < count; c++)
            {
                stack_trace_stream << stack[c] << ";";
            }

            std::string stack_trace = stack_trace_stream.str();
            std::wstring log_name = get_report_log_path();

            time_t now = time(0);
            std::stringstream log_stream;
            // TODO (*) : use real info about app
            log_stream << "Package: " << product_bundle << std::endl;
            log_stream << "Version: " << VERSION_INFO_STR << std::endl;
            log_stream << "OS: " << get_os_version() << std::endl;
            log_stream << "Manufacturer: MS" << std::endl;
            log_stream << "Model: " << tools::version_info().get_version() << std::endl;

            char str[26];
            ctime_s(str, sizeof str, &now);
            log_stream << "Date: " << str << std::endl;
            log_stream << stack_trace << std::endl;

            auto log_text = log_stream.str();
            DWORD dwWritten;
            HANDLE handleFile (CreateFile(log_name.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 
                0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0));

            // https://msdn.microsoft.com/ru-ru/library/windows/desktop/5fc6ft2t(v=vs.80).aspx
            if(handleFile == INVALID_HANDLE_VALUE)
            {
                return;
            }

            CHandle hFile(handleFile);
            WriteFile(hFile, log_text.c_str(), log_text.size(), &dwWritten, 0);
        }
Exemplo n.º 15
0
int backtrace(void **array, int framesToCapture)
{
	int frames = 0;
#ifdef _M_X64
	frames = CaptureStackBackTrace(framesToSkip, framesToCapture, backTrace, nullptr);
#else
	__try {
		void **frame = 0;
		__asm { mov frame, ebp }
		while (frame && frames < framesToCapture) {
			array[frames] = frame[1];
			frames++;
			frame = (void **) frame[0];
		}
	}
	__except (1 /*EXCEPTION_EXECUTE_HANDLER*/) { }
#endif
	return frames;
}
Exemplo n.º 16
0
//------------------------------------------------------------------------
Callstack* AllocateCallstack(uint skipFrames)
{
    void* stack[MAX_DEPTH];
    //Getting from the calling function (0 is this function) to the number you want to capture
    uint32_t frames = CaptureStackBackTrace(1 + skipFrames, MAX_DEPTH, stack, NULL);
        
    ++gCallstackCount;

    size_t size = sizeof(Callstack) + sizeof(void*) * frames;
    void* bufferDataBegin = malloc(size);
    Callstack* callstack = new(bufferDataBegin) Callstack();
    byte* frameDataFront = (byte*)bufferDataBegin + sizeof(Callstack);

    callstack->frames = (void**)frameDataFront;
    callstack->frameCount = frames;
    memcpy(callstack->frames, stack, sizeof(void*) * frames);

    return callstack;
}
Exemplo n.º 17
0
  void StackDump(int level) 
  {
    unsigned int   i;
    void         * stack[ 100 ];
    unsigned short frames;
    SYMBOL_INFO  * symbol;
    HANDLE         process;

    level = std::min(100, level);
    if (level <= 0) return;

    process = GetCurrentProcess();
    SymSetOptions(SYMOPT_LOAD_LINES);
    SymInitialize( process, NULL, TRUE );

    frames               = CaptureStackBackTrace( 0, level, stack, NULL );
    symbol               = ( SYMBOL_INFO * )calloc( sizeof( SYMBOL_INFO ) + 256 * sizeof( char ), 1 );
    symbol->MaxNameLen   = 255;
    symbol->SizeOfStruct = sizeof( SYMBOL_INFO );

    std::cerr << "C++ stack dump:\n";
    for( i = 0; i < frames; i++ )
    {
      SymFromAddr( process, ( DWORD64 )( stack[ i ] ), 0, symbol );
      DWORD  dwDisplacement;
      IMAGEHLP_LINE64 line;

      line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
      if (!strstr(symbol->Name,"debug::") &&
        SymGetLineFromAddr64(process, ( DWORD64 )( stack[ i ] ), &dwDisplacement, &line)) {

          std::cerr << "function: " << symbol->Name << 
            " - line: " << line.LineNumber << "\n";

      }
      if (0 == strcmp(symbol->Name,"main"))
        break;
    }

    free( symbol );
  }
Exemplo n.º 18
0
// Requires DbgHelp.dll/dbghelp.lib
static void dumpExceptions()
    {
    unsigned int   i;
    void *stack[ 100 ];
    unsigned short frames;
    SYMBOL_INFO *symbol;
    HANDLE process;

    process = GetCurrentProcess();
    SymInitialize(process, NULL, TRUE);
    frames = CaptureStackBackTrace(0, 100, stack, NULL);
    symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1 );
    symbol->MaxNameLen = 255;
    symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
    for( i = 0; i < frames; i++ )
        {
        SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol);
        printf("%i: %s - 0x%0X\n", frames-i-1, symbol->Name, symbol->Address);
        }
    free(symbol);
    #endif
    }
Exemplo n.º 19
0
// PD_TRACE_DECLARE_FUNCTION ( SDB_OSSWS, "ossWalkStack" )
UINT32 ossWalkStack( UINT32 framesToSkip,
                     UINT32 framesRequested,
                     void ** ppInstruction )
{
   PD_TRACE_ENTRY ( SDB_OSSWS );
   UINT32 numFrames, framesOnStk ;

   framesOnStk = 0 ;
   if ( NULL != ppInstruction )
   {
      numFrames = framesRequested ;

      if ( OSS_MAX_BACKTRACE_FRAMES_SUPPORTED <= ( framesToSkip + numFrames ) )
      {
         numFrames = OSS_MAX_BACKTRACE_FRAMES_SUPPORTED - framesToSkip -1 ;
      }
      framesOnStk = CaptureStackBackTrace( framesToSkip,
                                           numFrames, ppInstruction, NULL ) ;
   }
   PD_TRACE_EXIT ( SDB_OSSWS );
   return framesOnStk ;
}
Exemplo n.º 20
0
/*memory ownership to the caller*/
static void store_backtrace(char *s_backtrace)
{
	void *stack[STACK_PRINT_SIZE];
	size_t i, frames, bt_idx = 0;
	SYMBOL_INFO *symbol;
	HANDLE process;

	process = GetCurrentProcess();
	SymInitialize(process, NULL, TRUE);

	symbol = (SYMBOL_INFO*)_alloca(sizeof(SYMBOL_INFO) + SYMBOL_MAX_SIZE);
	symbol->MaxNameLen = SYMBOL_MAX_SIZE-1;
	symbol->SizeOfStruct = sizeof(SYMBOL_INFO);

	frames = CaptureStackBackTrace(STACK_FIRST_IDX, STACK_PRINT_SIZE, stack, NULL);

	for (i=0; i<frames; i++) {
		int len;
		int bt_len;
		char *symbol_name = "unresolved";
		SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol);
		if (symbol->Name) symbol_name = (char*)symbol->Name;

		bt_len = (int) strlen(symbol_name) + 10;
		if (bt_idx + bt_len > STACK_PRINT_SIZE*SYMBOL_MAX_SIZE) {
			gf_memory_log(GF_MEMORY_WARNING, "[MemoryInfo] Not enough space to hold backtrace - truncating\n");
			break;
		}
		
		len = _snprintf(s_backtrace+bt_idx, SYMBOL_MAX_SIZE-1, "\t%02u 0x%I64X %s", (unsigned int) (frames-i-1), symbol->Address, symbol_name);
		if (len<0) len = SYMBOL_MAX_SIZE-1;
		s_backtrace[bt_idx+len]='\n';
		bt_idx += (len+1);
	}
	assert(bt_idx < STACK_PRINT_SIZE*SYMBOL_MAX_SIZE);
	s_backtrace[bt_idx-1] = '\0';
}
Exemplo n.º 21
0
void print_stack_trace(out_stream_t *out, int signum) {
  handle_t process = GetCurrentProcess();
  if (!SymRefreshModuleList(process)) {
    out_stream_printf(out, "Error refreshing module list: %i", GetLastError());
    return;
  }

  out_stream_printf(out, "# Received condition %i\n", signum);

  // Capture the stack trace.
  static const size_t kMaxStackSize = 32;
  void *backtrace[kMaxStackSize];
  size_t frame_count = CaptureStackBackTrace(0, kMaxStackSize, backtrace, NULL);

  // Scan through the trace one frame at a time, resolving symbols as we go.
  static const size_t kMaxNameLength = 128;
  static const size_t kSymbolInfoSize = sizeof(SYMBOL_INFO) + (kMaxNameLength * sizeof(char_t));
  // A SYMBOL_INFO is variable size so we stack allocate a blob of memory and
  // cast it rather than stack allocate the info directly.
  uint8_t symbol_info_bytes[kSymbolInfoSize];
  ZeroMemory(symbol_info_bytes, kSymbolInfoSize);
  SYMBOL_INFO *info = reinterpret_cast<SYMBOL_INFO*>(symbol_info_bytes);
  // This isn't strictly true, it's symbol_info_bytes, but SymFromAddr requires
  // it to have this value.
  info->SizeOfStruct = sizeof(SYMBOL_INFO);
  info->MaxNameLen = kMaxNameLength;
  for (size_t i = 0; i < frame_count; i++) {
    void *addr = backtrace[i];
    DWORD64 addr64 = reinterpret_cast<DWORD64>(addr);
    if (SymFromAddr(process, addr64, 0, info)) {
      out_stream_printf(out, "# - 0x%p: %s\n", addr, info->Name);
    } else {
      out_stream_printf(out, "# - 0x%p\n", addr);
    }
  }
}
Exemplo n.º 22
0
LPVOID getCtrlRoutine() {
    LPVOID ctrlRoutine;
    
    // CtrlRoutine --> MyHandle --> getCtrlRoutine
    // set the CaptureStackBackTrace's first param to 2 to ingore the MyHandler and getCtrlRoutine calls.
    // should disable complier optimization on Release version.
    USHORT count = CaptureStackBackTrace((ULONG) 2, (ULONG) 1, &ctrlRoutine, NULL);
    if (count != 1) {
        _tprintf(__T("CaptureStackBackTrace error\n"));
        goto error;
    }
    
    HANDLE hProcess = GetCurrentProcess();
    if (!SymInitialize(hProcess, NULL, TRUE)) {
        RETVAL rv; _HandleLastError(rv, __T("SymInitialize"));
    }
    
    ULONG64 buffer[(sizeof(SYMBOL_INFO) + MAX_SYM_NAME*sizeof(TCHAR) + sizeof(ULONG64)-1)/sizeof(ULONG64)];
    PSYMBOL_INFO pSymbol = (PSYMBOL_INFO) buffer;
    pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
    pSymbol->MaxNameLen = MAX_SYM_NAME;
    
    LPVOID funcCtrlRoutine = NULL;
    DWORD64 dwDisplacement = 0;
    if(!SymFromAddr(hProcess, (DWORD64) ctrlRoutine, &dwDisplacement, pSymbol)) {
        RETVAL rv; _HandleLastError(rv, __T("SymFromAddr"));
    }
    funcCtrlRoutine = reinterpret_cast<LPVOID>(pSymbol->Address);
    
    SymCleanup(hProcess);
    
    return funcCtrlRoutine;
    
error:
    return NULL;
}
Exemplo n.º 23
0
size_t backtrace(void **frames, size_t n_frames) {
  // Skip the first three frames; they're always going to show
  // w_log, log_stack_trace and backtrace
  return CaptureStackBackTrace(3, (DWORD)n_frames, frames, NULL);
}
Exemplo n.º 24
0
void printTrace()
{
	SymInitialize(GetCurrentProcess(), NULL, TRUE);

	UINT32 maxframes = 62;
	UINT_PTR myFrames[62];

	ZeroMemory(myFrames, sizeof(UINT_PTR) * maxframes);
	ULONG BackTraceHash;
	maxframes = CaptureStackBackTrace(0, maxframes, reinterpret_cast<PVOID*>(myFrames), &BackTraceHash);

	const UINT_PTR* pFrame = myFrames;
	const size_t frameSize = maxframes;

	UINT32  startIndex = 0;

	int unresolvedFunctionsCount = 0;
	IMAGEHLP_LINE  sourceInfo = { 0 };
	sourceInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE);

	// Use static here to increase performance, and avoid heap allocs.
	// It's thread safe because of g_heapMapLock lock.
	static char stack_line[1024] = "";
	bool isPrevFrameInternal = false;
	DWORD NumChars = 0;

	const size_t max_line_length = 512;
	const int resolvedCapacity = 62 * max_line_length;
	const size_t allocedBytes = resolvedCapacity * sizeof(char);
	char resolved[resolvedCapacity];
	if (resolved) {
		ZeroMemory(resolved, allocedBytes);
	}
	HANDLE hProcess = GetCurrentProcess();
	int resolvedLength = 0;
	// Iterate through each frame in the call stack.
	for (UINT32 frame = 0; frame < frameSize; frame++)
	{
		if (pFrame[frame] == 0)
			break;
		// Try to get the source file and line number associated with
		// this program counter address.
		SIZE_T programCounter = pFrame[frame];

		DWORD64 displacement64;
		BYTE symbolBuffer[sizeof(SYMBOL_INFO) + 256 * sizeof(char)];
		LPCSTR functionName = getFunctionName(programCounter, displacement64, (SYMBOL_INFO*)&symbolBuffer);

		// It turns out that calls to SymGetLineFromAddrW64 may free the very memory we are scrutinizing here
		// in this method. If this is the case, m_Resolved will be null after SymGetLineFromAddrW64 returns.
		// When that happens there is nothing we can do except crash.
		DWORD            displacement = 0;

		BOOL foundline = SymGetLineFromAddr(hProcess, programCounter, &displacement, &sourceInfo);

		bool isFrameInternal = false;

		// show one allocation function for context
		if (NumChars > 0 && !isFrameInternal && isPrevFrameInternal) {
			resolvedLength += NumChars;
			if (resolved) {
				strncat_s(resolved, resolvedCapacity, stack_line, NumChars);
			}
		}
		isPrevFrameInternal = isFrameInternal;

		if (!foundline)
			displacement = (DWORD)displacement64;
		NumChars = resolveFunction(programCounter, foundline ? &sourceInfo : NULL,
			displacement, functionName, stack_line, _countof(stack_line));

		if (NumChars > 0 && !isFrameInternal) {
			resolvedLength += NumChars;
			if (resolved) {
				strncat_s(resolved, resolvedCapacity, stack_line, NumChars);
			}
		}
	} // end for loop
	printLog(resolved);

	SymCleanup(GetCurrentProcess());
	return;
}
Exemplo n.º 25
0
//==============================================================================
std::vector <std::string>
getStackBacktrace()
{
    std::vector <std::string> result;

#if BEAST_ANDROID || BEAST_MINGW || BEAST_BSD
    assert(false); // sorry, not implemented yet!

#elif BEAST_WINDOWS
    HANDLE process = GetCurrentProcess();
    SymInitialize (process, nullptr, TRUE);

    void* stack[128];
    int frames = (int) CaptureStackBackTrace (0,
        std::distance(std::begin(stack), std::end(stack)),
        stack, nullptr);

    // Allow symbols that are up to 1024 characters long.
    std::size_t constexpr nameLength = 1024;

    alignas(SYMBOL_INFO) unsigned char symbuf[
        sizeof(SYMBOL_INFO) + nameLength * sizeof(SYMBOL_INFO::Name)];

    auto symbol = reinterpret_cast<SYMBOL_INFO*>(symbuf);

    for (int i = 0; i < frames; ++i)
    {
        DWORD64 displacement = 0;

        std::memset (symbol, 0, sizeof(symbuf));

        symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
        symbol->MaxNameLen = nameLength;

        if (SymFromAddr (process, (DWORD64)stack[i], &displacement, symbol))
        {
            std::string frame;

            frame.append (std::to_string (i) + ": ");

            IMAGEHLP_MODULE64 moduleInfo { sizeof(moduleInfo) };

            if (::SymGetModuleInfo64 (process, symbol->ModBase, &moduleInfo))
            {
                frame.append (moduleInfo.ModuleName);
                frame.append (": ");
            }

            frame.append (symbol->Name);

            if (displacement)
            {
                frame.append ("+");
                frame.append (std::to_string (displacement));
            }

            result.push_back (frame);
        }
    }

#else
    void* stack[128];
    int frames = backtrace (stack,
        std::distance(std::begin(stack), std::end(stack)));

    std::unique_ptr<char*[], decltype(std::free)*> frame {
        backtrace_symbols (stack, frames), std::free };

    for (int i = 0; i < frames; ++i)
        result.push_back (frame[i]);
#endif

    return result;
}
Exemplo n.º 26
0
void StackWalker::walk(
    xsize skip,
    Visitor *visit)
  {
  (void)skip;
  (void)visit;
#if X_ENABLE_STACK_WALKING
  struct Utils
    {
    static void doVisit(Visitor *visit, xsize i, void *pcOffset)
      {
      visit->visit(i, pcOffset);
      }
    };

  enum
    {
    BlockCaptureSize = 16,
    MaxSymbols = 128,
    };

#if defined(X_WIN)

  xsize position = skip + 1;
  const xsize start = position;
  void *frames[BlockCaptureSize];

  xuint16 captured = 0;
  do
    {
    captured = CaptureStackBackTrace((DWORD)position, BlockCaptureSize, frames, 0);

    for(xsize i = 0; i < captured; ++i)
      {
      Utils::doVisit(visit, position + i - start, frames[i]);
      }

    position += captured;
    } while(captured == BlockCaptureSize);

#elif defined(X_OSX)

  void *frames[MaxSymbols];

  int captured = backtrace(frames, MaxSymbols);
  if (captured <= 0 || (xsize)captured > X_ARRAY_COUNT(frames))
    {
    return;
    }

  for(xsize i = 0; i < (xsize)captured; ++i)
    {
    Utils::doVisit(visit, i, frames[skip+i]);
    }

#else
  (void)skip;
  (void)visit;
#endif
#endif
  }
Exemplo n.º 27
0
void mrpt::system::getCallStackBackTrace(TCallStackBackTrace& out_bt)
{
	out_bt.backtrace_levels.clear();
	const unsigned int framesToSkip =
		1;  // skip *this* function from the backtrace
	const unsigned int framesToCapture = 64;

#ifdef _WIN32
	void* backTrace[framesToCapture]{};

	SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS);
	const HANDLE hProcess = GetCurrentProcess();
	if (!SymInitialize(
			hProcess, nullptr /* UserSearchPath  */, TRUE /*fInvadeProcess*/))
	{
		std::cerr
			<< "[mrpt::system::getCallStackBackTrace] Error in SymInitialize()!"
			<< std::endl;
		return;
	}

	char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
	PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
	pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
	pSymbol->MaxNameLen = MAX_SYM_NAME;

	const USHORT nFrames = CaptureStackBackTrace(
		framesToSkip, framesToCapture, backTrace, nullptr);
	for (unsigned int i = 0; i < nFrames; i++)
	{
		TCallStackEntry cse;
		cse.address = backTrace[i];

		if (!SymFromAddr(hProcess, (DWORD64)cse.address, nullptr, pSymbol))
		{
			cse.symbolName = "???";
			cse.symbolNameOriginal = "???";
			out_bt.backtrace_levels.emplace_back(cse);
			continue;
		}
		SYMBOL_INFO& si = *pSymbol;

		cse.symbolNameOriginal = si.Name;
		char undecorated_name[1024];
		if (!UnDecorateSymbolName(
				si.Name, undecorated_name, sizeof(undecorated_name),
				UNDNAME_COMPLETE))
		{
			cse.symbolName = cse.symbolNameOriginal;
		}
		else
		{
			cse.symbolName = std::string(undecorated_name);
		}

		out_bt.backtrace_levels.emplace_back(cse);
	}
#else
	// Based on: https://gist.github.com/fmela/591333
	void* callstack[framesToCapture];
	const int nMaxFrames = sizeof(callstack) / sizeof(callstack[0]);
	int nFrames = ::backtrace(callstack, nMaxFrames);
	char** symbols = ::backtrace_symbols(callstack, nFrames);

	for (int i = (int)framesToSkip; i < nFrames; i++)
	{
		TCallStackEntry cse;
		cse.address = callstack[i];

		Dl_info info;
		if (dladdr(callstack[i], &info) && info.dli_sname)
		{
			char* demangled = nullptr;
			int status = -1;
			if (info.dli_sname[0] == '_')
			{
				demangled = abi::__cxa_demangle(
					info.dli_sname, nullptr, nullptr, &status);
			}
			cse.symbolNameOriginal =
				info.dli_sname == nullptr ? symbols[i] : info.dli_sname;
			cse.symbolName =
				status == 0 ? std::string(demangled) : cse.symbolNameOriginal;
			free(demangled);
		}
		out_bt.backtrace_levels.emplace_back(cse);
	}
	free(symbols);
#endif
}
Exemplo n.º 28
0
// PD_TRACE_DECLARE_FUNCTION ( SDB_OSSWKSEX, "ossWalkStackEx" )
UINT32 ossWalkStackEx( LPEXCEPTION_POINTERS lpEP,
                       UINT32 framesToSkip,
                       UINT32 framesRequested ,
                       void ** ppInstruction )
{
   PD_TRACE_ENTRY ( SDB_OSSWKSEX );
   HANDLE       hProcess   = GetCurrentProcess() ;
   HANDLE       hThread    = GetCurrentThread() ;

   STACKFRAME64 stackFrame = { 0 } ;
   CONTEXT      cContext   = { 0 } ;
   PCONTEXT     pContext   = &cContext ;
   BOOLEAN      bSuccess   = true ;

   UINT32 numFrames, framesOnStk ;

   framesOnStk = 0 ;

   if ( NULL != ppInstruction )
   {
      numFrames = framesRequested ;

      if ( OSS_MAX_BACKTRACE_FRAMES_SUPPORTED <= ( framesToSkip + numFrames ) )
      {
         numFrames = OSS_MAX_BACKTRACE_FRAMES_SUPPORTED - framesToSkip -1 ;
      }

      if ( NULL == lpEP )
      {
         framesOnStk = CaptureStackBackTrace( framesToSkip,
                                              numFrames, ppInstruction, NULL ) ;
      }
      else
      {
      #ifndef _WIN64
         stackFrame.AddrPC.Offset    = lpEP->ContextRecord->Eip ;
         stackFrame.AddrPC.Mode      = AddrModeFlat ;
         stackFrame.AddrStack.Offset = lpEP->ContextRecord->Esp ;
         stackFrame.AddrStack.Mode   = AddrModeFlat ;
         stackFrame.AddrFrame.Offset = lpEP->ContextRecord->Ebp ;
         stackFrame.AddrFrame.Mode   = AddrModeFlat ;
         ossMemcpy( pContext, lpEP->ContextRecord, sizeof( CONTEXT ) ) ;
      #else
         RtlCaptureContext( pContext ) ;
      #endif

         bSuccess = true ;
         WaitForSingleObject( ossGetSysMutexHandle( _StackWalk64 ), INFINITE ) ;
         while ( bSuccess && framesOnStk < numFrames )
         {
            bSuccess = StackWalk64( OSS_THIS_IMAGE_MACHINE_TYPE,
                                    hProcess,
                                    hThread,
                                    &stackFrame,
                                    pContext,
                                    NULL,
                                    SymFunctionTableAccess64,
                                    SymGetModuleBase64,
                                    NULL ) ;
            if ( bSuccess )
            {
               ppInstruction[ framesOnStk ] = (void*)stackFrame.AddrPC.Offset ;
            }
            else
            {
               ppInstruction[ framesOnStk ] = 0 ;
            }
            framesOnStk++ ;
         }
         ReleaseMutex ( ossGetSysMutexHandle( _StackWalk64 ) ) ;
      }
   }
   PD_TRACE_EXIT ( SDB_OSSWKSEX );
   return framesOnStk ;
}
Exemplo n.º 29
0
static void dumpBacktrace( unsigned int depth )
{
  if ( depth == 0 )
    depth = 20;

#if (defined(linux) && !defined(ANDROID)) || defined(__FreeBSD__)
  int stderr_fd = -1;
  if ( access( "/usr/bin/c++filt", X_OK ) < 0 )
  {
    myPrint( "Stacktrace (c++filt NOT FOUND):\n" );
  }
  else
  {
    int fd[2];

    if ( pipe( fd ) == 0 && fork() == 0 )
    {
      close( STDIN_FILENO ); // close stdin

      // stdin from pipe
      if ( dup( fd[0] ) != STDIN_FILENO )
      {
        QgsDebugMsg( "dup to stdin failed" );
      }

      close( fd[1] );        // close writing end
      execl( "/usr/bin/c++filt", "c++filt", ( char * ) 0 );
      perror( "could not start c++filt" );
      exit( 1 );
    }

    myPrint( "Stacktrace (piped through c++filt):\n" );
    stderr_fd = dup( STDERR_FILENO );
    close( fd[0] );          // close reading end
    close( STDERR_FILENO );  // close stderr

    // stderr to pipe
    if ( dup( fd[1] ) != STDERR_FILENO )
    {
      QgsDebugMsg( "dup to stderr failed" );
    }

    close( fd[1] );          // close duped pipe
  }

  void **buffer = new void *[ depth ];
  int nptrs = backtrace( buffer, depth );
  backtrace_symbols_fd( buffer, nptrs, STDERR_FILENO );
  delete [] buffer;
  if ( stderr_fd >= 0 )
  {
    int status;
    close( STDERR_FILENO );
    if ( dup( stderr_fd ) != STDERR_FILENO )
    {
      QgsDebugMsg( "dup to stderr failed" );
    }
    close( stderr_fd );
    wait( &status );
  }
#elif defined(Q_OS_WIN)
  void **buffer = new void *[ depth ];

  SymSetOptions( SYMOPT_DEFERRED_LOADS | SYMOPT_INCLUDE_32BIT_MODULES | SYMOPT_UNDNAME );
  SymInitialize( GetCurrentProcess(), "http://msdl.microsoft.com/download/symbols", TRUE );

  unsigned short nFrames = CaptureStackBackTrace( 1, depth, buffer, NULL );
  SYMBOL_INFO *symbol = ( SYMBOL_INFO * ) qgsMalloc( sizeof( SYMBOL_INFO ) + 256 );
  symbol->MaxNameLen = 255;
  symbol->SizeOfStruct = sizeof( SYMBOL_INFO );

  for ( int i = 0; i < nFrames; i++ )
  {
    SymFromAddr( GetCurrentProcess(), ( DWORD64 )( buffer[ i ] ), 0, symbol );
    symbol->Name[ 255 ] = 0;
    myPrint( "%d: %s [%x]\n", i, symbol->Name, symbol->Address );
  }

  qgsFree( symbol );
#endif
}
Exemplo n.º 30
0
void* winpr_backtrace(DWORD size)
{
#if defined(HAVE_EXECINFO_H)
	t_execinfo* data = calloc(1, sizeof(t_execinfo));

	if (!data)
		return NULL;

	data->buffer = calloc(size, sizeof(void*));

	if (!data->buffer)
	{
		free(data);
		return NULL;
	}

	data->max = size;
	data->used = backtrace(data->buffer, size);
	return data;
#elif defined(ANDROID)
	t_corkscrew_data* data = calloc(1, sizeof(t_corkscrew_data));

	if (!data)
		return NULL;

	data->buffer = calloc(size, sizeof(backtrace_frame_t));

	if (!data->buffer)
	{
		free(data);
		return NULL;
	}

	pthread_once(&initialized, load_library);
	data->max = size;
	data->used = fkt->unwind_backtrace(data->buffer, 0, size);
	return data;
#elif defined(_WIN32) || defined(_WIN64)
	HANDLE process = GetCurrentProcess();
	t_win_stack* data = calloc(1, sizeof(t_win_stack));

	if (!data)
		return NULL;

	data->max = size;
	data->stack = calloc(data->max, sizeof(PVOID));

	if (!data->stack)
	{
		free(data);
		return NULL;
	}

	SymInitialize(process, NULL, TRUE);
	data->used = CaptureStackBackTrace(2, size, data->stack, NULL);

	return data;
#else
	LOGF(support_msg);
	return NULL;
#endif
}