コード例 #1
0
ファイル: SymbolEngine.cpp プロジェクト: cosmicb0y/vesper
bool CSymbolEngine::Init( HANDLE hProcess, PCTSTR SearchPath, bool Invade, bool Notify )
{
	// Check parameters and preconditions 

	if( m_hProcess != NULL )
	{
		_ASSERTE( !_T("Already initialized.") );
		if( hProcess != m_hProcess )
		{
			m_LastError = ERROR_INVALID_FUNCTION;
			return false;
		}
		else
		{
			return true;
		}
	}


	// Call SymInitialize

	if( !SymInitialize( hProcess, SearchPath, Invade ? TRUE : FALSE ) )
	{
		m_LastError = GetLastError();
		_ASSERTE( !_T("SymInitialize failed.") );
		return false;
	}


	// Register the notification callback, if requested

	if( Notify )
	{
		if( !SymRegisterCallback64( hProcess, DebugInfoCallback, (ULONG64)this ) )
		{
			m_LastError = GetLastError();
			_ASSERTE( !_T("SymInitialize failed.") );
			return false;
		}
	}


	// Complete 

	m_hProcess = hProcess;

	return true;

}
コード例 #2
0
ファイル: debugger.cpp プロジェクト: aijiekj/drmingw
BOOL DebugMainLoop(const DebugOptions *pOptions)
{
    BOOL fFinished = FALSE;
    BOOL fBreakpointSignalled = FALSE;
    BOOL fWowBreakpointSignalled = FALSE;
    BOOL fTerminating = FALSE;

    while(!fFinished)
    {
        DEBUG_EVENT DebugEvent;            // debugging event information
        DWORD dwContinueStatus = DBG_CONTINUE;    // exception continuation
        PPROCESS_INFO pProcessInfo;
        PTHREAD_INFO pThreadInfo;
        HANDLE hProcess;

        // Wait for a debugging event to occur. The second parameter indicates
        // that the function does not return until a debugging event occurs.
        if(!WaitForDebugEvent(&DebugEvent, INFINITE))
        {
            OutputDebug("WaitForDebugEvent: 0x%08lx", GetLastError());

            return FALSE;
        }

        // Process the debugging event code.
        switch (DebugEvent.dwDebugEventCode) {
        case EXCEPTION_DEBUG_EVENT: {
            PEXCEPTION_RECORD pExceptionRecord = &DebugEvent.u.Exception.ExceptionRecord;
            NTSTATUS ExceptionCode = pExceptionRecord->ExceptionCode;

            // Process the exception code. When handling
            // exceptions, remember to set the continuation
            // status parameter (dwContinueStatus). This value
            // is used by the ContinueDebugEvent function.
            if (pOptions->verbose_flag) {
                lprintf("EXCEPTION PID=%lu TID=%lu ExceptionCode=0x%lx dwFirstChance=%lu\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId,
                        pExceptionRecord->ExceptionCode,
                        DebugEvent.u.Exception.dwFirstChance
                );
            }

            // Find the process in the process list
            pProcessInfo = &g_Processes[DebugEvent.dwProcessId];

            dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;

            if (DebugEvent.u.Exception.dwFirstChance) {
                if (pExceptionRecord->ExceptionCode == (DWORD)STATUS_BREAKPOINT) {
                    // Signal the aedebug event
                    if (!fBreakpointSignalled) {
                        fBreakpointSignalled = TRUE;

                        if (pOptions->hEvent) {
                            SetEvent(pOptions->hEvent);
                            CloseHandle(pOptions->hEvent);
                        }

                        if (pOptions->dwThreadId) {
                            DWORD dwThreadId = pOptions->dwThreadId;
                            const DWORD dwFailed = (DWORD)-1;
                            DWORD dwRet = dwFailed;
                            pThreadInfo = &pProcessInfo->Threads[dwThreadId];
                            HANDLE hThread = pThreadInfo->hThread;
                            if (hThread != NULL) {
                                dwRet = ResumeThread(hThread);
                            }
                            if (dwRet == dwFailed) {
                                lprintf("error: failed to resume thread %lu\n", dwThreadId);
                            }
                        }

                        /*
                         * We ignore first-chance breakpoints by default.
                         *
                         * We get one of these whenever we attach to a process.
                         * But in some cases, we never get a second-chance, e.g.,
                         * when we're attached through MSVCRT's abort().
                         */
                        if (!pOptions->breakpoint_flag) {
                            dwContinueStatus = DBG_CONTINUE;
                            break;
                        }
                    }
                }

                if (ExceptionCode == STATUS_WX86_BREAKPOINT) {
                    if (!fWowBreakpointSignalled) {
                        fWowBreakpointSignalled = TRUE;
                        dwContinueStatus = DBG_CONTINUE;
                        break;
                    }
                }

               /*
                 * Ignore thread naming exception.
                 *
                 * http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
                 *
                 * TODO: Note down the thread name
                 */
                if (ExceptionCode == 0x406d1388) {
                    dwContinueStatus = DBG_CONTINUE;
                    break;
                }

                if (!pOptions->first_chance) {
                    break;
                }
            }

            // XXX: Deferred symbols don't get loaded without this
            SymRefreshModuleList(pProcessInfo->hProcess);

            dumpException(pProcessInfo->hProcess,
                          &DebugEvent.u.Exception.ExceptionRecord);

            // Find the thread in the thread list
            THREAD_INFO_LIST::const_iterator it;
            for (it = pProcessInfo->Threads.begin(); it != pProcessInfo->Threads.end(); ++it) {
                DWORD dwThreadId = it->first;
                HANDLE hThread = it->second.hThread;
                if (dwThreadId != DebugEvent.dwThreadId &&
                    ExceptionCode != STATUS_BREAKPOINT &&
                    ExceptionCode != STATUS_WX86_BREAKPOINT) {
                        continue;
                }

                dumpStack(pProcessInfo->hProcess, hThread, NULL);
            }

            if (!DebugEvent.u.Exception.dwFirstChance) {
                /*
                 * Terminate the process. As continuing would cause the JIT debugger
                 * to be invoked again.
                 */
                fTerminating = TRUE;
                TerminateProcess(pProcessInfo->hProcess, (UINT)ExceptionCode);
            }

            break;
        }

        case CREATE_THREAD_DEBUG_EVENT:
            if (pOptions->verbose_flag) {
                lprintf("CREATE_THREAD PID=%lu TID=%lu\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId
                );
            }

            // Add the thread to the thread list
            pProcessInfo = &g_Processes[DebugEvent.dwProcessId];
            pThreadInfo = &pProcessInfo->Threads[DebugEvent.dwThreadId];
            pThreadInfo->hThread = DebugEvent.u.CreateThread.hThread;
            break;

        case CREATE_PROCESS_DEBUG_EVENT: {
            HANDLE hFile = DebugEvent.u.CreateProcessInfo.hFile;

            char szImageName[MAX_PATH];
            char *lpImageName = NULL;
            if (hFile && GetFileNameFromHandle(hFile, szImageName, _countof(szImageName))) {
                lpImageName = szImageName;
            }

            if (pOptions->verbose_flag) {
                PCSTR lpModuleName = lpImageName ? getBaseName(lpImageName) : "";

                lprintf("CREATE_PROCESS PID=%lu TID=%lu lpBaseOfImage=%p %s\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId,
                        DebugEvent.u.CreateProcessInfo.lpBaseOfImage,
                        lpModuleName
                );
            }

            hProcess = DebugEvent.u.CreateProcessInfo.hProcess;

            pProcessInfo = &g_Processes[DebugEvent.dwProcessId];
            pProcessInfo->hProcess = hProcess;

            pThreadInfo = &pProcessInfo->Threads[DebugEvent.dwThreadId];
            pThreadInfo->hThread = DebugEvent.u.CreateProcessInfo.hThread;

            if (!InitializeSym(hProcess, FALSE)) {
                OutputDebug("error: SymInitialize failed: 0x%08lx\n", GetLastError());
                exit(EXIT_FAILURE);
            }

            SymRegisterCallback64(hProcess, &symCallback, 0);

            loadModule(hProcess, hFile, lpImageName, DebugEvent.u.CreateProcessInfo.lpBaseOfImage);

            break;
        }

        case EXIT_THREAD_DEBUG_EVENT:
            if (pOptions->verbose_flag) {
                lprintf("EXIT_THREAD PID=%lu TID=%lu dwExitCode=0x%lx\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId,
                        DebugEvent.u.ExitThread.dwExitCode
                );
            }

            // Remove the thread from the thread list
            pProcessInfo = &g_Processes[DebugEvent.dwProcessId];
            hProcess = pProcessInfo->hProcess;

            // Dump the stack on abort()
            if (!fTerminating && isAbnormalExitCode(DebugEvent.u.ExitThread.dwExitCode)) {
                pThreadInfo = &pProcessInfo->Threads[DebugEvent.dwThreadId];
                refreshSymbolsAndDumpStack(hProcess, pThreadInfo->hThread);
            }

            pProcessInfo->Threads.erase(DebugEvent.dwThreadId);
            break;

        case EXIT_PROCESS_DEBUG_EVENT: {
            if (pOptions->verbose_flag) {
                lprintf("EXIT_PROCESS PID=%lu TID=%lu dwExitCode=0x%lx\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId,
                        DebugEvent.u.ExitProcess.dwExitCode
                );
            }

            pProcessInfo = &g_Processes[DebugEvent.dwProcessId];
            hProcess = pProcessInfo->hProcess;

            // Dump the stack on abort()
            if (!fTerminating && isAbnormalExitCode(DebugEvent.u.ExitThread.dwExitCode)) {
                pThreadInfo = &pProcessInfo->Threads[DebugEvent.dwThreadId];
                refreshSymbolsAndDumpStack(hProcess, pThreadInfo->hThread);
            }

            // Remove the process from the process list
            g_Processes.erase(DebugEvent.dwProcessId);

            if (!SymCleanup(hProcess)) {
                OutputDebug("SymCleanup failed with 0x%08lx\n", GetLastError());
            }

            if (g_Processes.empty()) {
                fFinished = TRUE;
            }

            break;
        }

        case LOAD_DLL_DEBUG_EVENT: {
            HANDLE hFile = DebugEvent.u.LoadDll.hFile;

            char szImageName[MAX_PATH];
            char *lpImageName = NULL;
            if (hFile && GetFileNameFromHandle(hFile, szImageName, _countof(szImageName))) {
                lpImageName = szImageName;
            }

            if (pOptions->verbose_flag) {
                PCSTR lpModuleName = lpImageName ? getBaseName(lpImageName) : "";

                lprintf("LOAD_DLL PID=%lu TID=%lu lpBaseOfDll=%p %s\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId,
                        DebugEvent.u.LoadDll.lpBaseOfDll,
                        lpModuleName
                );
            }

            pProcessInfo = &g_Processes[DebugEvent.dwProcessId];
            hProcess = pProcessInfo->hProcess;

            loadModule(hProcess, hFile, lpImageName, DebugEvent.u.LoadDll.lpBaseOfDll);

            break;
        }

        case UNLOAD_DLL_DEBUG_EVENT:
            if (pOptions->verbose_flag) {
                lprintf("UNLOAD_DLL PID=%lu TID=%lu lpBaseOfDll=%p\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId,
                        DebugEvent.u.UnloadDll.lpBaseOfDll
                );
            }

            pProcessInfo = &g_Processes[DebugEvent.dwProcessId];
            hProcess = pProcessInfo->hProcess;

            SymUnloadModule64(hProcess, (UINT_PTR)DebugEvent.u.UnloadDll.lpBaseOfDll);

            break;

        case OUTPUT_DEBUG_STRING_EVENT: {
            if (pOptions->verbose_flag) {
                lprintf("OUTPUT_DEBUG_STRING PID=%lu TID=%lu\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId
                );
            }

            pProcessInfo = &g_Processes[DebugEvent.dwProcessId];

            assert(!DebugEvent.u.DebugString.fUnicode);

            LPSTR lpDebugStringData = readProcessString(pProcessInfo->hProcess,
                                                        DebugEvent.u.DebugString.lpDebugStringData,
                                                        DebugEvent.u.DebugString.nDebugStringLength);

            lprintf("%s", lpDebugStringData);

            free(lpDebugStringData);
            break;
        }

        case RIP_EVENT:
            if (pOptions->verbose_flag) {
                lprintf("RIP PID=%lu TID=%lu\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId
                );
            }
            break;

        default:
            if (pOptions->verbose_flag) {
                lprintf("EVENT%lu PID=%lu TID=%lu\r\n",
                    DebugEvent.dwDebugEventCode,
                    DebugEvent.dwProcessId,
                    DebugEvent.dwThreadId
                );
            }
            break;
        }

        // Resume executing the thread that reported the debugging event.
        ContinueDebugEvent(
            DebugEvent.dwProcessId,
            DebugEvent.dwThreadId,
            dwContinueStatus
        );
    }

    return TRUE;
}
コード例 #3
0
ファイル: addr2line.cpp プロジェクト: jrfonseca/drmingw
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;
}
コード例 #4
0
ファイル: ConfigDlg.cpp プロジェクト: hladrien/leakmon
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 );
}