//----------------------------------------------------------------------------//
static void dumpBacktrace(size_t frames)
{

#if defined(__ANDROID__)

    // Not implemented yet.
    CEGUI_UNUSED(frames);

#else

#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", ULongToPtr(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);

#else

    CEGUI_UNUSED(frames);
    
#endif

#else

    CEGUI_UNUSED(frames);

#endif

#endif
}
Esempio n. 2
0
File: main.cpp Progetto: volaya/QGIS
static void dumpBacktrace( unsigned int depth )
{
  if ( depth == 0 )
    depth = 20;

#if ((defined(linux) || defined(__linux__)) && !defined(ANDROID)) || defined(__FreeBSD__)
  // Below there is a bunch of operations that are not safe in multi-threaded
  // environment (dup()+close() combo, wait(), juggling with file descriptors).
  // Maybe some problems could be resolved with dup2() and waitpid(), but it seems
  // that if the operations on descriptors are not serialized, things will get nasty.
  // That's why there's this lovely mutex here...
  static QMutex mutex;
  QMutexLocker locker( &mutex );

  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", static_cast< char * >( nullptr ) );
      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
    int stderr_new = dup( fd[1] );
    if ( stderr_new != STDERR_FILENO )
    {
      if ( stderr_new >= 0 )
        close( stderr_new );
      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 );
    int dup_stderr = dup( stderr_fd );
    if ( dup_stderr != STDERR_FILENO )
    {
      close( dup_stderr );
      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;http://download.osgeo.org/osgeo4w/symstore", TRUE );

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

  for ( int i = 0; i < nFrames; i++ )
  {
    DWORD dwDisplacement;
    SymFromAddr( GetCurrentProcess(), ( DWORD64 )( buffer[ i ] ), 0, symbol );
    symbol->Name[ 255 ] = 0;
    if ( SymGetLineFromAddr( GetCurrentProcess(), ( DWORD64 )( buffer[i] ), &dwDisplacement, line ) )
    {
      myPrint( "%s(%d) : (%s) frame %d, address %x\n", line->FileName, line->LineNumber, symbol->Name, i, symbol->Address );
    }
    else
    {
      myPrint( "%s(%d) : (%s) unknown source location, frame %d, address %x [GetLastError()=%d]\n", __FILE__, __LINE__, symbol->Name, i, symbol->Address, GetLastError() );
    }
  }

  qgsFree( symbol );
  qgsFree( line );
#else
  Q_UNUSED( depth );
#endif
}
Esempio n. 3
0
//==============================================================================
std::vector <std::string>
getStackBacktrace()
{
    std::vector <std::string> result;

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

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

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

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

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

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

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

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

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

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

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

            IMAGEHLP_MODULE64 moduleInfo { sizeof(moduleInfo) };

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

            frame.append (symbol->Name);

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

            result.push_back (frame);
        }
    }

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

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

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

    return result;
}
Esempio n. 4
0
void AbstractBTGenerator::Run(HANDLE hThread, bool bFaultingThread)
{
    assert(m_process.IsValid());
    assert(hThread);

    if (!Init())
    {
        assert(false);
        return;
    }

    if (bFaultingThread)
    {
        const QString threadInfo = QString("Faulting thread (%1)").arg( reinterpret_cast<quintptr>(hThread) );
        emit DebugLine(threadInfo);
    }
    else
    {
        const QString threadInfo = QString("Thread %1").arg( reinterpret_cast<quintptr>(hThread) );
        emit DebugLine(threadInfo);
    }

    //HANDLE hFile = CreateFile(L"C:\\test\\test.dmp", FILE_ALL_ACCESS, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
    //if (!MiniDumpWriteDump(m_process.GetHandle(), m_process.GetId(), hFile,
    //    MiniDumpNormal, NULL, NULL, NULL))
    //{
    //    HRESULT hres = (HRESULT) GetLastError();
    //    printf("%08X\n\n", hres);
    //}
    //SafeCloseHandle(hFile);

    DWORD dw = SuspendThread(hThread);
    assert(dw != DWORD(-1));
    if (dw == DWORD(-1))
    {
        qCritical() << "SuspendThread() failed: " << GetLastError();
        return;
    }

    CONTEXT context;
    ZeroMemory(&context, sizeof(context));
    if (!bFaultingThread)
    {
        // if it's not the faulting thread, get its context
        context.ContextFlags = CONTEXT_FULL;
        if (!GetThreadContext(hThread, &context))
        {
            ResumeThread(hThread);
            assert(false);
            qCritical() << "GetThreadContext() failed: " << GetLastError();
            return;
        }
    }
    else
    {
        // if it is, get it from KCrash
        HANDLE hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, sharedMemoryName);
        if (hMapFile == NULL)
        {
            qCritical() << "OpenFileMapping() failed: " << GetLastError();
            return;
        }
        CONTEXT *othercontext = (CONTEXT*) MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(CONTEXT));
        if (othercontext == NULL)
        {
            qCritical() << "MapViewOfFile() failed: " << GetLastError();
            SafeCloseHandle(hMapFile);
            return;
        }
        CopyMemory(&context, othercontext, sizeof(CONTEXT));
        UnmapViewOfFile(othercontext); // continue even if it fails
        SafeCloseHandle(hMapFile);
    }

    // some of this stuff is taken from StackWalker
    ZeroMemory(&m_currentFrame, sizeof(m_currentFrame));
    DWORD machineType = IMAGE_FILE_MACHINE_UNKNOWN;
#if defined(_M_IX86)
    machineType = IMAGE_FILE_MACHINE_I386;
    m_currentFrame.AddrPC.Offset = context.Eip;
    m_currentFrame.AddrFrame.Offset = context.Ebp;
    m_currentFrame.AddrStack.Offset = context.Esp;
#elif defined(_M_X64)
    machineType = IMAGE_FILE_MACHINE_AMD64;
    m_currentFrame.AddrPC.Offset = context.Rip;
    m_currentFrame.AddrFrame.Offset = context.Rbp;
    m_currentFrame.AddrStack.Offset = context.Rsp;
#else
# error This architecture is not supported.
#endif
    m_currentFrame.AddrPC.Mode = AddrModeFlat;
    m_currentFrame.AddrFrame.Mode = AddrModeFlat;
    m_currentFrame.AddrStack.Mode = AddrModeFlat;

    SymSetOptions(SymGetOptions() | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES);
    SymInitialize(m_process.GetHandle(), NULL, FALSE);

    LoadSymbols();

    for (int i = 0; /*nothing*/; i++)
    {
        SetLastError(0);

        if (!StackWalk64(
            machineType,
            m_process.GetHandle(),
            hThread,
            &m_currentFrame,
            &context,
            &Callbacks::ReadProcessMemory,
            &Callbacks::SymFunctionTableAccess64,
            &Callbacks::SymGetModuleBase64,
            NULL))
        {
            emit Finished();
            qDebug() << "Stackwalk finished; GetLastError=" << GetLastError();
            break;
        }
        
        FrameChanged();

        QString modulename = GetModuleName();
        QString functionname = GetFunctionName();
        QString file = GetFile();
        int line = GetLine();
        QString address = QString::number(m_currentFrame.AddrPC.Offset, 16);

        QString debugLine = QString::fromLatin1(BACKTRACE_FORMAT).
            arg(modulename).arg(functionname).arg(file).arg(line).arg(address);
        
        emit DebugLine(debugLine);
    }

    // Resume the target thread now, or else the crashing process will not
    // be terminated
    ResumeThread(hThread);

    SymCleanup(m_process.GetHandle());

    emit DebugLine(QString());
}
Esempio n. 5
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], "--exe") == 0 ||
               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 : %lu\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 : %lu\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 : %lu\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 : %lu 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 reladdr = _strtoui64(buf, NULL, 16);
    ULONG64 buffer[(sizeof(SYMBOL_INFO) +
                    MAX_SYM_NAME*sizeof(TCHAR) +
                    sizeof(ULONG64) - 1)
                   / sizeof(ULONG64)];
    memset(buffer, 0, sizeof(buffer));
    PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
    IMAGEHLP_LINE64 line;
    DWORD dummy;

    // Just ignore overflow. In an overflow scenario, the resulting address
    // will be lower than module_base which hasn't been mapped by any prior
    // SymLoadModuleEx() command. This will cause SymFromAddr() and
    // SymGetLineFromAddr64() both to return failures and print the correct
    // ?? and ??:0 message variant.
    ULONG64 absaddr = reladdr + module_base;

    pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
    // The length of the name is not including the null-terminating character.
    pSymbol->MaxNameLen = MAX_SYM_NAME - 1;
    if (print_function_name) {
      if (SymFromAddr(process, (DWORD64)absaddr, NULL, pSymbol)) {
        printf("%s\n", pSymbol->Name);
      } else {
        printf("??\n");
      }
    }
    line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
    if (SymGetLineFromAddr64(process, (DWORD64)absaddr, &dummy, &line)) {
      printf("%s:%d\n", line.FileName, (int)line.LineNumber);
    } else {
      printf("??:0\n");
    }
  }
  SymUnloadModule64(process, module_base);
  SymCleanup(process);
  return rv;
}
Esempio n. 6
0
ULONG	getSymbols()
{
	CString FilePathName;
	PCSTR path;
	DWORD error;
	DWORD64 dw64Base;
	DWORD dwFileSize;
	g_CountOfFunFound	=	0;
	dw64Base = getNtBase();
	if (dw64Base==0)
	{
		::MessageBox(NULL,"Get base 0",NULL,NULL);
		return 0 ;
	}
	char	szSystemDir[1024]={0};
	GetSystemDirectory(szSystemDir, sizeof(szSystemDir));
	FilePathName	=	szSystemDir;
	FilePathName	=	FilePathName+"\\"+PathFindFileName(osname);
	
	path=FilePathName;
	//记得要带上symsrv.dll和dbghelp.dll
	char *pSymPath	=	"srv*C:\\winddk\\symbolsl*http://msdl.microsoft.com/download/symbols";
	myprint("retriving symbols for %s,symbols store in %s\r\n",path, pSymPath);
	 SymCleanup(GetCurrentProcess());
	if (SymInitialize(GetCurrentProcess(), pSymPath, TRUE))
	{
		// SymInitialize returned success
	}
	else
	{
		// SymInitialize failed
		error = GetLastError();
		myprint("SymInitialize returned error : %d\n", error);
		return 0;
	}
	
	DWORD err=0;
	// get the file size
	HANDLE hFile = CreateFile( FilePathName, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
	if( INVALID_HANDLE_VALUE == hFile )
	{
		err	=	GetLastError();
		::MessageBox(NULL,"out",NULL,NULL);
		return false;
	}
	if( INVALID_FILE_SIZE == ( dwFileSize = GetFileSize(hFile, NULL)) )
	{
		
	}
	CloseHandle(hFile);
	
	
	DWORD64 dw64ModAddress=SymLoadModule64( GetCurrentProcess(),NULL, (char*)path,NULL,dw64Base,dwFileSize);
	
	if(dw64ModAddress==0)
	{
		error = GetLastError();
		myprint("SymLoadModule64 returned error : %d\n", error);
		return 0;
		
	}

	if(!SymEnumSymbols( GetCurrentProcess(),
		dw64ModAddress,
		NULL, // Null point out that list all symbols
		SymEnumSymbolsProc,
		NULL))
	{
		//_tprintf( _T("Failed when SymEnumSymbols(): %d \n"), GetLastError() );
		return 0;
	}
	myprint("g_CountOfFunFound %d\r\n", g_CountOfFunFound);
	bool bRetSym	=	(g_CountOfFunFound>sizeof(dync_funs)/sizeof(dync_funs[0]));
	return bRetSym?dw64Base:0;

}
Esempio n. 7
0
void ConfigDlg::LoadSymbols()
{
    g_StackDepth = GetDlgItemInt( IDC_EDIT1, NULL, FALSE );
    if( m_bChanged )
    {
        CString csExeName;
        GetModuleFileName( 0, csExeName.GetBuffer( MAX_PATH), MAX_PATH );
        csExeName.ReleaseBuffer();
        csExeName = csExeName.MakeLower();
        csExeName.Replace( _T(".exe"), _T("Mem.ini"));
        CStdioFile File;
        if( !File.Open( csExeName, CFile::modeCreate|CFile::modeWrite ))
        {
            goto LoadDll;
        }        
        int nCount = m_List.GetItemCount();
        m_csPath.Empty();
        for( int nId = 0;nId < nCount; nId++ )
        {
            CString csItem = m_List.GetItemText( nId ,0 );
            m_csPath += csItem + _T(";");            
            csItem += _T("\r\n");
            File.WriteString( csItem );
        }
        File.Close();
    }
    
LoadDll:

    HMODULE hModule = GetModuleHandle( _T("dbghelp.dll"));
    SymRefreshModuleListDef pSymRefreshModuleList;
    
    if( hModule )
    {
        pSymRefreshModuleList = (SymRefreshModuleListDef)GetProcAddress( hModule, _T("SymRefreshModuleList"));
        CString csLoadedDll;
        GetModuleFileName( hModule, csLoadedDll.GetBuffer(MAX_PATH), MAX_PATH );
        csLoadedDll.ReleaseBuffer();
        if( !pSymRefreshModuleList )
        {
            // old version of dbghelp :(
            MessageBox( "Your application has already loaded dbghelp.dll from " + csLoadedDll +
                "\n\nFor acqurate results, replace this dll with the latest version of dbghelp.dll"
                "coming with \"Debugging tools for windows\" or with the dll the application folder of this utility", 
                    "Error", MB_OK );
        }
        else
        {
            MessageBox( "Your application has already loaded dbghelp.dll from " + csLoadedDll +
                " Please confirm that the symsrv.dll exists in th same folder.\n"
                "Otherwise symbol server will not work", 
                "Warning", MB_OK );
        }
        
    }
    else 
    {
// 			static int nTempvariable;
// 			MEMORY_BASIC_INFORMATION MemInfo;
// 			CString csDllPath;
// 			if( !VirtualQuery( &nTempvariable, &MemInfo, sizeof(MemInfo)))
// 			{
// 				goto LoadDll;
// 			}
        CString csDllPath;
        HMODULE hHookDll = GetModuleHandle( _T("HookDll.dll"));
        if( !GetModuleFileName( hHookDll, csDllPath.GetBuffer( MAX_PATH), MAX_PATH ))
        {
            goto LoadDll;
        }
        csDllPath.ReleaseBuffer();
        int nPos = csDllPath.ReverseFind( _T('\\'));
        if( 0 >= nPos )
        {
            goto LoadDll;
        }
        csDllPath = csDllPath.Left( nPos + 1 );
        //csDllPath = "C:\\Program Files\\Debugging Tools for Windows (x86)\\";
        csDllPath += _T("dbghelp.dll");
        
        hModule = LoadLibrary( csDllPath );
        if( !hModule)
        {
            hModule = LoadLibrary(  _T("dbghelp.dll"));
            pSymRefreshModuleList = (SymRefreshModuleListDef)GetProcAddress( hModule, _T("SymRefreshModuleList"));
            if( !pSymRefreshModuleList )
            {
                MessageBox( "Failed to load the dbghelp.dll from the local directory\n\n"
                            "The application will continue with the default dbghelp.dll. But some feature may"
                            "be unavailable", "Error", MB_OK );
            }
            
        }
        else
        {
             pSymRefreshModuleList = (SymRefreshModuleListDef)GetProcAddress( hModule, _T("SymRefreshModuleList"));
        }
        
    }

    SymCleanup(GetCurrentProcess());
    CString csWholePath = m_csPath;
    csWholePath.TrimRight( ';' );
    DWORD dwOption = 0;//SymGetOptions();
    dwOption |= SYMOPT_CASE_INSENSITIVE|SYMOPT_LOAD_LINES|SYMOPT_FAIL_CRITICAL_ERRORS|
                SYMOPT_LOAD_ANYTHING|SYMOPT_UNDNAME;    
    SymSetOptions( dwOption );
    CWinThread* pThread = AfxBeginThread( ThreadEntry, this );
    HANDLE hThread = pThread->m_hThread;
    
    
    BOOL fInvadeProcess = (0 == pSymRefreshModuleList)?TRUE:FALSE;

    
    BOOL bRet = SymInitialize(GetCurrentProcess(), (LPTSTR)csWholePath.operator LPCTSTR() , fInvadeProcess );
    SymRegisterCallback64( GetCurrentProcess(),SymRegisterCallbackProc64,(ULONG64 )this );
    while( !m_ProgressDlg.m_hWnd )// wait untill the dialog is created
    {
        Sleep( 50 );
    }

    if( pSymRefreshModuleList )
    {
        pSymRefreshModuleList( GetCurrentProcess());
    }
    //SymRefreshModuleList( GetCurrentProcess());
    m_ProgressDlg.SendMessage( WM_CLOSE );
    WaitForSingleObject( hThread, 10000 );
}
Esempio n. 8
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;
        std::unique_ptr<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;
        }
    }