Exemple #1
0
std::string win_stacktrace()
{
  void *stack[100];
  unsigned short frames = CaptureStackBackTrace(0, 100, stack, NULL);
  SYMBOL_INFO *symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1);
  symbol->MaxNameLen = 255;
  symbol->SizeOfStruct = sizeof(SYMBOL_INFO);

  HANDLE process = GetCurrentProcess();

  std::string result;
  result.reserve(128);
  
  {
    muduo::MutexLockGuard guard(
      muduo::Singleton<win::SymManager>::instance().getMutex());

    SymRefreshModuleList(process);

    char buf[512];
    int count = 0;
    for(unsigned int i = 0; i < frames; i++)
    {
      SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol);
      count = snprintf(buf, sizeof(buf)-1,
        "%i: %s - 0x%0X\n", frames-i-1, symbol->Name, symbol->Address);
      if (count != -1) result.append(buf);
    }
  }

  free(symbol);

  return result;
}
Exemple #2
0
static void
refreshSymbolsAndDumpStack(HANDLE hProcess, HANDLE hThread)
{
    assert(hProcess);
    assert(hThread);

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

    dumpStack(hProcess, hThread, NULL);
}
Exemple #3
0
void print_stack_trace(out_stream_t *out, int signum) {
  handle_t process = GetCurrentProcess();
  if (!SymRefreshModuleList(process)) {
    out_stream_printf(out, "Error refreshing module list: %i", GetLastError());
    return;
  }

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

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

  // Scan through the trace one frame at a time, resolving symbols as we go.
  static const size_t kMaxNameLength = 128;
  static const size_t kSymbolInfoSize = sizeof(SYMBOL_INFO) + (kMaxNameLength * sizeof(char_t));
  // A SYMBOL_INFO is variable size so we stack allocate a blob of memory and
  // cast it rather than stack allocate the info directly.
  uint8_t symbol_info_bytes[kSymbolInfoSize];
  ZeroMemory(symbol_info_bytes, kSymbolInfoSize);
  SYMBOL_INFO *info = reinterpret_cast<SYMBOL_INFO*>(symbol_info_bytes);
  // This isn't strictly true, it's symbol_info_bytes, but SymFromAddr requires
  // it to have this value.
  info->SizeOfStruct = sizeof(SYMBOL_INFO);
  info->MaxNameLen = kMaxNameLength;
  for (size_t i = 0; i < frame_count; i++) {
    void *addr = backtrace[i];
    DWORD64 addr64 = reinterpret_cast<DWORD64>(addr);
    if (SymFromAddr(process, addr64, 0, info)) {
      out_stream_printf(out, "# - 0x%p: %s\n", addr, info->Name);
    } else {
      out_stream_printf(out, "# - 0x%p\n", addr);
    }
  }
}
Exemple #4
0
/*
================
Sys_PrintStackTrace

Occurs when we encounter a fatal error.
Prints the stack trace as well as some other data.
================
*/
LONG WINAPI Sys_PrintStackTrace(EXCEPTION_POINTERS* exception)
{
	STACKFRAME frame = {};
#ifdef WIN32
	DWORD machine = IMAGE_FILE_MACHINE_I386;
#else
	DWORD machine = IMAGE_FILE_MACHINE_AMD64;
#endif
	HANDLE process = GetCurrentProcess();
	HANDLE thread = GetCurrentThread();
	int i = 0;

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

#ifdef WIN32
	frame.AddrPC.Offset = exception->ContextRecord->Eip;
	frame.AddrFrame.Offset = exception->ContextRecord->Ebp;
	frame.AddrStack.Offset = exception->ContextRecord->Esp;
#else
	frame.AddrPC.Offset = exception->ContextRecord->Rip;
	frame.AddrFrame.Offset = exception->ContextRecord->Rbp;
	frame.AddrStack.Offset = exception->ContextRecord->Rsp;
#endif

	Com_Printf("------------------------\n");
	Com_Printf("Enumerate Modules:\n");
	Com_Printf("------------------------\n");
	SymRefreshModuleList(process);
	SymEnumerateModules(process, Sys_PrintModule, nullptr);

	Com_Printf("\n\n");
	Com_Printf("------------------------\n");
	Com_Printf("Stack trace : \n");
	Com_Printf("------------------------\n");
	while (StackWalk(machine, process, thread, &frame, exception->ContextRecord, nullptr, SymFunctionTableAccess, SymGetModuleBase, nullptr))
	{
		DWORD moduleBase = SymGetModuleBase(process, frame.AddrPC.Offset);
		char moduleName[MAX_PATH];
		char funcName[MAX_PATH];
		char fileName[MAX_PATH];
		DWORD address = frame.AddrPC.Offset;
		char symbolBuffer[sizeof(IMAGEHLP_SYMBOL) + 255];
		PIMAGEHLP_SYMBOL symbol = (PIMAGEHLP_SYMBOL)symbolBuffer;
		IMAGEHLP_LINE line;
		DWORD offset = 0;

		line.SizeOfStruct = sizeof(IMAGEHLP_LINE);
		symbol->SizeOfStruct = (sizeof IMAGEHLP_SYMBOL) + 255;
		symbol->MaxNameLength = 254;

		if (moduleBase && GetModuleFileNameA((HINSTANCE)moduleBase, moduleName, MAX_PATH))
		{
			Sys_CleanModuleName(moduleName, MAX_PATH);
		}
		else
		{
			moduleName[0] = '\0';
		}

		if (SymGetSymFromAddr(process, frame.AddrPC.Offset, &offset, symbol))
		{
			Q_strncpyz(funcName, symbol->Name, MAX_PATH);
		}
		else
		{
			funcName[0] = '\0';
		}

		if (SymGetLineFromAddr(process, frame.AddrPC.Offset, &offset, &line))
		{
			Q_strncpyz(fileName, line.FileName, MAX_PATH);
			Sys_CleanModuleName(fileName, MAX_PATH);
			Com_sprintf(fileName, MAX_PATH, "%s:%i", fileName, line.LineNumber);
		}
		else
		{
			fileName[0] = '\0';
		}

		Com_Printf("%03i %20s 0x%08X | %s (%s)\n", i, moduleName, address, funcName, fileName);
		i++;
	}

	Sys_Error("Unhanded Exception: 0x%08X", exception->ExceptionRecord->ExceptionCode);
#ifdef _DEBUG
	return EXCEPTION_CONTINUE_SEARCH;
#else
	return EXCEPTION_EXECUTE_HANDLER;
#endif
	
}
/**
 * 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;
}
Exemple #6
0
bool DebuggingLoop()
{
	DEBUG_EVENT DebugEvent;
	CONTEXT ctxThreadContext;
	DWORD dwDebugState = NULL;

	PTCHAR sTemp = (PTCHAR)malloc(255 * sizeof(TCHAR));
	szTempSym = (PCHAR)malloc(MAX_SYM_NAME);

	ctxThreadContext.ContextFlags = CONTEXT_FULL;
	
	while(bDebugging)
	{
		if(!WaitForDebugEvent(&DebugEvent,INFINITE))
		{
			free(sTemp);
			free(szTempSym);
			return false;
		}

		switch(DebugEvent.dwDebugEventCode)
		{
		case LOAD_DLL_DEBUG_EVENT:
			{
				SymRefreshModuleList(piProcInfo.hProcess);
				dwDebugState = DBG_CONTINUE;
				break;
			}
		case CREATE_PROCESS_DEBUG_EVENT:
			{
				if(!bSymInit)
					bSymInit = SymInitialize(piProcInfo.hProcess,NULL,FALSE);
				dwDebugState = DBG_CONTINUE;
				break;
			}
		case CREATE_THREAD_DEBUG_EVENT:
			{
				HANDLE hThread = OpenThread(THREAD_ALL_ACCESS,false,DebugEvent.dwThreadId);
				GetThreadContext(hThread,&ctxThreadContext);
				ctxThreadContext.EFlags |= 0x100;
				SetThreadContext(hThread,&ctxThreadContext);

				dwDebugState = DBG_CONTINUE;
				break;
			}
		case EXIT_PROCESS_DEBUG_EVENT:
			{
				bDebugging = false;
				dwDebugState = DBG_CONTINUE;
				break;
			}
		case EXCEPTION_DEBUG_EVENT:
			{
				switch(DebugEvent.u.Exception.ExceptionRecord.ExceptionCode)
				{
				case EXCEPTION_BREAKPOINT:
					{
						dwDebugState = DBG_CONTINUE;
						break;
					}
				case EXCEPTION_SINGLE_STEP:
					{	
						HANDLE hThread = OpenThread(THREAD_ALL_ACCESS,false,DebugEvent.dwThreadId);
						GetThreadContext(hThread,&ctxThreadContext);
						InsertInfo((DWORD)DebugEvent.u.Exception.ExceptionRecord.ExceptionAddress,DebugEvent.dwThreadId,sTemp);
						ctxThreadContext.EFlags |= 0x100;
						SetThreadContext(hThread,&ctxThreadContext);
						dwDebugState = DBG_CONTINUE;
						break;
					}
				default:
					dwDebugState = DBG_EXCEPTION_NOT_HANDLED;
				}
				break;
			}
		default:
			dwDebugState = DBG_EXCEPTION_NOT_HANDLED;
		}
		ContinueDebugEvent(DebugEvent.dwProcessId,DebugEvent.dwThreadId,dwDebugState);
	}
	free(sTemp);
	free(szTempSym);
	return false;
}
Exemple #7
0
TORRENT_EXPORT void print_backtrace(char* out, int len, int max_depth
	, void* ctx)
{
	CONTEXT context_record;
	if (ctx)
	{
		context_record = *static_cast<CONTEXT*>(ctx);
	}
	else
	{
		// use the current thread's context
		RtlCaptureContext(&context_record);
	}

	int size = 0;
	std::array<void*, 50> stack;

	STACKFRAME64 stack_frame;
	memset(&stack_frame, 0, sizeof(stack_frame));
#if defined(_WIN64)
	int const machine_type = IMAGE_FILE_MACHINE_AMD64;
	stack_frame.AddrPC.Offset = context_record.Rip;
	stack_frame.AddrFrame.Offset = context_record.Rbp;
	stack_frame.AddrStack.Offset = context_record.Rsp;
#else
	int const machine_type = IMAGE_FILE_MACHINE_I386;
	stack_frame.AddrPC.Offset = context_record.Eip;
	stack_frame.AddrFrame.Offset = context_record.Ebp;
	stack_frame.AddrStack.Offset = context_record.Esp;
#endif
	stack_frame.AddrPC.Mode = AddrModeFlat;
	stack_frame.AddrFrame.Mode = AddrModeFlat;
	stack_frame.AddrStack.Mode = AddrModeFlat;
	while (StackWalk64(machine_type,
		GetCurrentProcess(),
		GetCurrentThread(),
		&stack_frame,
		&context_record,
		nullptr,
		&SymFunctionTableAccess64,
		&SymGetModuleBase64,
		nullptr) && size < stack.size())
	{
		stack[size++] = reinterpret_cast<void*>(stack_frame.AddrPC.Offset);
	}

	struct symbol_bundle : SYMBOL_INFO
	{
		wchar_t name[MAX_SYM_NAME];
	};

	HANDLE p = GetCurrentProcess();
	static bool sym_initialized = false;
	if (!sym_initialized)
	{
		sym_initialized = true;
		SymInitialize(p, NULL, true);
	}
	SymRefreshModuleList(p);
	for (int i = 0; i < size && len > 0; ++i)
	{
		DWORD_PTR frame_ptr = reinterpret_cast<DWORD_PTR>(stack[i]);

		DWORD64 displacement = 0;
		symbol_bundle symbol;
		symbol.MaxNameLen = MAX_SYM_NAME;
		symbol.SizeOfStruct = sizeof(SYMBOL_INFO);
		BOOL const has_symbol = SymFromAddr(p, frame_ptr, &displacement, &symbol);

		DWORD line_displacement = 0;
		IMAGEHLP_LINE64 line = {};
		line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
		BOOL const has_line = SymGetLineFromAddr64(GetCurrentProcess(), frame_ptr,
			&line_displacement, &line);

		int ret = std::snprintf(out, len, "%2d: %p", i, stack[i]);
		out += ret; len -= ret; if (len <= 0) break;

		if (has_symbol)
		{
			ret = std::snprintf(out, len, " %s +%-4" PRId64
				, demangle(symbol.Name).c_str(), displacement);
			out += ret; len -= ret; if (len <= 0) break;
		}

		if (has_line)
		{
			ret = std::snprintf(out, len, " %s:%d"
				, line.FileName, line.LineNumber);
			out += ret; len -= ret; if (len <= 0) break;
		}


		ret = std::snprintf(out, len, "\n");
		out += ret;
		len -= ret;

		if (i == max_depth && max_depth > 0) break;
	}
}
Exemple #8
0
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;
}
Exemple #9
0
void StackTree::refreshModuleList()
{
	ASSERT(s_instances > 0);
	SymRefreshModuleList(GetCurrentProcess());
}