Ejemplo n.º 1
0
//static
void MemoryManager::DumpMemory()
{
	static int dumpCount = 0;
	MemoryManager* instance = GetInstance();
	DWORD64  dwDisplacement = 0;
	DWORD64  dwAddress;
	IMAGEHLP_LINE64 line;
	DWORD	 dwLineDisplacement;
	DWORD  error;
	HANDLE hProcess;

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

	SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES);

	hProcess = GetCurrentProcess();

	if (!SymInitialize(hProcess, NULL, TRUE))
	{
		error = GetLastError();
		LogError("SymInitialize returned error : %d\n", error);
	}

	std::stringstream filename;
	filename << "MemDump" << dumpCount++ << ".txt";

	FILE *myFile = nullptr;
	errno_t openResult = fopen_s(&myFile, filename.str().c_str(), "w");
	XTVERIFY(openResult == 0);

	if (myFile)
	{
		fprintf(myFile, "Total Memory Used:%u\n\n", (uint32)instance->m_totalAlloc);


		Alloc* currentAlloc = instance->m_head;
		while(currentAlloc != NULL)
		{
			dwAddress = (DWORD64)currentAlloc->m_stack[2];
			line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);

			fprintf(myFile, "Size: %u\n", (uint32)currentAlloc->m_size);

			if (currentAlloc->m_stackDepth >= 3 && SymGetLineFromAddr64(hProcess, dwAddress, &dwLineDisplacement, &line))
			{
				fprintf(myFile, "%s:%u\n", line.FileName, line.LineNumber);
			}
			else
			{
				fprintf(myFile, "Unknown File\n");
			}

			fprintf(myFile, "Callstack:\n");
		
			for(int i = 0; i < currentAlloc->m_stackDepth; i++)
			{
				dwAddress = (DWORD64)currentAlloc->m_stack[i];

				pSymbol->SizeOfStruct = 88; //sizeof(SYMBOL_INFO);
				pSymbol->MaxNameLen = MAX_SYM_NAME;

				if (SymFromAddr(hProcess, dwAddress, &dwDisplacement, pSymbol))
				{
					const char* name = pSymbol->Name;
					fprintf(myFile, "\t%i: %s\n", i, name);
				}
				else
				{
					fprintf(myFile, "\t%i: Unknown\n", i);
				}
			}

			fprintf(myFile, "\n");

			currentAlloc = currentAlloc->m_next;
		}

		_flushall();

		CONTEXT Context;
		memset(&Context, 0, sizeof(Context));
		RtlCaptureContext(&Context);


		fclose(myFile);
	}

	SymCleanup(hProcess);
}
Ejemplo n.º 2
0
 FunctionResolver::FunctionResolver(HANDLE processHandle)
     : m_hProcess(processHandle)
 {
     SymSetOptions(SYMOPT_DEBUG | SYMOPT_LOAD_ANYTHING);
 }
Ejemplo n.º 3
0
int main(int argc, char *argv[]) {
  DWORD  error;
  HANDLE process;
  ULONG64 module_base;
  int i;
  char* search;
  char buf[256];   /* Enough to hold one hex address, I trust! */
  int rv = 0;
  /* We may add SYMOPT_UNDNAME if --demangle is specified: */
  DWORD symopts = SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES;
  char* filename = "a.out";         /* The default if -e isn't specified */
  int print_function_name = 0;      /* Set to 1 if -f is specified */

  for (i = 1; i < argc; i++) {
    if (strcmp(argv[i], "--functions") == 0 || strcmp(argv[i], "-f") == 0) {
      print_function_name = 1;
    } else if (strcmp(argv[i], "--demangle") == 0 ||
               strcmp(argv[i], "-C") == 0) {
      symopts |= SYMOPT_UNDNAME;
    } else if (strcmp(argv[i], "-e") == 0) {
      if (i + 1 >= argc) {
        fprintf(stderr, "FATAL ERROR: -e must be followed by a filename\n");
        return 1;
      }
      filename = argv[i+1];
      i++;     /* to skip over filename too */
    } else if (strcmp(argv[i], "--help") == 0) {
      usage();
      exit(0);
    } else {
      usage();
      exit(1);
    }
  }

  process = GetCurrentProcess();

  if (!SymInitialize(process, NULL, FALSE)) {
    error = GetLastError();
    fprintf(stderr, "SymInitialize returned error : %d\n", error);
    return 1;
  }

  search = malloc(SEARCH_CAP);
  if (SymGetSearchPath(process, search, SEARCH_CAP)) {
    if (strlen(search) + sizeof(";" WEBSYM) > SEARCH_CAP) {
      fprintf(stderr, "Search path too long\n");
      SymCleanup(process);
      return 1;
    }
    strcat(search, ";" WEBSYM);
  } else {
    error = GetLastError();
    fprintf(stderr, "SymGetSearchPath returned error : %d\n", error);
    rv = 1;                   /* An error, but not a fatal one */
    strcpy(search, WEBSYM);   /* Use a default value */
  }
  if (!SymSetSearchPath(process, search)) {
    error = GetLastError();
    fprintf(stderr, "SymSetSearchPath returned error : %d\n", error);
    rv = 1;                   /* An error, but not a fatal one */
  }

  SymSetOptions(symopts);
  module_base = SymLoadModuleEx(process, NULL, filename, NULL, 0, 0, NULL, 0);
  if (!module_base) {
    /* SymLoadModuleEx failed */
    error = GetLastError();
    fprintf(stderr, "SymLoadModuleEx returned error : %d for %s\n",
            error, filename);
    SymCleanup(process);
    return 1;
  }

  buf[sizeof(buf)-1] = '\0';  /* Just to be safe */
  while (fgets(buf, sizeof(buf)-1, stdin)) {
    /* GNU addr2line seems to just do a strtol and ignore any
     * weird characters it gets, so we will too.
     */
    unsigned __int64 addr = _strtoui64(buf, NULL, 16);
    ULONG64 buffer[(sizeof(SYMBOL_INFO) +
                    MAX_SYM_NAME*sizeof(TCHAR) +
                    sizeof(ULONG64) - 1)
                   / sizeof(ULONG64)];
    PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
    IMAGEHLP_LINE64 line;
    DWORD dummy;
    pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
    pSymbol->MaxNameLen = MAX_SYM_NAME;
    if (print_function_name) {
      if (SymFromAddr(process, (DWORD64)addr, NULL, pSymbol)) {
        printf("%s\n", pSymbol->Name);
      } else {
        printf("??\n");
      }
    }
    line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
    if (SymGetLineFromAddr64(process, (DWORD64)addr, &dummy, &line)) {
      printf("%s:%d\n", line.FileName, (int)line.LineNumber);
    } else {
      printf("??:0\n");
    }
  }
  SymUnloadModule64(process, module_base);
  SymCleanup(process);
  return rv;
}
Ejemplo n.º 4
0
GCallStack::GCallStack(HANDLE hThread, CONTEXT& c)
{
	if (!_bLockInit) // only init the single instance of the CRITICAL_SECTION 1 time for the many instances of GCallStack
	{
		InitializeCriticalSection(&_DbgHelpLock);
		_bLockInit = true;
	}

	DWORD imageType = IMAGE_FILE_MACHINE_I386;
	HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, GetCurrentProcessId());
	int frameNum = 0; // counts walked frames
	int MAX_STACK_FRAMES = 7777; // in C# the maximum stack frames imposed by the language is 1000.  Arbitrary limit to guarantee no condition of infinate walking in corrupted memory.
	DWORD offsetFromLine; // tells us line number in the source file
#if defined(_LINUX64) || defined(_WIN64) || defined(_IOS)
	unsigned __int64 offsetFromSymbol; // tells us how far from the symbol we were
#else
	DWORD offsetFromSymbol; // tells us how far from the symbol we were
#endif

	DWORD symOptions; // symbol handler settings
	IMAGEHLP_SYMBOL *pSym = (IMAGEHLP_SYMBOL *) malloc( IMGSYMLEN + MAXNAMELEN );

	GString strStackName(MAXNAMELEN + 512); // undecorated method/function name + Source file and line number

	IMAGEHLP_MODULE Module;
	IMAGEHLP_LINE Line;
	STACKFRAME64 s; // in/out stackframe
	memset( &s, '\0', sizeof s );

//  note: converted code from [std::string symSearchPath] to [GString symSearchPath] so it will compile with the _UNICODE build flag - 8/18/2014
	GString symSearchPath;

#ifdef _UNICODE
	wchar_t *tt = 0, *p;
	tt = new wchar_t[TTBUFLEN];
#else
	char *tt = 0, *p;
	tt = new char[TTBUFLEN];
#endif

	// build symbol search path from:
	symSearchPath = "";
	// current directory
	if (GetCurrentDirectory(TTBUFLEN, tt))
		symSearchPath << tt << "; ";
	// dir with executable
	if ( GetModuleFileName( 0, tt, TTBUFLEN ) )
	{
#ifdef _UNICODE
		for (p = tt + wcslen(tt) - 1; p >= tt; --p)
#else
		for (p = tt + strlen(tt) - 1; p >= tt; --p)	// VC6 does not have a _tcsclen() and we still support VC6
#endif
		{
			// locate the rightmost path separator
			if ( *p == '\\' || *p == '/' || *p == ':' )
				break;
		}
		// if we found one, p is pointing at it; if not, tt only contains an exe name (no path), and p points before its first byte
		if ( p != tt ) // path sep found?
		{
			if ( *p == ':' ) // we leave colons in place
				++ p;
			*p = '\0'; // eliminate the exe name and last path sep
			symSearchPath << tt << "; "; 
		}
	}
	// environment variable _NT_SYMBOL_PATH
	GString g("_NT_SYMBOL_PATH");
	if (GetEnvironmentVariable(g, tt, TTBUFLEN))
		symSearchPath << tt << "; ";
	// environment variable _NT_ALTERNATE_SYMBOL_PATH
	g = "_NT_ALTERNATE_SYMBOL_PATH";
	if (GetEnvironmentVariable(g, tt, TTBUFLEN))
		symSearchPath << tt << "; ";
	// environment variable SYSTEMROOT
	g = "SYSTEMROOT";
	if (GetEnvironmentVariable(g, tt, TTBUFLEN))
		symSearchPath << tt << "; ";

	if ( symSearchPath.size() > 0 ) // if we added anything, we have a trailing semicolon
		symSearchPath = symSearchPath.substr( 0, symSearchPath.size() - 1 );

	// 8/20/2014 note: In older Windows API's SymInitialize()'s 2nd argument was not defined as "const char *", it was only "char *" 
	// Although "const" was not defined, the API call is "const" in behavior.  In newer versions of the Windows API this has been fixed.
	// In newer versions - SymInitialize's 2nd argument may resolve to either "const char *" OR "const wchar_t *", and in those builds the
	// GString has a default conversion to the correct string type, however in the older build configurations, GString does not (and should not)
	// know how to resolve to a "char *" by default, so in that case the preprocessor directive isolates the code needed to convert to "char *" 

#if defined(_MSC_VER) && _MSC_VER <= 1200
	if (!SymInitialize(hProcess, symSearchPath.Buf(),	false))	// symSearchPath == (char *)
#else
	if (!SymInitialize(hProcess, symSearchPath,			true))  // symSearchPath == (const char *)  --OR--  (const wchar_t *) depending on the _UNICODE preprocessor definition
#endif
	{
		goto tagCleanUp;
	}

	symOptions = SymGetOptions();
	symOptions |= SYMOPT_LOAD_LINES;
	symOptions &= ~SYMOPT_UNDNAME;
	SymSetOptions( symOptions );

	enumAndLoadModuleSymbols( hProcess, GetCurrentProcessId() );

	// init STACKFRAME for first call, definitions found in ImageHlp.h
#ifdef _M_IX86
	imageType = IMAGE_FILE_MACHINE_I386;
	s.AddrPC.Offset = c.Eip;
	s.AddrPC.Mode = AddrModeFlat;
	s.AddrFrame.Offset = c.Ebp;
	s.AddrFrame.Mode = AddrModeFlat;
	s.AddrStack.Offset = c.Esp;
	s.AddrStack.Mode = AddrModeFlat;
#elif _M_X64
	imageType = IMAGE_FILE_MACHINE_AMD64;
	s.AddrPC.Offset = c.Rip;
	s.AddrPC.Mode = AddrModeFlat;
	s.AddrFrame.Offset = c.Rsp;
	s.AddrFrame.Mode = AddrModeFlat;
	s.AddrStack.Offset = c.Rsp;
	s.AddrStack.Mode = AddrModeFlat;
#elif _M_IA64
	imageType = IMAGE_FILE_MACHINE_IA64;
	s.AddrPC.Offset = c.StIIP;
	s.AddrPC.Mode = AddrModeFlat;
	s.AddrFrame.Offset = c.IntSp;
	s.AddrFrame.Mode = AddrModeFlat;
	s.AddrBStore.Offset = c.RsBSP;
	s.AddrBStore.Mode = AddrModeFlat;
	s.AddrStack.Offset = c.IntSp;
	s.AddrStack.Mode = AddrModeFlat;
#endif

	memset( pSym, '\0', IMGSYMLEN + MAXNAMELEN );
	pSym->SizeOfStruct = IMGSYMLEN;
	pSym->MaxNameLength = MAXNAMELEN;

	memset( &Line, '\0', sizeof Line );
	Line.SizeOfStruct = sizeof Line;

	memset( &Module, '\0', sizeof Module );
	Module.SizeOfStruct = sizeof Module;

	offsetFromSymbol = 0;

	
	//	DbgHelp is single threaded, so acquire a lock.
	EnterCriticalSection(&_DbgHelpLock);

	while ( frameNum < MAX_STACK_FRAMES )
	{
		// get next stack frame (StackWalk(), SymFunctionTableAccess(), SymGetModuleBase())
		// if this returns ERROR_INVALID_ADDRESS (487) or ERROR_NOACCESS (998), you can
		// assume that either you are done, or that the stack is so hosed that the next deeper frame could not be found.
#ifdef _WIN64
		if (!StackWalk64(imageType, hProcess, hThread, &s, &c, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
#else
		if (!StackWalk(imageType, hProcess, hThread, &s, &c, NULL, SymFunctionTableAccess, SymGetModuleBase, NULL))
#endif
			break;  // Maybe it failed, maybe we have finished walking the stack

		if ( s.AddrPC.Offset != 0 )
		{ 
			// Most likely a valid stack rame
			
			// show procedure info 
			if ( ! SymGetSymFromAddr64( hProcess, s.AddrPC.Offset, &offsetFromSymbol, pSym ) )
			{
				break;
			}
			else
			{
				// UnDecorateSymbolName() to get the Class::Method or function() name in tyhe callstack
				strStackName.Empty();
 				UnDecorateSymbolName(pSym->Name, strStackName._str, MAXNAMELEN, UNDNAME_COMPLETE);
				strStackName.SetLength(strlen(strStackName._str));

				// SymGetLineFromAddr() to get the source.cpp and the line number 
				IMAGEHLP_LINE64 Line;
				if (SymGetLineFromAddr64(hProcess, s.AddrPC.Offset, &offsetFromLine, &Line) != FALSE)
				{
					GString g(Line.FileName);  // Line.FileName conains the "c:\Full\Path\TO\Source.cpp"
					
					// Builds string "Foo::Bar[Source.cpp]@777"
					strStackName << "[" << g.StartingAt(g.ReverseFind("\\") + 1) << "]@" << Line.LineNumber; 
				}

				// add the GString to the GStringList, do not add frame 0 because it will always be GException::GSeception where we divided by 0
				if (frameNum > 0)
					_stk += strStackName;
			}
		}
		else
		{
			// base reached
			SetLastError(0);
			break;
		}

		++frameNum;
	}
	
	LeaveCriticalSection(&_DbgHelpLock);


	// de-init symbol handler etc. (SymCleanup())
	SymCleanup( hProcess );
	free( pSym );
tagCleanUp:;	
	delete [] tt;
	CloseHandle(hProcess);
}
Ejemplo n.º 5
0
void printStackTrace( std::ostream &os ) {
    HANDLE process = GetCurrentProcess();
    BOOL ret = SymInitialize( process, NULL, TRUE );
    if ( ret == FALSE ) {
        DWORD dosError = GetLastError();
        os << "Stack trace failed, SymInitialize failed with error " <<
           std::dec << dosError << std::endl;
        return;
    }
    DWORD options = SymGetOptions();
    options |= SYMOPT_LOAD_LINES | SYMOPT_FAIL_CRITICAL_ERRORS;
    SymSetOptions( options );

    CONTEXT context;
    memset( &context, 0, sizeof(context) );
    context.ContextFlags = CONTEXT_CONTROL;
    RtlCaptureContext( &context );

    STACKFRAME64 frame64;
    memset( &frame64, 0, sizeof(frame64) );

#if defined(_M_AMD64)
    DWORD imageType = IMAGE_FILE_MACHINE_AMD64;
    frame64.AddrPC.Offset = context.Rip;
    frame64.AddrFrame.Offset = context.Rbp;
    frame64.AddrStack.Offset = context.Rsp;
#elif defined(_M_IX86)
    DWORD imageType = IMAGE_FILE_MACHINE_I386;
    frame64.AddrPC.Offset = context.Eip;
    frame64.AddrFrame.Offset = context.Ebp;
    frame64.AddrStack.Offset = context.Esp;
#else
#error Neither _M_IX86 nor _M_AMD64 were defined
#endif
    frame64.AddrPC.Mode = AddrModeFlat;
    frame64.AddrFrame.Mode = AddrModeFlat;
    frame64.AddrStack.Mode = AddrModeFlat;

    const size_t nameSize = 1024;
    const size_t symbolRecordSize = sizeof(SYMBOL_INFO) + nameSize;
    boost::scoped_array<char> symbolBuffer( new char[symbolRecordSize] );
    memset( symbolBuffer.get(), 0, symbolRecordSize );
    SYMBOL_INFO* symbol = reinterpret_cast<SYMBOL_INFO*>( symbolBuffer.get() );
    symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
    symbol->MaxNameLen = nameSize;

    std::vector<TraceItem> traceList;
    TraceItem traceItem;
    size_t moduleWidth = 0;
    size_t fileWidth = 0;
    size_t frameCount = 0;
    for ( size_t i = 0; i < maxBackTraceFrames; ++i ) {
        ret = StackWalk64( imageType,
                           process,
                           GetCurrentThread(),
                           &frame64,
                           &context,
                           NULL,
                           NULL,
                           NULL,
                           NULL );
        if ( ret == FALSE || frame64.AddrReturn.Offset == 0 ) {
            frameCount = i;
            break;
        }

        // module (executable) name
        IMAGEHLP_MODULE64 module;
        memset ( &module, 0, sizeof(module) );
        module.SizeOfStruct = sizeof(module);
        ret = SymGetModuleInfo64( process, frame64.AddrPC.Offset, &module );
        char* moduleName = module.LoadedImageName;
        char* backslash = strrchr( moduleName, '\\' );
        if ( backslash ) {
            moduleName = backslash + 1;
        }
        traceItem.module = moduleName;
        size_t len = traceItem.module.length();
        if ( len > moduleWidth ) {
            moduleWidth = len;
        }

        // source code filename and line number
        IMAGEHLP_LINE64 line;
        memset( &line, 0, sizeof(line) );
        line.SizeOfStruct = sizeof(line);
        DWORD displacement32;
        ret = SymGetLineFromAddr64( process, frame64.AddrPC.Offset, &displacement32, &line );
        if ( ret ) {
            std::string filename( line.FileName );
            std::string::size_type start = filename.find( "\\src\\mongo\\" );
            if ( start == std::string::npos ) {
                start = filename.find( "\\src\\third_party\\" );
            }
            if ( start != std::string::npos ) {
                std::string shorter( "..." );
                shorter += filename.substr( start );
                traceItem.sourceFile.swap( shorter );
            }
            else {
                traceItem.sourceFile.swap( filename );
            }
            len = traceItem.sourceFile.length() + 3;
            traceItem.lineNumber = line.LineNumber;
            if ( traceItem.lineNumber < 10 ) {
                len += 1;
            }
            else if ( traceItem.lineNumber < 100 ) {
                len += 2;
            }
            else if ( traceItem.lineNumber < 1000 ) {
                len += 3;
            }
            else if ( traceItem.lineNumber < 10000 ) {
                len += 4;
            }
            else {
                len += 5;
            }
            traceItem.sourceLength = len;
            if ( len > fileWidth ) {
                fileWidth = len;
            }
        }
        else {
            traceItem.sourceFile.clear();
            traceItem.sourceLength = 0;
        }

        // symbol name and offset from symbol
        DWORD64 displacement;
        ret = SymFromAddr( process, frame64.AddrPC.Offset, &displacement, symbol );
        if ( ret ) {
            traceItem.symbol = symbol->Name;
            traceItem.instructionOffset = displacement;
        }
        else {
            traceItem.symbol = "???";
            traceItem.instructionOffset = 0;
        }

        // add to list
        traceList.push_back( traceItem );
    }
    SymCleanup( process );

    // print list
    ++moduleWidth;
    ++fileWidth;
    for ( size_t i = 0; i < frameCount; ++i ) {
        os << traceList[i].module << " ";
        size_t width = traceList[i].module.length();
        while ( width < moduleWidth ) {
            os << " ";
            ++width;
        }
        if ( traceList[i].sourceFile.length() ) {
            os << traceList[i].sourceFile << "(" << std::dec << traceList[i].lineNumber << ") ";
        }
        width = traceList[i].sourceLength;
        while ( width < fileWidth ) {
            os << " ";
            ++width;
        }
        os << traceList[i].symbol << "+0x" << std::hex << traceList[i].instructionOffset;
        os << std::endl;
    }
}
Ejemplo n.º 6
0
std::ostream& backtrace( std::ostream& os )
{
#ifdef _WIN32
    // Sym* functions from DbgHelp are not thread-safe...
    static Lock lock;
    ScopedMutex<> mutex( lock );
    
    typedef USHORT (WINAPI *CaptureStackBackTraceType)( __in ULONG, __in ULONG,
                                                        __out PVOID*,
                                                        __out_opt PULONG );
    CaptureStackBackTraceType backtraceFunc = (CaptureStackBackTraceType)
       GetProcAddress(LoadLibrary("kernel32.dll"), "RtlCaptureStackBackTrace");
    if( !backtraceFunc )
        return os;

    SymSetOptions( SYMOPT_UNDNAME | SYMOPT_LOAD_LINES );
    HANDLE hProcess = GetCurrentProcess();
    if( !SymInitialize( hProcess, 0, TRUE ))
        return os;  
    
    void* stack[ LB_BACKTRACE_DEPTH ];
    unsigned short frames = (backtraceFunc)( 0, LB_BACKTRACE_DEPTH, stack, 0 );
  
    SYMBOL_INFO* symbol = (SYMBOL_INFO*)calloc( sizeof(SYMBOL_INFO) +
                                         (LB_SYMBOL_LENGTH+-1)*sizeof(char), 1 );
    symbol->MaxNameLen   = LB_SYMBOL_LENGTH;
    symbol->SizeOfStruct = sizeof( SYMBOL_INFO );
    
    os << disableFlush << disableHeader << indent << std::endl;
    for( unsigned short i = 0; i < frames; ++i )
    {
        os << frames-i-1 << ": ";
        if ( !SymFromAddr( hProcess, (DWORD64)stack[i], 0, symbol ))
            os << "Unknown symbol";
        else
        {
            os << symbol->Name << " - ";            
            IMAGEHLP_LINE64 line = { sizeof(IMAGEHLP_LINE64) };
            if( !SymGetLineFromAddr64( hProcess, (DWORD64)stack[i], 0, &line ))
                os << std::hex << "0x" << symbol->Address << std::dec;
            else
                os << line.FileName << ":" << line.LineNumber;
        }
        os << std::endl;                
    }
    os << exdent << enableHeader << enableFlush;
    free( symbol );
    SymCleanup( hProcess );
#else
    void* callstack[ LB_BACKTRACE_DEPTH ];
    const int frames = ::backtrace( callstack, LB_BACKTRACE_DEPTH );
    char** names = ::backtrace_symbols( callstack, frames );
    os << disableFlush << disableHeader << indent << std::endl;
    for( int i = 1; i < frames; ++i )
    {
        std::string name = names[ i ];
#  ifdef __linux__
        const size_t symbolPos = name.find( "(_" );
#  else
        const size_t symbolPos = name.find( " _" );
#  endif
        if( symbolPos != std::string::npos )
            name = name.substr( symbolPos+1, name.length( ));

#  ifdef __linux__
        const size_t spacePos = name.find( '+' );
#  else
        const size_t spacePos = name.find( ' ' );
#  endif
        if( spacePos != std::string::npos )
            name = name.substr( 0, spacePos );

        int status;
        char* demangled = abi::__cxa_demangle( name.c_str(), 0, 0, &status);

        if( symbolPos == std::string::npos || spacePos == std::string::npos )
            os << names[ i ] << std::endl;
        else
        {
            if( demangled )
            {
                os << demangled << std::endl;
                free( demangled );
            }
            else
                os << name << std::endl;
        }
    }
    os << exdent << enableHeader << enableFlush;
    ::free( names );
#endif

    return os;
}
Ejemplo n.º 7
0
int main(int argc, char** argv)
{
    int 	        retv = 0;
    HANDLE              hFile = INVALID_HANDLE_VALUE;
    enum dbg_start      ds;

#ifdef __i386__
    be_cpu = &be_i386;
#elif defined(__powerpc__)
    be_cpu = &be_ppc;
#elif defined(__ALPHA__)
    be_cpu = &be_alpha;
#elif defined(__x86_64__)
    be_cpu = &be_x86_64;
#elif defined(__sparc__)
    be_cpu = &be_sparc;
#elif defined(__arm__)
    be_cpu = &be_arm;
#else
# error CPU unknown
#endif
    /* Initialize the output */
    dbg_houtput = GetStdHandle(STD_OUTPUT_HANDLE);

    /* Initialize internal vars */
    if (!dbg_load_internal_vars()) return -1;

    /* as we don't care about exec name */
    argc--; argv++;

    if (argc && !strcmp(argv[0], "--help"))
        return dbg_winedbg_usage(TRUE);

    if (argc && !strcmp(argv[0], "--gdb"))
    {
        retv = gdb_main(argc, argv);
        if (retv == -1) dbg_winedbg_usage(FALSE);
        return retv;
    }
    dbg_init_console();

    SymSetOptions((SymGetOptions() & ~(SYMOPT_UNDNAME)) |
                  SYMOPT_LOAD_LINES | SYMOPT_DEFERRED_LOADS | SYMOPT_AUTO_PUBLICS);

    if (argc && (!strcmp(argv[0], "--auto") || !strcmp(argv[0], "--minidump")))
    {
        /* force some internal variables */
        DBG_IVAR(BreakOnDllLoad) = 0;
        dbg_houtput = GetStdHandle(STD_ERROR_HANDLE);
        switch (dbg_active_auto(argc, argv))
        {
        case start_ok:          return 0;
        case start_error_parse: return dbg_winedbg_usage(FALSE);
        case start_error_init:  return -1;
        }
    }
    /* parse options */
    while (argc > 0 && argv[0][0] == '-')
    {
        if (!strcmp(argv[0], "--command"))
        {
            argc--; argv++;
            hFile = parser_generate_command_file(argv[0], NULL);
            if (hFile == INVALID_HANDLE_VALUE)
            {
                dbg_printf("Couldn't open temp file (%u)\n", GetLastError());
                return 1;
            }
            argc--; argv++;
            continue;
        }
        if (!strcmp(argv[0], "--file"))
        {
            argc--; argv++;
            hFile = CreateFileA(argv[0], GENERIC_READ|DELETE, 0, 
                                NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
            if (hFile == INVALID_HANDLE_VALUE)
            {
                dbg_printf("Couldn't open file %s (%u)\n", argv[0], GetLastError());
                return 1;
            }
            argc--; argv++;
            continue;
        }
        if (!strcmp(argv[0], "--"))
        {
            argc--; argv++;
            break;
        }
        return dbg_winedbg_usage(FALSE);
    }
    if (!argc) ds = start_ok;
    else if ((ds = dbg_active_attach(argc, argv)) == start_error_parse &&
             (ds = minidump_reload(argc, argv)) == start_error_parse)
        ds = dbg_active_launch(argc, argv);
    switch (ds)
    {
    case start_ok:              break;
    case start_error_parse:     return dbg_winedbg_usage(FALSE);
    case start_error_init:      return -1;
    }

    dbg_start_interactive(hFile);

    return 0;
}
Ejemplo n.º 8
0
/***********************************************************************
 *           symbol_get_lvalue
 *
 * Get the address of a named symbol.
 * Return values:
 *      sglv_found:   if the symbol is found
 *      sglv_unknown: if the symbol isn't found
 *      sglv_aborted: some error occurred (likely, many symbols of same name exist,
 *          and user didn't pick one of them)
 */
enum sym_get_lval symbol_get_lvalue(const char* name, const int lineno,
                                    struct dbg_lvalue* rtn, BOOL bp_disp)
{
    struct sgv_data             sgv;
    int		                i;
    char                        buffer[512];
    DWORD                       opt;
    IMAGEHLP_STACK_FRAME        ihsf;

    if (strlen(name) + 4 > sizeof(buffer))
    {
        WINE_WARN("Too long symbol (%s)\n", name);
        return sglv_unknown;
    }

    sgv.num        = 0;
    sgv.num_thunks = 0;
    sgv.name       = &buffer[2];
    sgv.do_thunks  = DBG_IVAR(AlwaysShowThunks);

    if (strchr(name, '!'))
    {
        strcpy(buffer, name);
    }
    else
    {
        buffer[0] = '*';
        buffer[1] = '!';
        strcpy(&buffer[2], name);
    }

    /* this is a wine specific options to return also ELF modules in the
     * enumeration
     */
    SymSetOptions((opt = SymGetOptions()) | 0x40000000);
    SymEnumSymbols(dbg_curr_process->handle, 0, buffer, sgv_cb, (void*)&sgv);

    if (!sgv.num)
    {
        const char*   ptr = strchr(name, '!');
        if ((ptr && ptr[1] != '_') || (!ptr && *name != '_'))
        {
            if (ptr)
            {
                int offset = ptr - name;
                memcpy(buffer, name, offset + 1);
                buffer[offset + 1] = '_';
                strcpy(&buffer[offset + 2], ptr + 1);
            }
            else
            {
                buffer[0] = '*';
                buffer[1] = '!';
                buffer[2] = '_';
                strcpy(&buffer[3], name);
            }
            SymEnumSymbols(dbg_curr_process->handle, 0, buffer, sgv_cb, (void*)&sgv);
        }
    }
    SymSetOptions(opt);

    /* now grab local symbols */
    if (stack_get_current_frame(&ihsf) && sgv.num < NUMDBGV)
    {
        sgv.frame_offset = ihsf.FrameOffset;
        SymEnumSymbols(dbg_curr_process->handle, 0, name, sgv_cb, (void*)&sgv);
    }

    if (!sgv.num)
    {
        dbg_printf("No symbols found for %s\n", name);
        return sglv_unknown;
    }

    /* recompute potential offsets for functions (linenumber, skip prolog) */
    for (i = 0; i < sgv.num; i++)
    {
        if (sgv.syms[i].flags & (SYMFLAG_REGISTER|SYMFLAG_REGREL|SYMFLAG_LOCAL|SYMFLAG_THUNK))
            continue;

        if (lineno == -1)
        {
            struct dbg_type     type;
            ULONG64             addr;

            type.module = sgv.syms[i].lvalue.type.module;
            type.id     = sgv.syms[i].sym_info;
            if (bp_disp && symbol_get_debug_start(&type, &addr))
                sgv.syms[i].lvalue.addr.Offset = addr;
        }
        else
        {
            DWORD               disp;
            IMAGEHLP_LINE       il;
            BOOL                found = FALSE;

            il.SizeOfStruct = sizeof(il);
            SymGetLineFromAddr(dbg_curr_process->handle,
                               (DWORD)memory_to_linear_addr(&sgv.syms[i].lvalue.addr),
                               &disp, &il);
            do
            {
                if (lineno == il.LineNumber)
                {
                    sgv.syms[i].lvalue.addr.Offset = il.Address;
                    found = TRUE;
                    break;
                }
            } while (SymGetLineNext(dbg_curr_process->handle, &il));
            if (!found)
                WINE_FIXME("No line (%d) found for %s (setting to symbol start)\n",
                           lineno, name);
        }
    }

    i = 0;
    if (dbg_interactiveP)
    {
        if (sgv.num - sgv.num_thunks > 1 || /* many symbols non thunks (and showing only non thunks) */
            (sgv.num > 1 && DBG_IVAR(AlwaysShowThunks)) || /* many symbols (showing symbols & thunks) */
            (sgv.num == sgv.num_thunks && sgv.num_thunks > 1))
        {
            dbg_printf("Many symbols with name '%s', "
                       "choose the one you want (<cr> to abort):\n", name);
            for (i = 0; i < sgv.num; i++) 
            {
                if (sgv.num - sgv.num_thunks > 1 && (sgv.syms[i].flags & SYMFLAG_THUNK) && !DBG_IVAR(AlwaysShowThunks))
                    continue;
                dbg_printf("[%d]: ", i + 1);
                if (sgv.syms[i].flags & SYMFLAG_LOCAL)
                {
                    dbg_printf("%s %sof %s\n",
                               sgv.syms[i].flags & SYMFLAG_PARAMETER ? "Parameter" : "Local variable",
                               sgv.syms[i].flags & (SYMFLAG_REGISTER|SYMFLAG_REGREL) ? "(in a register) " : "",
                               name);
                }
                else if (sgv.syms[i].flags & SYMFLAG_THUNK) 
                {
                    print_address(&sgv.syms[i].lvalue.addr, TRUE);
                    /* FIXME: should display where the thunks points to */
                    dbg_printf(" thunk %s\n", name);
                }
                else
                {
                    print_address(&sgv.syms[i].lvalue.addr, TRUE);
                    dbg_printf("\n");
                }
            }
            do
            {
                i = 0;
                if (input_read_line("=> ", buffer, sizeof(buffer)))
                {
                    if (buffer[0] == '\0') return sglv_aborted;
                    i = atoi(buffer);
                    if (i < 1 || i > sgv.num)
                        dbg_printf("Invalid choice %d\n", i);
                }
                else return sglv_aborted;
            } while (i < 1 || i > sgv.num);

            /* The array is 0-based, but the choices are 1..n, 
             * so we have to subtract one before returning.
             */
            i--;
        }
    }
    else
    {
        /* FIXME: could display the list of non-picked up symbols */
        if (sgv.num > 1)
            dbg_printf("More than one symbol named %s, picking the first one\n", name);
    }
    *rtn = sgv.syms[i].lvalue;
    return sglv_found;
}
Ejemplo n.º 9
0
/***********************************************************************
 *           symbol_get_line
 *
 * Find the symbol nearest to a given address.
 * Returns sourcefile name and line number in a format that the listing
 * handler can deal with.
 */
BOOL symbol_get_line(const char* filename, const char* name, IMAGEHLP_LINE* line)
{
    struct sgv_data     sgv;
    char                buffer[512];
    DWORD               opt, disp, linear;
    unsigned            i, found = FALSE;
    IMAGEHLP_LINE       il;

    sgv.num        = 0;
    sgv.num_thunks = 0;
    sgv.name       = &buffer[2];
    sgv.do_thunks  = FALSE;

    buffer[0] = '*';
    buffer[1] = '!';
    strcpy(&buffer[2], name);

    /* this is a wine specific options to return also ELF modules in the
     * enumeration
     */
    SymSetOptions((opt = SymGetOptions()) | 0x40000000);
    if (!SymEnumSymbols(dbg_curr_process->handle, 0, buffer, sgv_cb, (void*)&sgv))
    {
        SymSetOptions(opt);
        return FALSE;
    }

    if (!sgv.num && (name[0] != '_'))
    {
        buffer[2] = '_';
        strcpy(&buffer[3], name);
        if (!SymEnumSymbols(dbg_curr_process->handle, 0, buffer, sgv_cb, (void*)&sgv))
        {
            SymSetOptions(opt);
            return FALSE;
        }
    }
    SymSetOptions(opt);

    for (i = 0; i < sgv.num; i++)
    {
        linear = (DWORD)memory_to_linear_addr(&sgv.syms[i].lvalue.addr);

        il.SizeOfStruct = sizeof(il);
        if (!SymGetLineFromAddr(dbg_curr_process->handle, linear, &disp, &il))
            continue;
        if (filename && strcmp(line->FileName, filename)) continue;
        if (found)
        {
            WINE_FIXME("Several found, returning first (may not be what you want)...\n");
            break;
        }
        found = TRUE;
        *line = il;
    }
    if (!found)
    {
        if (filename)   dbg_printf("No such function %s in %s\n", name, filename);
	else            dbg_printf("No such function %s\n", name);
        return FALSE;
    }
    return TRUE;
}
Ejemplo n.º 10
0
static void stack_trace( PEXCEPTION_POINTERS pInfo )
{
	char message[1024];
	int len = 0;
	size_t i;
	HANDLE process = GetCurrentProcess();
	HANDLE thread = GetCurrentThread();
	IMAGEHLP_LINE64 line;
	DWORD dline = 0;
	DWORD options;
	CONTEXT context;
	STACKFRAME64 stackframe;
	DWORD image;

	memcpy( &context, pInfo->ContextRecord, sizeof(CONTEXT) );
	options = SymGetOptions(); 
	options |= SYMOPT_DEBUG;
	options |= SYMOPT_LOAD_LINES;
	SymSetOptions( options ); 

	SymInitialize( process, NULL, TRUE );

	

	ZeroMemory( &stackframe, sizeof(STACKFRAME64) );

#ifdef _M_IX86
	image = IMAGE_FILE_MACHINE_I386;
	stackframe.AddrPC.Offset = context.Eip;
	stackframe.AddrPC.Mode = AddrModeFlat;
	stackframe.AddrFrame.Offset = context.Ebp;
	stackframe.AddrFrame.Mode = AddrModeFlat;
	stackframe.AddrStack.Offset = context.Esp;
	stackframe.AddrStack.Mode = AddrModeFlat;
#elif _M_X64
	image = IMAGE_FILE_MACHINE_AMD64;
	stackframe.AddrPC.Offset = context.Rip;
	stackframe.AddrPC.Mode = AddrModeFlat;
	stackframe.AddrFrame.Offset = context.Rsp;
	stackframe.AddrFrame.Mode = AddrModeFlat;
	stackframe.AddrStack.Offset = context.Rsp;
	stackframe.AddrStack.Mode = AddrModeFlat;
#elif _M_IA64
	image = IMAGE_FILE_MACHINE_IA64;
	stackframe.AddrPC.Offset = context.StIIP;
	stackframe.AddrPC.Mode = AddrModeFlat;
	stackframe.AddrFrame.Offset = context.IntSp;
	stackframe.AddrFrame.Mode = AddrModeFlat;
	stackframe.AddrBStore.Offset = context.RsBSP;
	stackframe.AddrBStore.Mode = AddrModeFlat;
	stackframe.AddrStack.Offset = context.IntSp;
	stackframe.AddrStack.Mode = AddrModeFlat;
#endif
	len += snprintf( message + len, 1024 - len, "Sys_Crash: address %p, code %p\n", pInfo->ExceptionRecord->ExceptionAddress, pInfo->ExceptionRecord->ExceptionCode );
	if( SymGetLineFromAddr64( process, (DWORD64)pInfo->ExceptionRecord->ExceptionAddress, &dline, &line ) )
	{
		len += snprintf(message + len, 1024 - len,"Exception: %s:%d:%d\n", (char*)line.FileName, (int)line.LineNumber, (int)dline);
	}
	if( SymGetLineFromAddr64( process, stackframe.AddrPC.Offset, &dline, &line ) )
	{
		len += snprintf(message + len, 1024 - len,"PC: %s:%d:%d\n", (char*)line.FileName, (int)line.LineNumber, (int)dline);
	}
	if( SymGetLineFromAddr64( process, stackframe.AddrFrame.Offset, &dline, &line ) )
	{
		len += snprintf(message + len, 1024 - len,"Frame: %s:%d:%d\n", (char*)line.FileName, (int)line.LineNumber, (int)dline);
	}
	for( i = 0; i < 25; i++ )
	{
		char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
		PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
		BOOL result = StackWalk64(
			image, process, thread,
			&stackframe, &context, NULL,
			SymFunctionTableAccess64, SymGetModuleBase64, NULL);

		DWORD64 displacement = 0;
		if( !result )
			break;

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

		len += snprintf( message + len, 1024 - len, "% 2d %p", i, (void*)stackframe.AddrPC.Offset );
		if( SymFromAddr( process, stackframe.AddrPC.Offset, &displacement, symbol ) )
		{
			len += snprintf( message + len, 1024 - len, " %s ", symbol->Name );
		}
		if( SymGetLineFromAddr64( process, stackframe.AddrPC.Offset, &dline, &line ) )
		{
			len += snprintf(message + len, 1024 - len,"(%s:%d:%d) ", (char*)line.FileName, (int)line.LineNumber, (int)dline);
		}
		len += snprintf( message + len, 1024 - len, "(");
		len += ModuleName( process, message + len, (void*)stackframe.AddrPC.Offset, 1024 - len );
		len += snprintf( message + len, 1024 - len, ")\n");
	}
#ifdef XASH_SDL
	if( host.type != HOST_DEDICATED ) // let system to restart server automaticly
		SDL_ShowSimpleMessageBox( SDL_MESSAGEBOX_ERROR,"Sys_Crash", message, host.hWnd );
#endif
	Sys_PrintLog(message);

	SymCleanup(process);
}
Ejemplo n.º 11
0
int CMiniDumpReader::Open(CString sFileName, CString sSymSearchPath)
{  
    static DWORD dwProcessID = 0;

    if(m_bLoaded)
    {
        return 1;
    }

    m_sFileName = sFileName;
    m_sSymSearchPath = sSymSearchPath;

    m_hFileMiniDump = CreateFile(
        sFileName, 
        FILE_ALL_ACCESS, 
        0, 
        NULL, 
        OPEN_EXISTING, 
        NULL, 
        NULL);

    if(m_hFileMiniDump==INVALID_HANDLE_VALUE)
    {
        Close();
        return 1;
    }

    m_hFileMapping = CreateFileMapping(
        m_hFileMiniDump, 
        NULL, 
        PAGE_READONLY, 
        0, 
        0, 
        0);

    if(m_hFileMapping==NULL)
    {
        Close();
        return 2;
    }

    m_pMiniDumpStartPtr = MapViewOfFile(
        m_hFileMapping, 
        FILE_MAP_READ, 
        0, 
        0, 
        0);

    if(m_pMiniDumpStartPtr==NULL)
    {    
        Close();
        return 3;
    }

    m_DumpData.m_hProcess = (HANDLE)(++dwProcessID);  

    DWORD dwOptions = 0;
    //dwOptions |= SYMOPT_DEFERRED_LOADS; // Symbols are not loaded until a reference is made requiring the symbols be loaded.
    dwOptions |= SYMOPT_EXACT_SYMBOLS; // Do not load an unmatched .pdb file. 
    dwOptions |= SYMOPT_FAIL_CRITICAL_ERRORS; // Do not display system dialog boxes when there is a media failure such as no media in a drive.
    dwOptions |= SYMOPT_UNDNAME; // All symbols are presented in undecorated form.   
    SymSetOptions(dwOptions);

    strconv_t strconv;
    BOOL bSymInit = SymInitializeW(
        m_DumpData.m_hProcess,
        strconv.t2w(sSymSearchPath), 
        FALSE);

    if(!bSymInit)
    {
        m_DumpData.m_hProcess = NULL;
        Close();
        return 5;
    }

    /*SymRegisterCallbackW64(
    m_DumpData.m_hProcess, 
    SymRegisterCallbackProc64,
    (ULONG64)this);*/

    m_bReadSysInfoStream = !ReadSysInfoStream();  
    m_bReadModuleListStream = !ReadModuleListStream();
    m_bReadThreadListStream = !ReadThreadListStream();
    m_bReadMemoryListStream = !ReadMemoryListStream();    
    m_bReadExceptionStream = !ReadExceptionStream();    

    m_bLoaded = true;
    return 0;
}
Ejemplo n.º 12
0
void julia_init(char *imageFile)
{
    jl_page_size = jl_getpagesize();
    jl_find_stack_bottom();
    jl_dl_handle = jl_load_dynamic_library(NULL, JL_RTLD_DEFAULT);
#ifdef _OS_WINDOWS_
    uv_dlopen("ntdll.dll",jl_ntdll_handle); //bypass julia's pathchecking for system dlls
    uv_dlopen("Kernel32.dll",jl_kernel32_handle);
    uv_dlopen("msvcrt.dll",jl_crtdll_handle);
    uv_dlopen("Ws2_32.dll",jl_winsock_handle);
    _jl_exe_handle.handle = GetModuleHandleA(NULL);
#if defined(_CPU_X86_64_)
    SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS);
    SymInitialize(GetCurrentProcess(), NULL, 1);
    needsSymRefreshModuleList = 0;
#endif
#endif
    jl_io_loop = uv_default_loop(); //this loop will internal events (spawining process etc.)
    init_stdio();

#if defined(__linux__)
    int ncores = jl_cpu_cores();
    if (ncores > 1) {
        cpu_set_t cpumask;
        CPU_ZERO(&cpumask);
        for(int i=0; i < ncores; i++) {
            CPU_SET(i, &cpumask);
        }
        sched_setaffinity(0, sizeof(cpu_set_t), &cpumask);
    }
#endif

#ifdef JL_GC_MARKSWEEP
    jl_gc_init();
    jl_gc_disable();
#endif
    jl_init_frontend();
    jl_init_types();
    jl_init_tasks(jl_stack_lo, jl_stack_hi-jl_stack_lo);
    jl_init_codegen();
    jl_an_empty_cell = (jl_value_t*)jl_alloc_cell_1d(0);

    jl_init_serializer();

    if (!imageFile) {
        jl_main_module = jl_new_module(jl_symbol("Main"));
        jl_main_module->parent = jl_main_module;
        jl_core_module = jl_new_module(jl_symbol("Core"));
        jl_core_module->parent = jl_main_module;
        jl_set_const(jl_main_module, jl_symbol("Core"),
                     (jl_value_t*)jl_core_module);
        jl_module_using(jl_main_module, jl_core_module);
        jl_current_module = jl_core_module;
        jl_init_intrinsic_functions();
        jl_init_primitives();
        jl_load("boot.jl");
        jl_get_builtin_hooks();
        jl_boot_file_loaded = 1;
        jl_init_box_caches();
    }

    if (imageFile) {
        JL_TRY {
            jl_restore_system_image(imageFile);
        }
        JL_CATCH {
            JL_PRINTF(JL_STDERR, "error during init:\n");
            jl_show(jl_stderr_obj(), jl_exception_in_transit);
            JL_PRINTF(JL_STDERR, "\n");
            jl_exit(1);
        }
    }

    // set module field of primitive types
    int i;
    void **table = jl_core_module->bindings.table;
    for(i=1; i < jl_core_module->bindings.size; i+=2) {
        if (table[i] != HT_NOTFOUND) {
            jl_binding_t *b = (jl_binding_t*)table[i];
            if (b->value && jl_is_datatype(b->value)) {
                jl_datatype_t *tt = (jl_datatype_t*)b->value;
                tt->name->module = jl_core_module;
            }
        }
    }

    // the Main module is the one which is always open, and set as the
    // current module for bare (non-module-wrapped) toplevel expressions.
    // it does "using Base" if Base is available.
    if (jl_base_module != NULL) {
        jl_add_standard_imports(jl_main_module);
    }
    // eval() uses Main by default, so Main.eval === Core.eval
    jl_module_import(jl_main_module, jl_core_module, jl_symbol("eval"));
    jl_current_module = jl_main_module;

#ifndef _OS_WINDOWS_
    struct sigaction actf;
    memset(&actf, 0, sizeof(struct sigaction));
    sigemptyset(&actf.sa_mask);
    actf.sa_handler = fpe_handler;
    actf.sa_flags = 0;
    if (sigaction(SIGFPE, &actf, NULL) < 0) {
        JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno));
        jl_exit(1);
    }

    stack_t ss;
    ss.ss_flags = 0;
    ss.ss_size = SIGSTKSZ;
    ss.ss_sp = malloc(ss.ss_size);
    if (sigaltstack(&ss, NULL) < 0) {
        JL_PRINTF(JL_STDERR, "sigaltstack: %s\n", strerror(errno));
        jl_exit(1);
    }

    struct sigaction act;
    memset(&act, 0, sizeof(struct sigaction));
    sigemptyset(&act.sa_mask);
    act.sa_sigaction = segv_handler;
    act.sa_flags = SA_ONSTACK | SA_SIGINFO;
    if (sigaction(SIGSEGV, &act, NULL) < 0) {
        JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno));
        jl_exit(1);
    }

    if (signal(SIGPIPE,SIG_IGN) == SIG_ERR) {
        JL_PRINTF(JL_STDERR, "Couldn't set SIGPIPE\n");
        jl_exit(1);
    }
#else
    if (signal(SIGFPE, (void (__cdecl *)(int))fpe_handler) == SIG_ERR) {
        JL_PRINTF(JL_STDERR, "Couldn't set SIGFPE\n");
        jl_exit(1);
    }
#endif


#ifdef JL_GC_MARKSWEEP
    jl_gc_enable();
#endif
}
Ejemplo n.º 13
0
//https://msdn.microsoft.com/en-us/library/windows/desktop/bb204633(v=vs.85).aspx
void Util::getStackTrace(std::string& stream)
{
#ifdef _WIN32
    stream = "===========Call stack===========\n";
    typedef USHORT(WINAPI *CaptureStackBackTraceType)(__in ULONG, __in ULONG, __out PVOID*, __out_opt PULONG);
    CaptureStackBackTraceType func = (CaptureStackBackTraceType)(GetProcAddress(LoadLibraryA("kernel32.dll"), "RtlCaptureStackBackTrace"));

    if (func == NULL)
    {
        stream += "[Error] Failed to resolve Call Stack print function\n";
        return;
    }

    //Set to get the full decorated function name
    DWORD options = SymGetOptions();
    DWORD newOptions = options & ~SYMOPT_UNDNAME;
    newOptions = newOptions | SYMOPT_PUBLICS_ONLY;
    SymSetOptions(newOptions);

    // Quote from Microsoft Documentation:
    // ## Windows Server 2003 and Windows XP:
    // ## The sum of the FramesToSkip and FramesToCapture parameters must be less than 63.
    const int kMaxCallers = 62;

    void         * callers_stack[kMaxCallers];
    unsigned short frames;
    SYMBOL_INFO  * symbol;
    HANDLE         process;
    process = GetCurrentProcess();
    SymInitialize(process, NULL, TRUE);
    frames = (func)(0, kMaxCallers, callers_stack, NULL);
    symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1);
    symbol->MaxNameLen = 255;
    symbol->SizeOfStruct = sizeof(SYMBOL_INFO);

    //printf("(%016I64LX):\n", sample_address);
    //out << "(" << sample_address << "): " << std::endl;
    const unsigned short  MAX_CALLERS_SHOWN = 6;
    frames = frames < MAX_CALLERS_SHOWN ? frames : MAX_CALLERS_SHOWN;
    for (unsigned int i = 0; i < frames; i++)
    {
        SymFromAddr(process, (DWORD64)(callers_stack[i]), 0, symbol);
        //printf("*** %d: %016I64LX %s - 0x%0X\n", i, callers_stack[i], symbol->Name, symbol->Address);

        char undecoratedName[MAX_SYM_NAME];
        //UnDecorateSymbolName(symbol->Name, undecoratedName, MAX_SYM_NAME, UNDNAME_COMPLETE);
        stream += std::string(symbol->Name, symbol->NameLen) + "\n";
        //stream += std::string(undecoratedName) + "\n";

    }

    free(symbol);
    stream += "=======End of Call stack========\n";
#else
    stream = "===========Call stack===========\n";
    void *array[10];
    size_t size = 0;

    size = backtrace(array, 10);
    char** symbols = backtrace_symbols(array, size);

    if(symbols == nullptr)
    {
        printLog(LogMessageType::Error, __FILE__, __LINE__, "Failed to get symbols.");
        return;
    }

    for(size_t i = 0; i < size; i++)
    {
        int status = 0;
        //char* name = abi::__cxa_demangle(symbols[i], tmp, &dms, &status);

        //We have to create the subsequence first
        std::string tmp(symbols[i]);
		size_t tmp_i = tmp.find_first_of('+');
		size_t end_index = tmp_i != std::string::npos ? tmp_i : tmp.length() - 1;
        std::string symbol(tmp.begin() + tmp.find_first_of('(') + 1, tmp.begin() + end_index);

        char* name = abi::__cxa_demangle(symbol.c_str(), nullptr, nullptr, &status);
        if(status != 0)
        {
            //printLog(LogMessageType::Error, __FILE__, __LINE__, "Failed to demangle name \"%s\" with code %d", symbol.c_str(), status);
        }
        if(name == nullptr)
        {
            stream += std::string(symbols[i]) + "\n";
        }
        else
        {
            stream += std::string(name) + "\n";
            free(name);
        }
    }
    stream += "=======End of Call stack========\n";
#endif
}
Ejemplo n.º 14
0
Archivo: init.c Proyecto: aviks/julia
void julia_init(char *imageFile)
{
    jl_page_size = jl_getpagesize();
    jl_find_stack_bottom();
    jl_dl_handle = jl_load_dynamic_library(NULL, JL_RTLD_DEFAULT);
#ifdef _OS_WINDOWS_
    uv_dlopen("ntdll.dll",jl_ntdll_handle); //bypass julia's pathchecking for system dlls
    uv_dlopen("Kernel32.dll",jl_kernel32_handle);
    uv_dlopen("msvcrt.dll",jl_crtdll_handle);
    uv_dlopen("Ws2_32.dll",jl_winsock_handle);
    _jl_exe_handle.handle = GetModuleHandleA(NULL);
    if (!DuplicateHandle( GetCurrentProcess(), GetCurrentThread(),
                          GetCurrentProcess(), (PHANDLE)&hMainThread, 0,
                          TRUE, DUPLICATE_SAME_ACCESS )) {
        JL_PRINTF(JL_STDERR, "Couldn't access handle to main thread\n");
    }
#if defined(_CPU_X86_64_)
    SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS);
    SymInitialize(GetCurrentProcess(), NULL, 1);
    needsSymRefreshModuleList = 0;
#endif
#endif
    jl_io_loop = uv_default_loop(); //this loop will internal events (spawining process etc.)
    init_stdio();

#if defined(__linux__)
    int ncores = jl_cpu_cores();
    if (ncores > 1) {
        cpu_set_t cpumask;
        CPU_ZERO(&cpumask);
        for(int i=0; i < ncores; i++) {
            CPU_SET(i, &cpumask);
        }
        sched_setaffinity(0, sizeof(cpu_set_t), &cpumask);
    }
#endif

#ifdef JL_GC_MARKSWEEP
    jl_gc_init();
    jl_gc_disable();
#endif
    jl_init_frontend();
    jl_init_types();
    jl_init_tasks(jl_stack_lo, jl_stack_hi-jl_stack_lo);
    jl_init_codegen();
    jl_an_empty_cell = (jl_value_t*)jl_alloc_cell_1d(0);

    jl_init_serializer();

    if (!imageFile) {
        jl_main_module = jl_new_module(jl_symbol("Main"));
        jl_main_module->parent = jl_main_module;
        jl_core_module = jl_new_module(jl_symbol("Core"));
        jl_core_module->parent = jl_main_module;
        jl_set_const(jl_main_module, jl_symbol("Core"),
                     (jl_value_t*)jl_core_module);
        jl_module_using(jl_main_module, jl_core_module);
        jl_current_module = jl_core_module;
        jl_init_intrinsic_functions();
        jl_init_primitives();
        jl_load("boot.jl");
        jl_get_builtin_hooks();
        jl_boot_file_loaded = 1;
        jl_init_box_caches();
    }

    if (imageFile) {
        JL_TRY {
            jl_restore_system_image(imageFile);
        }
        JL_CATCH {
            JL_PRINTF(JL_STDERR, "error during init:\n");
            jl_show(jl_stderr_obj(), jl_exception_in_transit);
            JL_PRINTF(JL_STDERR, "\n");
            jl_exit(1);
        }
    }

    // set module field of primitive types
    int i;
    void **table = jl_core_module->bindings.table;
    for(i=1; i < jl_core_module->bindings.size; i+=2) {
        if (table[i] != HT_NOTFOUND) {
            jl_binding_t *b = (jl_binding_t*)table[i];
            if (b->value && jl_is_datatype(b->value)) {
                jl_datatype_t *tt = (jl_datatype_t*)b->value;
                tt->name->module = jl_core_module;
            }
        }
    }

    // the Main module is the one which is always open, and set as the
    // current module for bare (non-module-wrapped) toplevel expressions.
    // it does "using Base" if Base is available.
    if (jl_base_module != NULL) {
        jl_add_standard_imports(jl_main_module);
    }
    // eval() uses Main by default, so Main.eval === Core.eval
    jl_module_import(jl_main_module, jl_core_module, jl_symbol("eval"));
    jl_current_module = jl_main_module;


#ifndef _OS_WINDOWS_
    signal_stack = malloc(SIGSTKSZ);
    struct sigaction actf;
    memset(&actf, 0, sizeof(struct sigaction));
    sigemptyset(&actf.sa_mask);
    actf.sa_handler = fpe_handler;
    actf.sa_flags = 0;
    if (sigaction(SIGFPE, &actf, NULL) < 0) {
        JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno));
        jl_exit(1);
    }
#if defined(_OS_LINUX_)
    stack_t ss;
    ss.ss_flags = 0;
    ss.ss_size = SIGSTKSZ;
    ss.ss_sp = signal_stack;
    if (sigaltstack(&ss, NULL) < 0) {
        JL_PRINTF(JL_STDERR, "sigaltstack: %s\n", strerror(errno));
        jl_exit(1);
    }

    struct sigaction act;
    memset(&act, 0, sizeof(struct sigaction));
    sigemptyset(&act.sa_mask);
    act.sa_sigaction = segv_handler;
    act.sa_flags = SA_ONSTACK | SA_SIGINFO;
    if (sigaction(SIGSEGV, &act, NULL) < 0) {
        JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno));
        jl_exit(1);
    }

    if (signal(SIGPIPE,SIG_IGN) == SIG_ERR) {
        JL_PRINTF(JL_STDERR, "Couldn't set SIGPIPE\n");
        jl_exit(1);
    }
#elif defined (_OS_DARWIN_)
    kern_return_t ret;
    mach_port_t self = mach_task_self();
    ret = mach_port_allocate(self,MACH_PORT_RIGHT_RECEIVE,&segv_port);
    HANDLE_MACH_ERROR("mach_port_allocate",ret);
    ret = mach_port_insert_right(self,segv_port,segv_port,MACH_MSG_TYPE_MAKE_SEND);
    HANDLE_MACH_ERROR("mach_port_insert_right",ret);

    // Alright, create a thread to serve as the listener for exceptions
    pthread_t thread;
    pthread_attr_t attr;
    if (pthread_attr_init(&attr) != 0)
    {
        JL_PRINTF(JL_STDERR, "pthread_attr_init failed");
        jl_exit(1);
    }
    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
    if (pthread_create(&thread,&attr,mach_segv_listener,NULL) != 0)
    {
        JL_PRINTF(JL_STDERR, "pthread_create failed");
        jl_exit(1);
    }
    pthread_attr_destroy(&attr);

    ret = task_set_exception_ports(self,EXC_MASK_BAD_ACCESS,segv_port,EXCEPTION_DEFAULT,MACHINE_THREAD_STATE);
    HANDLE_MACH_ERROR("task_set_exception_ports",ret);
#endif
#else
    if (signal(SIGFPE, (void (__cdecl *)(int))fpe_handler) == SIG_ERR) {
        JL_PRINTF(JL_STDERR, "Couldn't set SIGFPE\n");
        jl_exit(1);
    }
#endif


#ifdef JL_GC_MARKSWEEP
    jl_gc_enable();
#endif
}
Ejemplo n.º 15
0
Archivo: mye.cpp Proyecto: kilitary/mye
int exceptionHandler(unsigned int code, struct _EXCEPTION_POINTERS *e)
{
    char strCode[128];
    bool canContinue;
    int numException = 0;
    char szTemp[1024];
    PEXCEPTION_POINTERS eNext = e;
    PEXCEPTION_RECORD excRec;
    static DWORD numCall = 0;

    if (numCall++ >= 4)
        ExitProcess(0);

    _snprintf(szTemp, sizeof(szTemp), "!!! exceptionHandler(0x%08p)->0x%08p  [ %03d ] *************************** !!!",
        e, e->ExceptionRecord, numCall);
    // OutputDebugString(szTemp);
    deb(szTemp);

    _snprintf(szTemp, sizeof(szTemp),
        "eax=0x%08X ebx=0x%08X ecx=0x%08X edx=0x%08X\r\nesi=0x%08X edi=0x%08X esp=0x%08X ebp=0x%08X",
        eNext->ContextRecord->Eax, eNext->ContextRecord->Ebx, eNext->ContextRecord->Ecx, eNext->ContextRecord->Edx,
        eNext->ContextRecord->Esi, eNext->ContextRecord->Edi, eNext->ContextRecord->Esp, eNext->ContextRecord->Ebp);
    // OutputDebugString(szTemp);
    deb(szTemp);

    do
    {
        excRec = eNext->ExceptionRecord;

        numException++;

        // deb(" -> # %-4d 0x%08p", numException, excRec);
        // deb("code: %x", excRec->ExceptionCode);

        canContinue = excRec->ExceptionFlags == EXCEPTION_NONCONTINUABLE ? true:false;
        // deb("canContinue: %d", canContinue);

        if (excRec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
        {
            _snprintf(strCode, sizeof(strCode), "Access violation (%s @ 0x%08p)",
                excRec->ExceptionInformation[0] ? "WRITE":"READ", excRec->ExceptionInformation[1]);
        }
        else
            if (excRec->ExceptionCode == EXCEPTION_IN_PAGE_ERROR)
            {
                _snprintf(strCode, sizeof(strCode), "Access in-page violation (%s @ 0x%08p) ntcode: %d",
                    excRec->ExceptionInformation[0] ? "READ":"WRITE", excRec->ExceptionInformation[1],
                    excRec->ExceptionInformation[2]);
            }
            else
            {
                _snprintf(strCode, sizeof(strCode), "<unkcode=%X> d0: 0x%08x d1: 0x%08x d2: 0x%08x",
                    excRec->ExceptionCode, excRec->ExceptionInformation[0], excRec->ExceptionInformation[1],
                    excRec->ExceptionInformation[2]);
            }

        _snprintf(szTemp, sizeof(szTemp), "Exception 0x%08X %s Address=0x%08X canContinue=%s", excRec->ExceptionCode,
            strCode, excRec->ExceptionAddress, canContinue ? "yes":"no");
        deb(szTemp);

        if (!eNext->ExceptionRecord->ExceptionRecord)
            break;

        excRec = eNext->ExceptionRecord->ExceptionRecord;
        eNext->ExceptionRecord = eNext->ExceptionRecord->ExceptionRecord;

    }
    while (excRec->ExceptionRecord);

    // find symbols
    LPAPI_VERSION av = ImagehlpApiVersion();
    // deb("dbghelp.dll: %d.%d rev:%d", av->MajorVersion, av->MinorVersion, av->Revision);

    int ret = SymInitialize(GetCurrentProcess(), "c:\\symbols", TRUE);
    SymSetOptions(SYMOPT_UNDNAME | SYMOPT_ALLOW_ABSOLUTE_SYMBOLS | SYMOPT_DEFERRED_LOADS | 0x01000000 |
        SYMOPT_CASE_INSENSITIVE | SYMOPT_LOAD_ANYTHING | SYMOPT_LOAD_LINES);
    if (!ret)
        deb("syminit failed: code=%d, %s", ret, fmterr());

    PSYMBOL_INFO si;
    unsigned long stackPtr = e->ContextRecord->Esp;
    DWORD dwDisp = false;
    unsigned __int64 dwDisp64 = false;
    LPVOID addr;

    si = (PSYMBOL_INFO)malloc(4096);

    for (int i = 0;i<100;i++)
    {
        memset(si, 0, 4096);
        // si.Name = (char*) a(128);
        si->MaxNameLen = 3000;
        si->SizeOfStruct = sizeof(SYMBOL_INFO) + 3000;

        memcpy((void*) &addr, (void*)stackPtr, 4);

        char szTemp[128];

        memset(szTemp, 0, sizeof(szTemp));
        si->Address = (unsigned __int64)addr;
        // get sym module name
        ret = SymFromAddr(GetCurrentProcess(), (unsigned __int64)addr, &dwDisp64, si);
        // if(ret)
        snprintf(szTemp, sizeof(szTemp), "  %03d 0x%08X :%-25s", i, addr, si->Name);

        // get sym module line number
        IMAGEHLP_LINE64 il;

        memset(&il, 0, sizeof(il));
        il.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
        il.Address = (unsigned __int64)addr;
        ret = SymGetLineFromAddr64(GetCurrentProcess(), (unsigned __int64)addr, &dwDisp, &il);

        char szTemp2[128];

        memset(szTemp2, 0, sizeof(szTemp2));

        if (il.LineNumber)
            snprintf(szTemp2, sizeof(szTemp2), "  %s:%d (0x%08X)", il.FileName, il.LineNumber, il.Address);

        // show line info

        if (addr && (strlen(szTemp) || strlen(szTemp2)))
            deb("  %s %s", szTemp, szTemp2[0] ? szTemp2:"");

        stackPtr -= 4;
    }
    // ret=SymEnumSymbols(GetCurrentProcess(), 0, "!", EnumSymProc, NULL);
    // if(!ret)
    // deb("enum err: %s", fmterr());

    deb("!!! exceptionHandler out\r\n");

    // EXCEPTION_CONTINUE_EXECUTION
    // EXCEPTION_EXECUTE_HANDLER

    return EXCEPTION_EXECUTE_HANDLER;
}
Ejemplo n.º 16
0
DbgHelp::DbgHelp(HANDLE process)
: mProcess(process)
, mDbgHelp(0)
, mMutex()
, mSymGetModuleInfo64(0)  
, mSymLoadModule64(0)   
, mSymInitialize(0)   
, mSymUnloadModule64(0)
, mSymEnumerateModules64(0)
, mSymCleanup(0)  
, mSymFunctionTableAccess64(0)
, mSymGetModuleBase64(0)
, mSymGetSymFromAddr64(0)
, mSymSetOptions(0)     
, mSymGetOptions(0)     
, mUnDecorateSymbolName(0)  
, mSymUnDName64(0)  
, mStackWalk64(0)
, mMiniDumpWriteDump(0)
//, mSymRegisterCallback64(0)
// currently not used:
//, mSymEnumSymbols(0)
//, mSymEnumTypes(0)
//, mSymSetContext(0)
//, mSymGetTypeInfo(0)
//, mImagehlpApiVersion(0)
{
  if(!mProcess)
  {
    throw StackDumpException(__FILE__, __LINE__, "DbgHelp: invalid process handle passed");
  }

  //
  // Load dbgHelp.dll and map the functions we need
  //
  if((mDbgHelp = ::LoadLibraryW(cDbgHelpDllPath)) == 0)
  {
    throw StackDumpException(__FILE__, __LINE__, "DbgHelp: Failed to load dbgHelp.dll");        
  }

  // Map function pointers
  if(0 == (mSymGetModuleInfo64    = reinterpret_cast<SymGetModuleInfo64Fnc>   (GetProcAddress(mDbgHelp, "SymGetModuleInfo64"))))      throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymGetModuleInfo64");
  if(0 == (mSymLoadModule64     = reinterpret_cast<SymLoadModule64Fnc>      (GetProcAddress(mDbgHelp, "SymLoadModule64"))))       throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymLoadModule64");     
  if(0 == (mSymInitialize       = reinterpret_cast<SymInitializeFnc>      (GetProcAddress(mDbgHelp, "SymInitialize"))))       throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymInitialize");     
  if(0 == (mSymUnloadModule64     = reinterpret_cast<SymUnloadModule64Fnc>    (GetProcAddress(mDbgHelp, "SymUnloadModule64"))))     throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymUnloadModule64");   
  if(0 == (mSymEnumerateModules64   = reinterpret_cast<SymEnumerateModules64Fnc>  (GetProcAddress(mDbgHelp, "SymEnumerateModules64"))))   throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymEnumerateModules64");
  if(0 == (mSymCleanup        = reinterpret_cast<SymCleanupFnc>       (GetProcAddress(mDbgHelp, "SymCleanup"))))          throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymCleanup");        
  if(0 == (mSymFunctionTableAccess64  = reinterpret_cast<SymFunctionTableAccess64Fnc> (GetProcAddress(mDbgHelp, "SymFunctionTableAccess64"))))  throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymFunctionTableAccess64");  
  if(0 == (mSymGetModuleBase64    = reinterpret_cast<SymGetModuleBase64Fnc>   (GetProcAddress(mDbgHelp, "SymGetModuleBase64"))))      throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymGetModuleBase64");    
  if(0 == (mSymGetSymFromAddr64   = reinterpret_cast<SymGetSymFromAddr64Fnc>    (GetProcAddress(mDbgHelp, "SymGetSymFromAddr64"))))     throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymGetSymFromAddr64");   
  if(0 == (mSymSetOptions       = reinterpret_cast<SymSetOptionsFnc>      (GetProcAddress(mDbgHelp, "SymSetOptions"))))       throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymSetOptions");     
  if(0 == (mSymGetOptions       = reinterpret_cast<SymGetOptionsFnc>      (GetProcAddress(mDbgHelp, "SymGetOptions"))))       throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymGetOptions");     
  if(0 == (mUnDecorateSymbolName    = reinterpret_cast<UnDecorateSymbolNameFnc>   (GetProcAddress(mDbgHelp, "UnDecorateSymbolName"))))    throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: UnDecorateSymbolName");    
  if(0 == (mSymUnDName64        = reinterpret_cast<SymUnDName64Fnc>       (GetProcAddress(mDbgHelp, "SymUnDName64"))))        throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymUnDName64");        
  if(0 == (mStackWalk64       = reinterpret_cast<StackWalk64Fnc>        (GetProcAddress(mDbgHelp, "StackWalk64"))))         throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: StackWalk64");       
  if(0 == (mMiniDumpWriteDump = reinterpret_cast<MiniDumpWriteDumpFnc>  (GetProcAddress(mDbgHelp, "MiniDumpWriteDump"))))         throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: MiniDumpWriteDump");       
  //if(0 == (mSymRegisterCallback64   = reinterpret_cast<SymRegisterCallback64Fnc>  (GetProcAddress(mDbgHelp, "SymRegisterCallback64"))))   throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymRegisterCallback64"); 
// currently not used:
//  if(0 == (mSymEnumSymbols      = reinterpret_cast<SymEnumTypesFnc>       (GetProcAddress(mDbgHelp, "SymEnumSymbols"))))        throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymEnumSymbols");        
//  if(0 == (mSymEnumTypes        = reinterpret_cast<SymEnumSymbolsFnc>     (GetProcAddress(mDbgHelp, "SymEnumTypes"))))        throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymEnumTypes");      
//  if(0 == (mSymSetContext       = reinterpret_cast<SymSetContextFnc>      (GetProcAddress(mDbgHelp, "SymSetContext"))))       throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymSetContext");
//  if(0 == (mSymGetTypeInfo      = reinterpret_cast<SymGetTypeInfoFnc>     (GetProcAddress(mDbgHelp, "SymGetTypeInfo"))))        throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymGetTypeInfo");      
//  if(0 == (mImagehlpApiVersion    = reinterpret_cast<ImagehlpApiVersionFnc>   (GetProcAddress(mDbgHelp, "ImagehlpApiVersion"))))      throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: ImagehlpApiVersion");    

  //
  // Initialize dbgHelp lib
  //
  if(!SymInitialize(0, false))            // set no user path since we're manually loading all modules
  {
    ::FreeLibrary(mDbgHelp);
    // don't use NcErrorFacade to throw, since it would try to log a callstack
    throw StackDumpException(__FILE__, __LINE__, "DbgHelp: Failed to initialize");        
  }

  // Set options
  DWORD symOptions = SymGetOptions();
  symOptions &= ~SYMOPT_UNDNAME;        // We undecorate names manually since that enable us to get more info
  symOptions |= SYMOPT_PUBLICS_ONLY;      // Needed to get types of function parameters, sacrificing access to private and local info
//  symOptions |= SYMOPT_DEBUG;
  SymSetOptions(symOptions);
//  SymRegisterCallback64(traceEvents, 0);
}
/**
 * Initializes the symbol engine if needed.
 */ 
bool FWindowsPlatformStackWalk::InitStackWalking()
{
	// DbgHelp functions are not thread safe, but this function can potentially be called from different
	// threads in our engine, so we take a critical section
	static FCriticalSection CriticalSection;
	FScopeLock Lock( &CriticalSection );

	// Only initialize once.
	if( !GStackWalkingInitialized )
	{
		void* DllHandle = FPlatformProcess::GetDllHandle( TEXT("PSAPI.DLL") );
		if( DllHandle == NULL )
		{
			return false;
		}

		// Load dynamically linked PSAPI routines.
		FEnumProcesses			= (TFEnumProcesses)			FPlatformProcess::GetDllExport( DllHandle,TEXT("EnumProcesses"));
		FEnumProcessModules		= (TFEnumProcessModules)	FPlatformProcess::GetDllExport( DllHandle,TEXT("EnumProcessModules"));
#if WINVER > 0x502
		FGetModuleFileNameEx	= (TFGetModuleFileNameEx)	FPlatformProcess::GetDllExport( DllHandle,TEXT("GetModuleFileNameExW"));
		FGetModuleBaseName		= (TFGetModuleBaseName)		FPlatformProcess::GetDllExport( DllHandle,TEXT("GetModuleBaseNameW"));
#else
		FGetModuleFileNameEx	= (TFGetModuleFileNameEx)	FPlatformProcess::GetDllExport( DllHandle,TEXT("GetModuleFileNameExA"));
		FGetModuleBaseName		= (TFGetModuleBaseName)		FPlatformProcess::GetDllExport( DllHandle,TEXT("GetModuleBaseNameA"));
#endif
		FGetModuleInformation	= (TFGetModuleInformation)	FPlatformProcess::GetDllExport( DllHandle,TEXT("GetModuleInformation"));

		// Abort if we can't look up the functions.
		if( !FEnumProcesses || !FEnumProcessModules || !FGetModuleFileNameEx || !FGetModuleBaseName || !FGetModuleInformation )
		{
			return false;
		}

		// Set up the symbol engine.
		uint32 SymOpts = SymGetOptions();

		SymOpts |= SYMOPT_LOAD_LINES;
		SymOpts |= SYMOPT_FAIL_CRITICAL_ERRORS;
		SymOpts |= SYMOPT_DEFERRED_LOADS;
		SymOpts |= SYMOPT_EXACT_SYMBOLS;

		// This option allows for undecorated names to be handled by the symbol engine.
		SymOpts |= SYMOPT_UNDNAME;

		// Disable by default as it can be very spammy/slow.  Turn it on if you are debugging symbol look-up!
		//		SymOpts |= SYMOPT_DEBUG;

		// Not sure these are important or desirable
		//		SymOpts |= SYMOPT_ALLOW_ABSOLUTE_SYMBOLS;
		//		SymOpts |= SYMOPT_CASE_INSENSITIVE;

		SymSetOptions( SymOpts );
	
		// Initialize the symbol engine.		
		const FString RemoteStorage = GetRemoteStorage(GetDownstreamStorage());
#if WINVER > 0x502
		SymInitializeW( GetCurrentProcess(), RemoteStorage.IsEmpty() ? nullptr : *RemoteStorage, true );
#else
		SymInitialize( GetCurrentProcess(), nullptr, true );
#endif
	
		GNeedToRefreshSymbols = false;
		GStackWalkingInitialized = true;

		if (!FPlatformProperties::IsMonolithicBuild() && FPlatformStackWalk::WantsDetailedCallstacksInNonMonolithicBuilds())
		{
			LoadProcessModules( RemoteStorage );
		}			
	}
#if WINVER > 0x502
	else if (GNeedToRefreshSymbols)
	{
		// Refresh and reload symbols
		SymRefreshModuleList( GetCurrentProcess() );
		if (!FPlatformProperties::IsMonolithicBuild() && FPlatformStackWalk::WantsDetailedCallstacksInNonMonolithicBuilds())
		{
			const FString RemoteStorage = GetRemoteStorage( GetDownstreamStorage() );
			LoadProcessModules( RemoteStorage );
		}
		GNeedToRefreshSymbols = false;
	}
#endif

	return GStackWalkingInitialized;
}
Ejemplo n.º 18
0
	void printCallStack()
	{
		SymInitialize(GetCurrentProcess(), NULL, TRUE);
		SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
		DWORD mtype;
		CONTEXT ctx;
		ZeroMemory(&ctx, sizeof(CONTEXT));
		ctx.ContextFlags = CONTEXT_CONTROL;
		RtlCaptureContext(&ctx);

		STACKFRAME64 stack;
		ZeroMemory(&stack, sizeof(STACKFRAME64));
#ifdef _M_IX86
		mtype = IMAGE_FILE_MACHINE_I386;
		stack.AddrPC.Offset = ctx.Eip;
		stack.AddrPC.Mode = AddrModeFlat;
		stack.AddrFrame.Offset = ctx.Ebp;
		stack.AddrFrame.Mode = AddrModeFlat;
		stack.AddrStack.Offset = ctx.Esp;
		stack.AddrStack.Mode = AddrModeFlat;
#elif _M_X64
		mtype = IMAGE_FILE_MACHINE_AMD64;
		stack.AddrPC.Offset = ctx.Rip;
		stack.AddrPC.Mode = AddrModeFlat;
		stack.AddrFrame.Offset = ctx.Rsp;
		stack.AddrFrame.Mode = AddrModeFlat;
		stack.AddrStack.Offset = ctx.Rsp;
		stack.AddrStack.Mode = AddrModeFlat;
#endif

		DWORD ldsp = 0;
		IMAGEHLP_LINE64 line;
		ZeroMemory(&line, sizeof(IMAGEHLP_LINE64));
		line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);

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

		UINT num = 0;
		while (StackWalk64(mtype,
			GetCurrentProcess(),
			GetCurrentThread(),
			&stack,
			&ctx,
			NULL,
			SymFunctionTableAccess64,
			SymGetModuleBase64,
			NULL))
		{

			if (stack.AddrPC.Offset == 0)
			{
				break;
			}

			++num;
			BOOL res = SymGetLineFromAddr64(GetCurrentProcess(), stack.AddrPC.Offset, &ldsp, &line);
			res = res && SymFromAddr(GetCurrentProcess(), stack.AddrPC.Offset, 0, sym);

			if (res == TRUE)
			{
				// TODO replace with inner
				printf("\t[%i] %s (%s:%d)\n", num, sym->Name, line.FileName, line.LineNumber);
			}
			else
			{
				// TODO replace with inner
				printf("\t[%i] 0x%p\n", num, stack.AddrPC.Offset);
			}
		}

		SymCleanup(GetCurrentProcess());
	}
Ejemplo n.º 19
0
//----------------------------------------------------------------------------//
static void dumpBacktrace(size_t frames)
{
#if defined(_DEBUG) || defined(DEBUG)
#if defined(_MSC_VER)
    SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_INCLUDE_32BIT_MODULES);

    if (!SymInitialize(GetCurrentProcess(), 0, TRUE))
        return;

    HANDLE thread = GetCurrentThread();

    CONTEXT context;
    RtlCaptureContext(&context);

    STACKFRAME64 stackframe;
    ZeroMemory(&stackframe, sizeof(stackframe));
    stackframe.AddrPC.Mode = AddrModeFlat;
    stackframe.AddrStack.Mode = AddrModeFlat;
    stackframe.AddrFrame.Mode = AddrModeFlat;

#if _M_IX86
    stackframe.AddrPC.Offset = context.Eip;
    stackframe.AddrStack.Offset = context.Esp;
    stackframe.AddrFrame.Offset = context.Ebp;
    DWORD machine_arch = IMAGE_FILE_MACHINE_I386;
#elif _M_X64
    stackframe.AddrPC.Offset = context.Rip;
    stackframe.AddrStack.Offset = context.Rsp;
    stackframe.AddrFrame.Offset = context.Rbp;
    DWORD machine_arch = IMAGE_FILE_MACHINE_AMD64;
#endif

    char symbol_buffer[1024];
    ZeroMemory(symbol_buffer, sizeof(symbol_buffer));
    PSYMBOL_INFO symbol = reinterpret_cast<PSYMBOL_INFO>(symbol_buffer);
    symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
    symbol->MaxNameLen = sizeof(symbol_buffer) - sizeof(SYMBOL_INFO);

    Logger& logger(Logger::getSingleton());
    logger.logEvent("========== Start of Backtrace ==========", Errors);

    size_t frame_no = 0;
    while (StackWalk64(machine_arch, GetCurrentProcess(), thread, &stackframe,
                       &context, 0, SymFunctionTableAccess64, SymGetModuleBase64, 0) &&
           stackframe.AddrPC.Offset)
    {
        symbol->Address = stackframe.AddrPC.Offset;
        DWORD64 displacement = 0;
        char signature[256];

        if (SymFromAddr(GetCurrentProcess(), symbol->Address, &displacement, symbol))
            UnDecorateSymbolName(symbol->Name, signature, sizeof(signature), UNDNAME_COMPLETE);
        else
            sprintf_s(signature, sizeof(signature), "%p", symbol->Address);
 
        IMAGEHLP_MODULE64 modinfo;
        modinfo.SizeOfStruct = sizeof(modinfo);

        const BOOL have_image_name =
            SymGetModuleInfo64(GetCurrentProcess(), symbol->Address, &modinfo);

        char outstr[512];
        sprintf_s(outstr, sizeof(outstr), "#%d %s +%#llx (%s)",
                  frame_no, signature, displacement,
                  (have_image_name ? modinfo.LoadedImageName : "????"));

        logger.logEvent(outstr, Errors);

        if (++frame_no >= frames)
            break;

        if (!stackframe.AddrReturn.Offset)
            break;
    }

    logger.logEvent("==========  End of Backtrace  ==========", Errors);

    SymCleanup(GetCurrentProcess());
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__HAIKU__)
    void* buffer[frames];
    const int received = backtrace(&buffer[0], frames);

    Logger& logger(Logger::getSingleton());

    logger.logEvent("========== Start of Backtrace ==========", Errors);

    for (int i = 0; i < received; ++i)
    {
        char outstr[512];
        Dl_info info;
        if (dladdr(buffer[i], &info))
        {
            if (!info.dli_sname)
                snprintf(outstr, 512, "#%d %p (%s)", i, buffer[i], info.dli_fname);
            else
            {
                ptrdiff_t offset = static_cast<char*>(buffer[i]) -
                                   static_cast<char*>(info.dli_saddr);

                int demangle_result = 0;
                char* demangle_name = abi::__cxa_demangle(info.dli_sname, 0, 0, &demangle_result);
                snprintf(outstr, 512, "#%d %s +%#tx (%s)",
                         i, demangle_name ? demangle_name : info.dli_sname, offset, info.dli_fname);
                std::free(demangle_name);
            }
        }
        else
            snprintf(outstr, 512, "#%d --- error ---", i);

        logger.logEvent(outstr, Errors);
    }

    logger.logEvent("==========  End of Backtrace  ==========", Errors);
#endif
#endif
}
Ejemplo n.º 20
0
LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS* ptrs)
{
	EXCEPTION_RECORD* rec = ptrs->ExceptionRecord;
	CONTEXT* ctx = ptrs->ContextRecord;
	DWORD base = Vars.pModule ? Vars.pModule->dwBaseAddress : (DWORD)Vars.hModule;

	char path[MAX_PATH+_MAX_FNAME] = "";
	sprintf_s(path, sizeof(path), "%s\\D2BS.bin", Vars.szPath);

	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, GetCurrentProcessId());
	HANDLE hThread = GetCurrentThread();
	CONTEXT context = *ctx;

	SymSetOptions(SYMOPT_LOAD_LINES|SYMOPT_FAIL_CRITICAL_ERRORS|SYMOPT_NO_PROMPTS|SYMOPT_DEFERRED_LOADS);
	SymInitialize(hProcess, Vars.szPath, TRUE);
	SymLoadModule64(hProcess, NULL, path, NULL, base, 0);

	STACKFRAME64 stack;
	stack.AddrPC.Offset = context.Eip;
	stack.AddrPC.Mode = AddrModeFlat;
	stack.AddrStack.Offset = context.Esp;
	stack.AddrStack.Mode = AddrModeFlat;
	stack.AddrFrame.Offset = context.Ebp;
	stack.AddrFrame.Mode = AddrModeFlat;

	std::string trace;

	for(int i = 0; i < 64; i++)
	{
		if(!StackWalk64(IMAGE_FILE_MACHINE_I386, hProcess, hThread, &stack, &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
			break;

		// infinite loop
		if(stack.AddrReturn.Offset == stack.AddrPC.Offset)
			break;
		// jump to 0
		if(stack.AddrPC.Offset == 0)
			break;

		SYMBOL_INFO* sym = GetSymFromAddr(hProcess, stack.AddrPC.Offset);

		if(sym)
		{
			char msg[1024];
			ULONG64 base = (sym->Address - sym->ModBase);

			IMAGEHLP_LINE64* line = GetLineFromAddr(hProcess, stack.AddrPC.Offset);
			if(line)
				sprintf_s(msg, 1024, "\t%s+0x%08x, File: %s line %d\n",
						sym->Name, base, strrchr(line->FileName, '\\')+1, line->LineNumber);
			else
				sprintf_s(msg, 1024, "\t%s+0x%08x\n", sym->Name, base);

			trace.append(msg);
			delete line;
		}
		else
		{
			char addr[100];
			sprintf_s(addr, sizeof(addr), "\t0x%08x\n", stack.AddrFrame.Offset);
			trace.append(addr);
		}

		delete[] (char*)sym;
	}

	SYMBOL_INFO* sym = GetSymFromAddr(hProcess, (DWORD64)rec->ExceptionAddress);

	IMAGEHLP_LINE64* line = GetLineFromAddr(hProcess, (DWORD64)rec->ExceptionAddress);

	Log("EXCEPTION!\n*** 0x%08x at 0x%08x (%s in %s line %d)\n"
		"D2BS loaded at: 0x%08x\n"
		"Registers:\n"
		"\tEIP: 0x%08x, ESP: 0x%08x\n"
		"\tCS: 0x%04x, DS: 0x%04x, ES: 0x%04x, SS: 0x%04x, FS: 0x%04x, GS: 0x%04x\n"
		"\tEAX: 0x%08x, EBX: 0x%08x, ECX: 0x%08x, EDX: 0x%08x, ESI: 0x%08x, EDI: 0x%08x, EBP: 0x%08x, FLG: 0x%08x\n"
		"Stack Trace:\n%s\nEnd of stack trace.",
			rec->ExceptionCode, rec->ExceptionAddress,
			sym != NULL ? sym->Name : "Unknown", line != NULL ? strrchr(line->FileName, '\\')+1 : "Unknown", line != NULL ? line->LineNumber : 0,
			base,
			ctx->Eip, ctx->Esp,
			ctx->SegCs, ctx->SegDs, ctx->SegEs, ctx->SegSs, ctx->SegFs, ctx->SegGs,
			ctx->Eax, ctx->Ebx, ctx->Ecx, ctx->Edx, ctx->Esi, ctx->Edi, ctx->Ebp, ctx->EFlags,
			trace.c_str());

	delete[] (char*)sym;
	delete line;

	SymCleanup(hProcess);

	return EXCEPTION_EXECUTE_HANDLER;
}
Ejemplo n.º 21
0
static void	print_backtrace(CONTEXT *pctx)
{
	SymGetLineFromAddrW64_func_t	zbx_SymGetLineFromAddrW64 = NULL;
	SymFromAddr_func_t		zbx_SymFromAddr	= NULL;

	CONTEXT			ctx, ctxcount;
	STACKFRAME64		s, scount;
	PSYMBOL_INFO		pSym = NULL;
	HMODULE			hModule;
	HANDLE			hProcess, hThread;
	DWORD64			offset;
	wchar_t			szProcessName[MAX_PATH];
	char			*process_name = NULL, *process_path = NULL, *frame = NULL;
	size_t			frame_alloc = 0, frame_offset;
	int			nframes = 0;

	ctx = *pctx;

	zabbix_log(LOG_LEVEL_CRIT, "=== Backtrace: ===");

	memset(&s, 0, sizeof(s));

	s.AddrPC.Mode = AddrModeFlat;
	s.AddrFrame.Mode = AddrModeFlat;
	s.AddrStack.Mode = AddrModeFlat;

#ifdef _M_X64
	s.AddrPC.Offset = ctx.Rip;
	s.AddrFrame.Offset = ctx.Rbp;
	s.AddrStack.Offset = ctx.Rsp;
#else
	s.AddrPC.Offset = ctx.Eip;
	s.AddrFrame.Offset = ctx.Ebp;
	s.AddrStack.Offset = ctx.Esp;
#endif
	hProcess = GetCurrentProcess();
	hThread = GetCurrentThread();

	if (0 != GetModuleFileNameEx(hProcess, NULL, szProcessName, ARRSIZE(szProcessName)))
	{
		char	*ptr;
		int	path_alloc = 0, path_offset = 0;

		process_name = zbx_unicode_to_utf8(szProcessName);

		if (NULL != (ptr = strstr(process_name, progname)))
			zbx_strncpy_alloc(&process_path, &path_alloc, &path_offset, process_name, ptr - process_name);
	}

	if (NULL != (hModule = GetModuleHandle(TEXT("DbgHelp.DLL"))))
	{
		zbx_SymGetLineFromAddrW64 = (SymGetLineFromAddrW64_func_t)GetProcAddress(hModule,
				"SymGetLineFromAddr64");
		zbx_SymFromAddr = (SymFromAddr_func_t)GetProcAddress(hModule, "SymFromAddr");
	}

	if (NULL != zbx_SymFromAddr || NULL != zbx_SymGetLineFromAddrW64)
	{
		SymSetOptions(SymGetOptions() | SYMOPT_LOAD_LINES);

		if (FALSE != SymInitialize(hProcess, process_path, TRUE))
		{
			pSym = (PSYMBOL_INFO) zbx_malloc(NULL, sizeof(SYMBOL_INFO) + MAX_SYM_NAME);
			memset(pSym, 0, sizeof(SYMBOL_INFO) + MAX_SYM_NAME);
			pSym->SizeOfStruct = sizeof(SYMBOL_INFO);
			pSym->MaxNameLen = MAX_SYM_NAME;
		}
	}

	scount = s;
	ctxcount = ctx;

	/* get number of frames, ctxcount may be modified during StackWalk64() calls */
	while (TRUE == StackWalk64(ZBX_IMAGE_FILE_MACHINE, hProcess, hThread, &scount, &ctxcount, NULL, NULL, NULL,
			NULL))
	{
		if (0 == scount.AddrReturn.Offset)
			break;
		nframes++;
	}

	while (TRUE == StackWalk64(ZBX_IMAGE_FILE_MACHINE, hProcess, hThread, &s, &ctx, NULL, NULL, NULL, NULL))
	{
		frame_offset = 0;
		zbx_snprintf_alloc(&frame, &frame_alloc, &frame_offset, "%d: %s", nframes--,
				NULL == process_name ? "(unknown)" : process_name);

		if (NULL != pSym)
		{
			DWORD		dwDisplacement;
			IMAGEHLP_LINE64	line = {sizeof(IMAGEHLP_LINE64)};

			zbx_chrcpy_alloc(&frame, &frame_alloc, &frame_offset, '(');
			if (NULL != zbx_SymFromAddr &&
					TRUE == zbx_SymFromAddr(hProcess, s.AddrPC.Offset, &offset, pSym))
			{
				zbx_snprintf_alloc(&frame, &frame_alloc, &frame_offset, "%s+0x%lx", pSym->Name, offset);
			}

			if (NULL != zbx_SymGetLineFromAddrW64 && TRUE == zbx_SymGetLineFromAddrW64(hProcess,
					s.AddrPC.Offset, &dwDisplacement, &line))
			{
				zbx_snprintf_alloc(&frame, &frame_alloc, &frame_offset, " %s:%d", line.FileName,
						line.LineNumber);
			}
			zbx_chrcpy_alloc(&frame, &frame_alloc, &frame_offset, ')');
		}

		zabbix_log(LOG_LEVEL_CRIT, "%s [0x%lx]", frame, s.AddrPC.Offset);

		if (0 == s.AddrReturn.Offset)
			break;
	}

	SymCleanup(hProcess);

	zbx_free(frame);
	zbx_free(process_path);
	zbx_free(process_name);
	zbx_free(pSym);
}
Ejemplo n.º 22
0
int dbg_help_client_t::init(char* path) {
    DWORD64 dwBaseAddr=0;

    int chars;
    char exe_path[MAX_PATH];
    chars = GetModuleFileName(NULL, exe_path, MAX_PATH);
    if (chars == 0) { 
        fprintf(stderr,"Could not find base path for XED executable\n");
        fflush(stderr);
        exit(1);
    }
    //fprintf(stderr,"EXE PATH %s\n", exe_path);
    char* dir = find_base_path(exe_path);
    //fprintf(stderr,"DIR      %s\n", dir);

    char* dbghelp = append3(dir,"\\","dbghelp.dll");
    //fprintf(stderr,"DBGHLP   %s\n", dbghelp);

    if (_access_s(dbghelp,4) != 0) {
        //fprintf(stderr,
        //    "WARNING: Could not find dbghelp.dll in xed.exe directory\n");
        //fflush(stderr);
        return 0;
    }    
    //fprintf(stderr,"FOUND DBGHELP\n");

    if (validate_version(dbghelp)) {
        fprintf(stderr,
            "WARNING: dbghelp.dll version is too old\n");
        fflush(stderr);
        return 0;
    }


    //FIXME: Add a version check for the dll ( ImagehlpApiVersion is NOT
    //the right thing)
        
    SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS);
    hProcess = GetCurrentProcess();
    
    if (SymInitialize(hProcess, NULL, FALSE))     {
        // nothing
    }
    else    {
        error = GetLastError();
        fprintf(stderr,"SymInitialize returned error : %d 0x%x\n",
                error, error);
        fflush(stderr);
        return 0;
    }


    actual_base = SymLoadModuleEx(hProcess, NULL, path, NULL, 
                                  dwBaseAddr, 0, NULL, 0);
    if (actual_base) {
        // nothing
    }
    else    {
        error = GetLastError();
        fprintf(stderr,"SymLoadModuleEx returned error : %d 0x%x\n", 
                error, error);
        fflush(stderr);
        return 0;
    }


    if (SymEnumerateModules64(hProcess, 
                        (PSYM_ENUMMODULES_CALLBACK64)enum_modules, this)) {
        // nothing
    }
    else    {
        error = GetLastError();
        fprintf(stderr,"SymEnumerateModules64 returned error : %d 0x%x\n",
               error, error);
        fflush(stderr);
        return 0;
    }

    if (SymEnumSymbols(hProcess, actual_base, 0, enum_sym, this))    {
        // nothing
    }
    else    {
        error = GetLastError();
        fprintf(stderr,"SymEnumSymbols failed: %d 0x%x\n", error, error);
        fflush(stderr);
        return 0;
    }

    make_symbol_vector(&sym_tab);
    initialized = true;
    return 1;
}
Ejemplo n.º 23
0
static void sym_init(void) {
  proc = GetCurrentProcess();
  SymInitialize(proc, NULL, TRUE);
  SymSetOptions(SYMOPT_LOAD_LINES|SYMOPT_FAIL_CRITICAL_ERRORS|
      SYMOPT_NO_PROMPTS|SYMOPT_UNDNAME);
}
Ejemplo n.º 24
0
int
main(int argc, char **argv)
{
    BOOL bRet;
    DWORD dwRet;
    bool debug = false;
    char *szModule = nullptr;
    bool functions = false;
    bool demangle = false;
    bool pretty = false;

    while (1) {
        int opt = getopt(argc, argv, "?CDe:fHp");

        switch (opt) {
        case 'C':
            demangle = true;
            break;
        case 'D':
            debug = true;
            break;
        case 'e':
            szModule = optarg;
            break;
        case 'f':
            functions = true;
            break;
        case 'H':
            usage(argv[0]);
            return EXIT_SUCCESS;
        case 'p':
            pretty = true;
            break;
        case '?':
            fprintf(stderr, "error: invalid option `%c`\n", optopt);
            /* pass-through */
        default:
            usage(argv[0]);
            return EXIT_FAILURE;
        case -1:
            break;
        }
        if (opt == -1) {
            break;
        }
    }

    if (szModule == nullptr) {
        usage(argv[0]);
        return EXIT_FAILURE;
    }

    // Load the module
    HMODULE hModule = nullptr;
#ifdef _WIN64
    hModule = LoadLibraryExA(szModule, NULL, LOAD_LIBRARY_AS_DATAFILE);
#endif
    if (!hModule) {
        hModule = LoadLibraryExA(szModule, NULL, DONT_RESOLVE_DLL_REFERENCES);
    }
    if (!hModule) {
        fprintf(stderr, "error: failed to load %s\n", szModule);
        return EXIT_FAILURE;
    }

    DWORD dwSymOptions = SymGetOptions();

    dwSymOptions |= SYMOPT_LOAD_LINES;

#ifndef NDEBUG
    dwSymOptions |= SYMOPT_DEBUG;
#endif

    // We can get more information by calling UnDecorateSymbolName() ourselves.
    dwSymOptions &= ~SYMOPT_UNDNAME;
    
    SymSetOptions(dwSymOptions);

    HANDLE hProcess = GetCurrentProcess();
    bRet = InitializeSym(hProcess, FALSE);
    assert(bRet);

    if (debug) {
        SymRegisterCallback64(hProcess, &callback, 0);
    }

    dwRet = SymLoadModuleEx(hProcess, NULL, szModule, NULL, (DWORD64)(UINT_PTR)hModule, 0, NULL, 0);
    if (!dwRet) {
        fprintf(stderr, "warning: failed to load module symbols\n");
    }

    if (!GetModuleHandleA("symsrv.dll")) {
        fprintf(stderr, "warning: symbol server not loaded\n");
    }

    while (optind < argc) {
        const char *arg = argv[optind++];

        DWORD64 dwRelAddr;
        if (arg[0] == '0' && arg[1] == 'x') {
            sscanf(&arg[2], "%08" PRIX64, &dwRelAddr);
        } else {
            dwRelAddr = atol(arg);
        }

        UINT_PTR dwAddr = (UINT_PTR)hModule + dwRelAddr;

        if (functions) {
            struct {
                SYMBOL_INFO Symbol;
                CHAR Name[512];
            } sym;
            char UnDecoratedName[512];
            const char *function = "??";
            ZeroMemory(&sym, sizeof sym);
            sym.Symbol.SizeOfStruct = sizeof sym.Symbol;
            sym.Symbol.MaxNameLen = sizeof sym.Symbol.Name + sizeof sym.Name;
            DWORD64 dwSymDisplacement = 0;
            bRet = SymFromAddr(hProcess, dwAddr, &dwSymDisplacement, &sym.Symbol);
            if (bRet) {
                function = sym.Symbol.Name;
                if (demangle) {
                    if (UnDecorateSymbolName( sym.Symbol.Name, UnDecoratedName, sizeof UnDecoratedName, UNDNAME_COMPLETE)) {
                        function = UnDecoratedName;
                    }
                }
            }
            fputs(function, stdout);
            fputs(pretty ? " at " : "\n", stdout);
        }

        IMAGEHLP_LINE64 line;
        ZeroMemory(&line, sizeof line);
        line.SizeOfStruct = sizeof line;
        DWORD dwLineDisplacement = 0;
        bRet = SymGetLineFromAddr64(hProcess, dwAddr, &dwLineDisplacement, &line);
        if (bRet) {
            fprintf(stdout, "%s:%lu\n", line.FileName, line.LineNumber);
        } else {
            fputs("??:?\n", stdout);
        }
        fflush(stdout);
    }


    SymCleanup(hProcess);


    FreeLibrary(hModule);


    return 0;
}
Ejemplo n.º 25
0
static void
dump_thread(void *arg)
{
    HANDLE dbghelp;
    BOOL (WINAPI *pSymInitialize)(HANDLE, const char *, BOOL);
    BOOL (WINAPI *pSymCleanup)(HANDLE);
    BOOL (WINAPI *pStackWalk64)(DWORD, HANDLE, HANDLE, STACKFRAME64 *, void *, PREAD_PROCESS_MEMORY_ROUTINE64, PFUNCTION_TABLE_ACCESS_ROUTINE64, PGET_MODULE_BASE_ROUTINE64, PTRANSLATE_ADDRESS_ROUTINE64);
    DWORD64 (WINAPI *pSymGetModuleBase64)(HANDLE, DWORD64);
    BOOL (WINAPI *pSymFromAddr)(HANDLE, DWORD64, DWORD64 *, SYMBOL_INFO *);
    BOOL (WINAPI *pSymGetLineFromAddr64)(HANDLE, DWORD64, DWORD *, IMAGEHLP_LINE64 *);
    HANDLE (WINAPI *pOpenThread)(DWORD, BOOL, DWORD);
    DWORD tid = *(DWORD *)arg;
    HANDLE ph;
    HANDLE th;

    dbghelp = LoadLibrary("dbghelp.dll");
    if (!dbghelp) return;
    pSymInitialize = (BOOL (WINAPI *)(HANDLE, const char *, BOOL))GetProcAddress(dbghelp, "SymInitialize");
    pSymCleanup = (BOOL (WINAPI *)(HANDLE))GetProcAddress(dbghelp, "SymCleanup");
    pStackWalk64 = (BOOL (WINAPI *)(DWORD, HANDLE, HANDLE, STACKFRAME64 *, void *, PREAD_PROCESS_MEMORY_ROUTINE64, PFUNCTION_TABLE_ACCESS_ROUTINE64, PGET_MODULE_BASE_ROUTINE64, PTRANSLATE_ADDRESS_ROUTINE64))GetProcAddress(dbghelp, "StackWalk64");
    pSymGetModuleBase64 = (DWORD64 (WINAPI *)(HANDLE, DWORD64))GetProcAddress(dbghelp, "SymGetModuleBase64");
    pSymFromAddr = (BOOL (WINAPI *)(HANDLE, DWORD64, DWORD64 *, SYMBOL_INFO *))GetProcAddress(dbghelp, "SymFromAddr");
    pSymGetLineFromAddr64 = (BOOL (WINAPI *)(HANDLE, DWORD64, DWORD *, IMAGEHLP_LINE64 *))GetProcAddress(dbghelp, "SymGetLineFromAddr64");
    pOpenThread = (HANDLE (WINAPI *)(DWORD, BOOL, DWORD))GetProcAddress(GetModuleHandle("kernel32.dll"), "OpenThread");
    if (pSymInitialize && pSymCleanup && pStackWalk64 && pSymGetModuleBase64 &&
	pSymFromAddr && pSymGetLineFromAddr64 && pOpenThread) {
	SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES);
	ph = GetCurrentProcess();
	pSymInitialize(ph, NULL, TRUE);
	th = pOpenThread(THREAD_SUSPEND_RESUME|THREAD_GET_CONTEXT, FALSE, tid);
	if (th) {
	    if (SuspendThread(th) != (DWORD)-1) {
		CONTEXT context;
		memset(&context, 0, sizeof(context));
		context.ContextFlags = CONTEXT_FULL;
		if (GetThreadContext(th, &context)) {
		    char libpath[MAX_PATH];
		    char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
		    SYMBOL_INFO *info = (SYMBOL_INFO *)buf;
		    DWORD mac;
		    STACKFRAME64 frame;
		    memset(&frame, 0, sizeof(frame));
#if defined(_M_AMD64) || defined(__x86_64__)
		    mac = IMAGE_FILE_MACHINE_AMD64;
		    frame.AddrPC.Mode = AddrModeFlat;
		    frame.AddrPC.Offset = context.Rip;
		    frame.AddrFrame.Mode = AddrModeFlat;
		    frame.AddrFrame.Offset = context.Rbp;
		    frame.AddrStack.Mode = AddrModeFlat;
		    frame.AddrStack.Offset = context.Rsp;
#elif defined(_M_IA64) || defined(__ia64__)
		    mac = IMAGE_FILE_MACHINE_IA64;
		    frame.AddrPC.Mode = AddrModeFlat;
		    frame.AddrPC.Offset = context.StIIP;
		    frame.AddrBStore.Mode = AddrModeFlat;
		    frame.AddrBStore.Offset = context.RsBSP;
		    frame.AddrStack.Mode = AddrModeFlat;
		    frame.AddrStack.Offset = context.IntSp;
#else	/* i386 */
		    mac = IMAGE_FILE_MACHINE_I386;
		    frame.AddrPC.Mode = AddrModeFlat;
		    frame.AddrPC.Offset = context.Eip;
		    frame.AddrFrame.Mode = AddrModeFlat;
		    frame.AddrFrame.Offset = context.Ebp;
		    frame.AddrStack.Mode = AddrModeFlat;
		    frame.AddrStack.Offset = context.Esp;
#endif

		    while (pStackWalk64(mac, ph, th, &frame, &context, NULL,
					NULL, NULL, NULL)) {
			DWORD64 addr = frame.AddrPC.Offset;
			IMAGEHLP_LINE64 line;
			DWORD64 displacement;
			DWORD tmp;

			if (addr == frame.AddrReturn.Offset || addr == 0 ||
			    frame.AddrReturn.Offset == 0)
			    break;

			memset(buf, 0, sizeof(buf));
			info->SizeOfStruct = sizeof(SYMBOL_INFO);
			info->MaxNameLen = MAX_SYM_NAME;
			if (pSymFromAddr(ph, addr, &displacement, info)) {
			    if (GetModuleFileName((HANDLE)(uintptr_t)pSymGetModuleBase64(ph, addr), libpath, sizeof(libpath)))
				fprintf(stderr, "%s", libpath);
			    fprintf(stderr, "(%s+0x%I64x)",
				    info->Name, displacement);
			}
			fprintf(stderr, " [0x%p]", (void *)(VALUE)addr);
			memset(&line, 0, sizeof(line));
			line.SizeOfStruct = sizeof(line);
			if (pSymGetLineFromAddr64(ph, addr, &tmp, &line))
			    fprintf(stderr, " %s:%lu", line.FileName, line.LineNumber);
			fprintf(stderr, "\n");
		    }
		}

		ResumeThread(th);
	    }
	    CloseHandle(th);
	}
	pSymCleanup(ph);
    }
    FreeLibrary(dbghelp);
}
Ejemplo n.º 26
0
void AFXAPI AfxDumpStack(DWORD dwTarget /* = AFX_STACK_DUMP_TARGET_DEFAULT */)
{
	CTraceClipboardData clipboardData(dwTarget);

	clipboardData.SendOut("=== begin AfxDumpStack output ===\r\n");

	CDWordArray adwAddress;
	HANDLE hProcess = ::GetCurrentProcess();
	if (SymInitialize(hProcess, NULL, FALSE))
	{
		// force undecorated names to get params
		DWORD dw = SymGetOptions();
		dw &= ~SYMOPT_UNDNAME;
		SymSetOptions(dw);

		HANDLE hThread = ::GetCurrentThread();
		CONTEXT threadContext;

		threadContext.ContextFlags = CONTEXT_FULL;

		if (::GetThreadContext(hThread, &threadContext))
		{
			STACKFRAME stackFrame;
			memset(&stackFrame, 0, sizeof(stackFrame));
			stackFrame.AddrPC.Mode = AddrModeFlat;

			DWORD dwMachType;

#if defined(_M_IX86)
			dwMachType                  = IMAGE_FILE_MACHINE_I386;

			// program counter, stack pointer, and frame pointer
			stackFrame.AddrPC.Offset    = threadContext.Eip;
			stackFrame.AddrStack.Offset = threadContext.Esp;
			stackFrame.AddrStack.Mode   = AddrModeFlat;
			stackFrame.AddrFrame.Offset = threadContext.Ebp;
			stackFrame.AddrFrame.Mode   = AddrModeFlat;
#elif defined(_M_MRX000)
			// only program counter
			dwMachType                  = IMAGE_FILE_MACHINE_R4000;
			stackFrame.AddrPC. Offset    = treadContext.Fir;
#elif defined(_M_ALPHA)
			// only program counter
			dwMachType                  = IMAGE_FILE_MACHINE_ALPHA;
			stackFrame.AddrPC.Offset    = (unsigned long) threadContext.Fir;
#elif defined(_M_PPC)
			// only program counter
			dwMachType                  = IMAGE_FILE_MACHINE_POWERPC;
			stackFrame.AddrPC.Offset    = threadContext.Iar;
#elif
#error("Unknown Target Machine");
#endif

			adwAddress.SetSize(0, 16);

			int nFrame;
			for (nFrame = 0; nFrame < 1024; nFrame++)
			{
				if (!StackWalk(dwMachType, hProcess, hProcess,
					&stackFrame, &threadContext, NULL,
					FunctionTableAccess, GetModuleBase, NULL))
				{
					break;
				}

				adwAddress.SetAtGrow(nFrame, stackFrame.AddrPC.Offset);
			}
		}
	}
	else
	{
		DWORD dw = GetLastError();
		char sz[100];
		wsprintfA(sz,
			"AfxDumpStack Error: IMAGEHLP.DLL wasn't found. "
			"GetLastError() returned 0x%8.8X\r\n", dw);
		clipboardData.SendOut(sz);
	}

	// dump it out now
	int nAddress;
	int cAddresses = adwAddress.GetSize();
	for (nAddress = 0; nAddress < cAddresses; nAddress++)
	{
		SYMBOL_INFO info;
		DWORD dwAddress = adwAddress[nAddress];

		char sz[20];
		wsprintfA(sz, "%8.8X: ", dwAddress);
		clipboardData.SendOut(sz);

		if (ResolveSymbol(hProcess, dwAddress, info))
		{
			clipboardData.SendOut(info.szModule);
			clipboardData.SendOut(info.szSymbol);
		}
		else
			clipboardData.SendOut("symbol not found");
		clipboardData.SendOut("\r\n");
	}

	clipboardData.SendOut("=== end AfxDumpStack() output ===\r\n");
}
Ejemplo n.º 27
0
    /**
     * Print stack trace (using a specified stack context) to "os"
     * 
     * @param context   CONTEXT record for stack trace
     * @param os        ostream& to receive printed stack backtrace
     */
    void printWindowsStackTrace( CONTEXT& context, std::ostream& os ) {
        SimpleMutex::scoped_lock lk(_stackTraceMutex);
        HANDLE process = GetCurrentProcess();
        BOOL ret = SymInitialize(process, getSymbolSearchPath(process), TRUE);
        if ( ret == FALSE ) {
            DWORD dosError = GetLastError();
            log() << "Stack trace failed, SymInitialize failed with error " <<
                    std::dec << dosError << std::endl;
            return;
        }
        DWORD options = SymGetOptions();
        options |= SYMOPT_LOAD_LINES | SYMOPT_FAIL_CRITICAL_ERRORS;
        SymSetOptions( options );

        STACKFRAME64 frame64;
        memset( &frame64, 0, sizeof(frame64) );

#if defined(_M_AMD64)
        DWORD imageType = IMAGE_FILE_MACHINE_AMD64;
        frame64.AddrPC.Offset = context.Rip;
        frame64.AddrFrame.Offset = context.Rbp;
        frame64.AddrStack.Offset = context.Rsp;
#elif defined(_M_IX86)
        DWORD imageType = IMAGE_FILE_MACHINE_I386;
        frame64.AddrPC.Offset = context.Eip;
        frame64.AddrFrame.Offset = context.Ebp;
        frame64.AddrStack.Offset = context.Esp;
#else
#error Neither _M_IX86 nor _M_AMD64 were defined
#endif
        frame64.AddrPC.Mode = AddrModeFlat;
        frame64.AddrFrame.Mode = AddrModeFlat;
        frame64.AddrStack.Mode = AddrModeFlat;

        const size_t nameSize = 1024;
        const size_t symbolBufferSize = sizeof(SYMBOL_INFO) + nameSize;
        boost::scoped_array<char> symbolCharBuffer( new char[symbolBufferSize] );
        memset( symbolCharBuffer.get(), 0, symbolBufferSize );
        SYMBOL_INFO* symbolBuffer = reinterpret_cast<SYMBOL_INFO*>( symbolCharBuffer.get() );
        symbolBuffer->SizeOfStruct = sizeof(SYMBOL_INFO);
        symbolBuffer->MaxNameLen = nameSize;

        // build list
        std::vector<TraceItem> traceList;
        TraceItem traceItem;
        size_t moduleWidth = 0;
        size_t sourceWidth = 0;
        for ( size_t i = 0; i < maxBackTraceFrames; ++i ) {
            ret = StackWalk64( imageType,
                               process,
                               GetCurrentThread(),
                               &frame64,
                               &context,
                               NULL,
                               NULL,
                               NULL,
                               NULL );
            if ( ret == FALSE || frame64.AddrReturn.Offset == 0 ) {
                break;
            }
            DWORD64 address = frame64.AddrPC.Offset;
            getModuleName( process, address, &traceItem.moduleName );
            size_t width = traceItem.moduleName.length();
            if ( width > moduleWidth ) {
                moduleWidth = width;
            }
            getSourceFileAndLineNumber( process, address, &traceItem.sourceAndLine );
            width = traceItem.sourceAndLine.length();
            if ( width > sourceWidth ) {
                sourceWidth = width;
            }
            getsymbolAndOffset( process, address, symbolBuffer, &traceItem.symbolAndOffset );
            traceList.push_back( traceItem );
        }
        SymCleanup( process );

        // print list
        ++moduleWidth;
        ++sourceWidth;
        size_t frameCount = traceList.size();
        for ( size_t i = 0; i < frameCount; ++i ) {
            std::stringstream ss;
            ss << traceList[i].moduleName << " ";
            size_t width = traceList[i].moduleName.length();
            while ( width < moduleWidth ) {
                ss << " ";
                ++width;
            }
            ss << traceList[i].sourceAndLine << " ";
            width = traceList[i].sourceAndLine.length();
            while ( width < sourceWidth ) {
                ss << " ";
                ++width;
            }
            ss << traceList[i].symbolAndOffset;
            log() << ss.str() << std::endl;
        }
    }
Ejemplo n.º 28
0
void CSymbolEngine::SetOptions( DWORD Options )
{
	SymSetOptions( Options );
}
Ejemplo 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
}
Ejemplo n.º 30
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
}