// Trap a particular thread BOOL TrapThread(DWORD dwProcessId, DWORD dwThreadId) { PPROCESS_INFO pProcessInfo; PTHREAD_INFO pThreadInfo; HANDLE hProcess; HANDLE hThread; /* FIXME: synchronize access to globals */ pProcessInfo = &g_Processes[dwProcessId]; hProcess = pProcessInfo->hProcess; assert(hProcess); pThreadInfo = &pProcessInfo->Threads[dwThreadId]; hThread = pThreadInfo->hThread; assert(hThread); DWORD dwRet = SuspendThread(hThread); if (dwRet != (DWORD)-1) { CONTEXT Context; if (getThreadContext(hProcess, hThread, &Context)) { dumpStack(hProcess, hThread, &Context); } writeDump(dwProcessId, pProcessInfo, nullptr); // TODO: Flag fTerminating exit(3); } TerminateProcess(hProcess, 3); return TRUE; }
afs_int32 writeDatabase(struct ubik_trans *ut, int fid) { dbadr dbAddr, dbAppAddr; struct dump diskDump, apDiskDump; dbadr tapeAddr; struct tape diskTape; dbadr volFragAddr; struct volFragment diskVolFragment; struct volInfo diskVolInfo; int length, hash; int old = 0; int entrySize; afs_int32 code = 0, tcode; afs_int32 appDumpAddrs[MAXAPPENDS], numaddrs, appcount, j; struct memoryHashTable *mht; LogDebug(4, "writeDatabase:\n"); /* write out a header identifying this database etc */ tcode = writeDbHeader(fid); if (tcode) { LogError(tcode, "writeDatabase: Can't write Header\n"); ERROR(tcode); } /* write out the tree of dump structures */ mht = ht_GetType(HT_dumpIden_FUNCTION, &entrySize); if (!mht) { LogError(tcode, "writeDatabase: Can't get dump type\n"); ERROR(BUDB_BADARGUMENT); } for (old = 0; old <= 1; old++) { /*oldnew */ /* only two states, old or not old */ length = (old ? mht->oldLength : mht->length); if (!length) continue; for (hash = 0; hash < length; hash++) { /*hashBuckets */ /* dump all the dumps in this hash bucket */ for (dbAddr = ht_LookupBucket(ut, mht, hash, old); dbAddr; dbAddr = ntohl(diskDump.idHashChain)) { /*initialDumps */ /* now check if this dump had any errors/inconsistencies. * If so, don't dump it */ if (badEntry(dbAddr)) { LogError(0, "writeDatabase: Damaged dump entry at addr 0x%x\n", dbAddr); Log(" Skipping remainder of dumps on hash chain %d\n", hash); break; } tcode = cdbread(ut, dump_BLOCK, dbAddr, &diskDump, sizeof(diskDump)); if (tcode) { LogError(tcode, "writeDatabase: Can't read dump entry (addr 0x%x)\n", dbAddr); Log(" Skipping remainder of dumps on hash chain %d\n", hash); break; } /* Skip appended dumps, only start with initial dumps */ if (diskDump.initialDumpID != 0) continue; /* Skip appended dumps, only start with initial dumps. Then * follow the appended dump chain so they are in order for restore. */ appcount = numaddrs = 0; for (dbAppAddr = dbAddr; dbAppAddr; dbAppAddr = ntohl(apDiskDump.appendedDumpChain)) { /*appendedDumps */ /* Check to see if we have a circular loop of appended dumps */ for (j = 0; j < numaddrs; j++) { if (appDumpAddrs[j] == dbAppAddr) break; /* circular loop */ } if (j < numaddrs) { /* circular loop */ Log("writeDatabase: Circular loop found in appended dumps\n"); Log("Skipping rest of appended dumps of dumpID %u\n", ntohl(diskDump.id)); break; } if (numaddrs >= MAXAPPENDS) numaddrs = MAXAPPENDS - 1; /* don't overflow */ appDumpAddrs[numaddrs] = dbAppAddr; numaddrs++; /* If we dump a 1000 appended dumps, assume a loop */ if (appcount >= 5 * MAXAPPENDS) { Log("writeDatabase: Potential circular loop of appended dumps\n"); Log("Skipping rest of appended dumps of dumpID %u. Dumped %d\n", ntohl(diskDump.id), appcount); break; } appcount++; /* Read the dump entry */ if (dbAddr == dbAppAddr) { /* First time through, don't need to read the dump entry again */ memcpy(&apDiskDump, &diskDump, sizeof(diskDump)); } else { if (badEntry(dbAppAddr)) { LogError(0, "writeDatabase: Damaged appended dump entry at addr 0x%x\n", dbAddr); Log(" Skipping this and remainder of appended dumps of initial DumpID %u\n", ntohl(diskDump.id)); break; } tcode = cdbread(ut, dump_BLOCK, dbAppAddr, &apDiskDump, sizeof(apDiskDump)); if (tcode) { LogError(tcode, "writeDatabase: Can't read appended dump entry (addr 0x%x)\n", dbAppAddr); Log(" Skipping this and remainder of appended dumps of initial DumpID %u\n", ntohl(diskDump.id)); break; } /* Verify that this appended dump points to the initial dump */ if (ntohl(apDiskDump.initialDumpID) != ntohl(diskDump.id)) { LogError(0, "writeDatabase: Appended dumpID %u does not reference initial dumpID %u\n", ntohl(apDiskDump.id), ntohl(diskDump.id)); Log(" Skipping this appended dump\n"); continue; } } /* Save the dump entry */ tcode = writeDump(fid, &apDiskDump); if (tcode) { LogError(tcode, "writeDatabase: Can't write dump entry\n"); ERROR(tcode); } /* For each tape on this dump */ for (tapeAddr = ntohl(apDiskDump.firstTape); tapeAddr; tapeAddr = ntohl(diskTape.nextTape)) { /*tapes */ /* read the tape entry */ tcode = cdbread(ut, tape_BLOCK, tapeAddr, &diskTape, sizeof(diskTape)); if (tcode) { LogError(tcode, "writeDatabase: Can't read tape entry (addr 0x%x) of dumpID %u\n", tapeAddr, ntohl(apDiskDump.id)); Log(" Skipping this and remaining tapes in the dump (and all their volumes)\n"); break; } /* Save the tape entry */ tcode = writeTape(fid, &diskTape, ntohl(apDiskDump.id)); if (tcode) { LogError(tcode, "writeDatabase: Can't write tape entry\n"); ERROR(tcode); } /* For each volume on this tape. */ for (volFragAddr = ntohl(diskTape.firstVol); volFragAddr; volFragAddr = ntohl(diskVolFragment.sameTapeChain)) { /*volumes */ /* Read the volume Fragment entry */ tcode = cdbread(ut, volFragment_BLOCK, volFragAddr, &diskVolFragment, sizeof(diskVolFragment)); if (tcode) { LogError(tcode, "writeDatabase: Can't read volfrag entry (addr 0x%x) of dumpID %u\n", volFragAddr, ntohl(apDiskDump.id)); Log(" Skipping this and remaining volumes on tape '%s'\n", diskTape.name); break; } /* Read the volume Info entry */ tcode = cdbread(ut, volInfo_BLOCK, ntohl(diskVolFragment.vol), &diskVolInfo, sizeof(diskVolInfo)); if (tcode) { LogError(tcode, "writeDatabase: Can't read volinfo entry (addr 0x%x) of dumpID %u\n", ntohl(diskVolFragment.vol), ntohl(apDiskDump.id)); Log(" Skipping volume on tape '%s'\n", diskTape.name); continue; } /* Save the volume entry */ tcode = writeVolume(ut, fid, &diskVolFragment, &diskVolInfo, ntohl(apDiskDump.id), diskTape.name); if (tcode) { LogError(tcode, "writeDatabase: Can't write volume entry\n"); ERROR(tcode); } } /*volumes */ } /*tapes */ } /*appendedDumps */ } /*initialDumps */ } /*hashBuckets */ } /*oldnew */ /* write out the textual configuration information */ tcode = writeText(ut, fid, TB_DUMPSCHEDULE); if (tcode) { LogError(tcode, "writeDatabase: Can't write dump schedule\n"); ERROR(tcode); } tcode = writeText(ut, fid, TB_VOLUMESET); if (tcode) { LogError(tcode, "writeDatabase: Can't write volume set\n"); ERROR(tcode); } tcode = writeText(ut, fid, TB_TAPEHOSTS); if (tcode) { LogError(tcode, "writeDatabase: Can't write tape hosts\n"); ERROR(tcode); } tcode = writeStructHeader(fid, SD_END); if (tcode) { LogError(tcode, "writeDatabase: Can't write end savedb\n"); ERROR(tcode); } error_exit: doneWriting(code); return (code); }
void runTest(unsigned int startFreq, unsigned int targetFreq, unsigned int coreID) { double startBenchTime=0; double targetBenchTime=0; unsigned long lowBoundTime=0; unsigned long highBoundTime=0; unsigned long time =0; unsigned long startLoopTime = 0; unsigned long lateStartLoopTime = 0; unsigned long endLoopTime = 0; /* Build the confidence interval of the sample mean */ double startBenchSD=0; double targetBenchSD=0; unsigned long startLowBoundTime=0; unsigned long startHighBoundTime=0; unsigned long targetLowBoundTime=0; unsigned long targetHighBoundTime=0; unsigned long targetQ1=0; unsigned long targetQ3=0; setFreq(coreID,targetFreq); waitCurFreq(coreID,targetFreq); targetBenchTime = measureLoop(NB_BENCH_META_REPET); fprintf(stdout,"Bench %d %.2f\n",targetFreq, targetBenchTime); targetBenchSD = sd(NB_BENCH_META_REPET, targetBenchTime, times); // Build the inter-quartile range for the target frequency interQuartileRange(NB_BENCH_META_REPET, times, &targetQ1, &targetQ3); setFreq(coreID,startFreq); waitCurFreq(coreID,startFreq); startBenchTime = measureLoop(NB_BENCH_META_REPET); fprintf(stdout,"Bench %d %.2f\n",startFreq, startBenchTime); startBenchSD = sd(NB_BENCH_META_REPET, startBenchTime, times); // Build the confidence interval for the target frequency confidenceInterval(NB_BENCH_META_REPET, targetBenchTime, targetBenchSD, &targetLowBoundTime, &targetHighBoundTime); fprintf(stdout,"targetLowbound : %lu ; targetHighbound : %lu\n", targetLowBoundTime,targetHighBoundTime); fprintf(stdout,"targetQ1 : %lu ; targetQ3 : %lu\n", targetQ1, targetQ3); // Build the confidence interval for the start frequency confidenceInterval(NB_BENCH_META_REPET, startBenchTime, startBenchSD, &startLowBoundTime, &startHighBoundTime); fprintf(stdout,"startLowbound : %lu ; startHighbound : %lu\n", startLowBoundTime,startHighBoundTime); // Check if the confidence intervals overlap if ( startLowBoundTime >= targetHighBoundTime || targetLowBoundTime >= startHighBoundTime ) { fprintf(stdout,"Confidence intervals do not overlap, alternatives are statistically different with selected confidence level\n"); } else if( startLowBoundTime < targetHighBoundTime || targetLowBoundTime > startHighBoundTime ) { if( ( startBenchTime >= targetLowBoundTime && startBenchTime <= targetHighBoundTime ) || ( targetBenchTime >= startLowBoundTime && targetBenchTime <= startHighBoundTime ) ) { fprintf(stdout,"Warning: confidence intervals overlap considerably, alternatives are equal with selected confidence level\n"); return; }else { fprintf(stdout,"Warning: confidence intervals overlap, we can not state any thing, need to do the t-test\n"); } } //lowBoundTime = targetLowBoundTime ; //highBoundTime = targetHighBoundTime; // Now we use the inter-quartile range lowBoundTime = targetQ1; highBoundTime = targetQ3; sync(); loop(); warmup_cpuid(); { unsigned int i = 0; unsigned int j = 0; unsigned int it = 0; unsigned int niters = 0; char validated = 0; double validateBenchTime=0; double validateBenchSD=0; unsigned long validateLowBoundTime=0; unsigned long validateHighBoundTime=0; for (it=0;it<NB_REPORT_TIMES;it++){ do { startLoopTime = 0; lateStartLoopTime = 0; endLoopTime = 0; niters = 0; #ifdef _DUMP resetDump(); #endif sync_rdtsc1(startLoopTime); setFreq(coreID,targetFreq); sync_rdtsc1(lateStartLoopTime); do { time = loop(); #ifdef _DUMP writeDump(time); #endif } while ( ( time < lowBoundTime || time > highBoundTime ) && ++niters < NB_TRY_REPET_LOOP ); sync_rdtsc2(endLoopTime); // Validation validated = 1; times[0] = time; measurements[it]= endLoopTime - startLoopTime; measurements_late[it]= endLoopTime - lateStartLoopTime; measurements_timestamps[it]= endLoopTime ; for ( i = 1 ; i < NB_VALIDATION_REPET ; i++ ) { times[i] = loop(); #ifdef _DUMP writeDump(times[i]); #endif } // Build a confidence interval for the new time value validateBenchTime = average(NB_VALIDATION_REPET, times); validateBenchSD = sd(NB_VALIDATION_REPET, validateBenchTime, times); confidenceInterval(NB_VALIDATION_REPET, validateBenchTime, validateBenchSD, &validateLowBoundTime, &validateHighBoundTime); if ( validateHighBoundTime < targetLowBoundTime || validateLowBoundTime > targetHighBoundTime ) { validated = 0; if (j%20==19) { setFreq(coreID,targetFreq); waitCurFreq(coreID,targetFreq); targetBenchTime = measureLoop(NB_BENCH_META_REPET); targetBenchSD = sd(NB_BENCH_META_REPET, targetBenchTime, times); // Build the inter-quartile range for the target frequency interQuartileRange(NB_BENCH_META_REPET, times, &targetQ1, &targetQ3); confidenceInterval(NB_BENCH_META_REPET, targetBenchTime, targetBenchSD, &targetLowBoundTime, &targetHighBoundTime); lowBoundTime = targetQ1; highBoundTime = targetQ3; } } setFreq(coreID,startFreq); waitCurFreq(coreID,startFreq); wait(NB_WAIT_US); }while(!validated && ++j < NB_TRY_REPET); if ( j >= NB_TRY_REPET || validated == 0 ){ it--; } #if NB_REPORT_TIMES == 1 fprintf(stdout,"Number of iterations to solution : %d ; Number of attempts : %d\n", niters, j+1); if ( j >= NB_TRY_REPET || validated == 0 ) fprintf(stdout,"Warning: The computed change time may not be accurate\n"); fprintf(stdout,"LastTime : %lu ; validateLowbound : %lu ; validateHighbound : %lu\n", time, validateLowBoundTime,validateHighBoundTime); #endif }} #if NB_REPORT_TIMES == 1 fprintf(stdout,"Change time (with write) : %lu\n" ,endLoopTime-startLoopTime); fprintf(stdout,"Change time : %lu\n" ,endLoopTime-lateStartLoopTime); fprintf(stdout,"Write cost : : %lu\n" ,lateStartLoopTime-startLoopTime); #else int i=0; for (i=0;i<NB_REPORT_TIMES;i++){ fprintf(stdout,"%lu\t%llu\t%lu\n",measurements[i],measurements_timestamps[i]-measurements_timestamps[0],measurements_late[i]); } #endif }
void icqv8_processChannel2(HICQ icq, ICQV8 *cfg, int sz, SNAC *snac) { static const struct snacproc snacs[] = { { 0x01, icqv8_snac01_table }, { 0x02, icqv8_snac02_table }, { 0x03, icqv8_snac03_table }, { 0x04, icqv8_snac04_table }, { 0x09, icqv8_snac09_table }, { 0x0B, icqv8_snac0B_table }, { 0x13, icqv8_snac13_table }, { 0x15, icqv8_snac15_table }, { 0x00, NULL } }; const SNAC_CMD *ptr; const struct snacproc *sproc; int rc; snac->family = SHORT_VALUE(snac->family); snac->subType = SHORT_VALUE(snac->subType); // DBGTracex(snac->family); // DBGTracex(snac->subType); for(sproc = snacs;sproc->tbl && sproc->id != snac->family;sproc++); ptr = sproc->tbl; // DBGMessage("***********************************************************************"); // DBGTracex(ptr); // DBGTracex(&icqv8_snac13_table); // CHKPoint(); while(ptr && ptr->subType) { // DBGTracex(ptr->subType); if(ptr->subType == snac->subType) { // CHKPoint(); rc = ptr->exec(icq, cfg, sz-sizeof(SNAC), snac->request, (void *) (snac+1)); if(rc) logError(icq,rc,snac->family,snac->subType,sz,snac); return; } ptr++; } // DBGTracex(ptr->subType); // if(icqPacket(icq, 7, pkt, sz, 0, 0)) // return; writeDump(icq,sz,snac); // DBGMessage("***********************************************************************"); }
BOOL DebugMainLoop(void) { BOOL fFinished = FALSE; BOOL fTerminating = FALSE; while (!fFinished) { DEBUG_EVENT DebugEvent; // debugging event information DWORD dwContinueStatus = DBG_CONTINUE; // exception continuation PPROCESS_INFO pProcessInfo; PTHREAD_INFO pThreadInfo; // 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 (debugOptions.verbose_flag) { lprintf("EXCEPTION PID=%lu TID=%lu ExceptionCode=0x%lx dwFirstChance=%lu\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 (!pProcessInfo->fBreakpointSignalled) { pProcessInfo->fBreakpointSignalled = TRUE; if (debugOptions.hEvent) { SetEvent(debugOptions.hEvent); CloseHandle(debugOptions.hEvent); } if (debugOptions.dwThreadId) { DWORD dwThreadId = debugOptions.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 (!debugOptions.breakpoint_flag) { dwContinueStatus = DBG_CONTINUE; break; } } } if (ExceptionCode == STATUS_WX86_BREAKPOINT) { if (!pProcessInfo->fWowBreakpointSignalled) { pProcessInfo->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 (ExceptionCode == DBG_CONTROL_C || ExceptionCode == DBG_CONTROL_BREAK) { dwContinueStatus = DBG_CONTINUE; } else if (!debugOptions.first_chance) { // Ignore other first change exceptions break; } } 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 && ExceptionCode != DBG_CONTROL_C && ExceptionCode != DBG_CONTROL_BREAK) { continue; } CONTEXT Context; if (!getThreadContext(pProcessInfo->hProcess, hThread, &Context)) { continue; } dumpStack(pProcessInfo->hProcess, hThread, &Context); if (!DebugEvent.u.Exception.dwFirstChance) { EXCEPTION_POINTERS ExceptionPointers; ExceptionPointers.ExceptionRecord = pExceptionRecord; ExceptionPointers.ContextRecord = &Context; MINIDUMP_EXCEPTION_INFORMATION ExceptionParam; ExceptionParam.ThreadId = DebugEvent.dwThreadId; ExceptionParam.ExceptionPointers = &ExceptionPointers; ExceptionParam.ClientPointers = FALSE; writeDump(DebugEvent.dwProcessId, pProcessInfo, &ExceptionParam); } } 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 (debugOptions.verbose_flag) { lprintf("CREATE_THREAD PID=%lu TID=%lu\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 (debugOptions.verbose_flag) { PCSTR lpModuleName = lpImageName ? getBaseName(lpImageName) : ""; lprintf("CREATE_PROCESS PID=%lu TID=%lu lpBaseOfImage=%p %s\n", DebugEvent.dwProcessId, DebugEvent.dwThreadId, DebugEvent.u.CreateProcessInfo.lpBaseOfImage, lpModuleName ); } HANDLE hProcess = DebugEvent.u.CreateProcessInfo.hProcess; pProcessInfo = &g_Processes[DebugEvent.dwProcessId]; pProcessInfo->hProcess = hProcess; pProcessInfo->fDumpWritten = !debugOptions.minidump; 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 (debugOptions.verbose_flag) { lprintf("EXIT_THREAD PID=%lu TID=%lu dwExitCode=0x%lx\n", DebugEvent.dwProcessId, DebugEvent.dwThreadId, DebugEvent.u.ExitThread.dwExitCode ); } // Remove the thread from the thread list pProcessInfo = &g_Processes[DebugEvent.dwProcessId]; // Dump the stack on abort() if (!fTerminating && isAbnormalExitCode(DebugEvent.u.ExitThread.dwExitCode)) { pThreadInfo = &pProcessInfo->Threads[DebugEvent.dwThreadId]; HANDLE hProcess = pProcessInfo->hProcess; HANDLE hThread = pThreadInfo->hThread; CONTEXT Context; if (getThreadContext(hProcess, hThread, &Context)) { dumpStack(hProcess, hThread, &Context); } } pProcessInfo->Threads.erase(DebugEvent.dwThreadId); break; case EXIT_PROCESS_DEBUG_EVENT: { if (debugOptions.verbose_flag) { lprintf("EXIT_PROCESS PID=%lu TID=%lu dwExitCode=0x%lx\n", DebugEvent.dwProcessId, DebugEvent.dwThreadId, DebugEvent.u.ExitProcess.dwExitCode ); } pProcessInfo = &g_Processes[DebugEvent.dwProcessId]; // Dump the stack on abort() if (!fTerminating && isAbnormalExitCode(DebugEvent.u.ExitThread.dwExitCode)) { pThreadInfo = &pProcessInfo->Threads[DebugEvent.dwThreadId]; HANDLE hProcess = pProcessInfo->hProcess; HANDLE hThread = pThreadInfo->hThread; CONTEXT Context; if (getThreadContext(hProcess, hThread, &Context)) { dumpStack(hProcess, hThread, &Context); } writeDump(DebugEvent.dwProcessId, pProcessInfo, nullptr); } // Remove the process from the process list g_Processes.erase(DebugEvent.dwProcessId); if (!SymCleanup(pProcessInfo->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 (debugOptions.verbose_flag) { PCSTR lpModuleName = lpImageName ? getBaseName(lpImageName) : ""; lprintf("LOAD_DLL PID=%lu TID=%lu lpBaseOfDll=%p %s\n", DebugEvent.dwProcessId, DebugEvent.dwThreadId, DebugEvent.u.LoadDll.lpBaseOfDll, lpModuleName ); } pProcessInfo = &g_Processes[DebugEvent.dwProcessId]; loadModule(pProcessInfo->hProcess, hFile, lpImageName, DebugEvent.u.LoadDll.lpBaseOfDll); break; } case UNLOAD_DLL_DEBUG_EVENT: if (debugOptions.verbose_flag) { lprintf("UNLOAD_DLL PID=%lu TID=%lu lpBaseOfDll=%p\n", DebugEvent.dwProcessId, DebugEvent.dwThreadId, DebugEvent.u.UnloadDll.lpBaseOfDll ); } pProcessInfo = &g_Processes[DebugEvent.dwProcessId]; SymUnloadModule64(pProcessInfo->hProcess, (UINT_PTR)DebugEvent.u.UnloadDll.lpBaseOfDll); break; case OUTPUT_DEBUG_STRING_EVENT: { if (debugOptions.verbose_flag) { lprintf("OUTPUT_DEBUG_STRING PID=%lu TID=%lu\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 (debugOptions.verbose_flag) { lprintf("RIP PID=%lu TID=%lu\n", DebugEvent.dwProcessId, DebugEvent.dwThreadId ); } break; default: if (debugOptions.verbose_flag) { lprintf("EVENT%lu PID=%lu TID=%lu\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; }