/* * TimerThread - handle timer ticks */ static DWORD WINAPI TimerThread( LPVOID parms ) { CONTEXT con; int i; uint_32 Fir; parms = parms; for( ;; ) { Sleep( sleepTime ); if( doneSample ) { break; } timeOut = TRUE; for( i = 0; i < threadCount; i++ ) { if( threadInfo[i].live ) { myGetThreadContext( threadInfo[i].id, &con ); Fir = LODWORD( con.Fir ); RecordSample( Fir, SEGMENT, threadInfo[i].id ); timeOut = FALSE; } } } return( 0 ); } /* TimerThread */
/* * SkipBreakpoint - increment Fir past a breakpoint */ static void SkipBreakpoint( DWORD tid ) { CONTEXT con; uint_32 Fir; unsigned_64 newFir; myGetThreadContext( tid, &con ); Fir = LODWORD( con.Fir ); newFir.u._32[0] = Fir + 4; newFir.u._32[1] = 0; con.Fir = *((DWORDLONG *)&newFir); mySetThreadContext( tid, &con ); } /* SkipBreakpoint */
/* * TimerThread - handle timer ticks */ DWORD WINAPI TimerThread( LPVOID parms ) { CONTEXT con; int i; parms = parms; while( 1 ) { Sleep( sleepTime ); if( doneSample ) { break; } timeOut = TRUE; for( i=0;i<threadCount;i++ ) { if( threadInfo[i].live ) { myGetThreadContext( threadInfo[i].id, &con ); RecordSample( con.Eip, con.SegCs, threadInfo[i].id ); timeOut = FALSE; } } } return( 0 ); } /* TimerThread */
/* * StartProg - start sampling a program */ void StartProg( char *cmd, char *prog, char *full_args, char *dos_args ) { DWORD code; DWORD tid; CONTEXT con; BOOL waiting_for_first_bp; SIZE_T len; DWORD continue_how; BOOL rc; seg_offset where; DWORD ttid; HANDLE tth; cmd = cmd; strcpy( utilBuff, prog ); strcat( utilBuff, " " ); strcat( utilBuff, full_args ); loadProg( prog, utilBuff ); tid = debugEvent.dwThreadId; tth = CreateThread( NULL, 1024, TimerThread, NULL, 0, &ttid ); if( !tth ) { internalError( MsgArray[MSG_SAMPLE_3 - ERR_FIRST_MESSAGE] ); } /* attempt to ensure that we can get all of our samples in one shot */ SetThreadPriority( tth, THREAD_PRIORITY_TIME_CRITICAL ); Output( MsgArray[MSG_SAMPLE_1 - ERR_FIRST_MESSAGE] ); Output( prog ); Output( "\r\n" ); waiting_for_first_bp = TRUE; continue_how = DBG_CONTINUE; for( ;; ) { ContinueDebugEvent( taskPid, tid, continue_how ); rc = WaitForDebugEvent( &debugEvent, INFINITE ); continue_how = DBG_CONTINUE; tid = debugEvent.dwThreadId; switch( debugEvent.dwDebugEventCode ) { case EXCEPTION_DEBUG_EVENT: code = debugEvent.u.Exception.ExceptionRecord.ExceptionCode; switch( code ) { case STATUS_SINGLE_STEP: if( timeOut ) { myGetThreadContext( tid, &con ); RecordSample( con.Eip, con.SegCs, tid ); timeOut = FALSE; } break; case STATUS_BREAKPOINT: if( !waiting_for_first_bp ) { myGetThreadContext( tid, &con ); con.Eip--; if( (con.Edx & 0xffff) != 0 ) { /* this is a mark */ ReadProcessMemory( processHandle, (LPVOID)con.Eax, utilBuff, BUFF_SIZE - 1, len ); utilBuff[len] = '\0'; where.segment = con.SegCs; where.offset = con.Eip; WriteMark( utilBuff, where ); } else { /* this passes CommonAddr */ commonAddr.segment = con.Ecx & 0xffff; commonAddr.offset = con.Ebx; } } else { waiting_for_first_bp = FALSE; } break; case STATUS_DATATYPE_MISALIGNMENT: case STATUS_ACCESS_VIOLATION: case STATUS_IN_PAGE_ERROR: case STATUS_NO_MEMORY: case STATUS_ILLEGAL_INSTRUCTION: case STATUS_NONCONTINUABLE_EXCEPTION: case STATUS_INVALID_DISPOSITION: case STATUS_ARRAY_BOUNDS_EXCEEDED: case STATUS_FLOAT_DENORMAL_OPERAND: case STATUS_FLOAT_DIVIDE_BY_ZERO: case STATUS_FLOAT_INVALID_OPERATION: case STATUS_FLOAT_OVERFLOW: case STATUS_FLOAT_STACK_CHECK: case STATUS_FLOAT_UNDERFLOW: case STATUS_INTEGER_DIVIDE_BY_ZERO: case STATUS_INTEGER_OVERFLOW: case STATUS_PRIVILEGED_INSTRUCTION: case STATUS_STACK_OVERFLOW: case STATUS_CONTROL_C_EXIT: if( debugEvent.u.Exception.dwFirstChance ) { continue_how = DBG_EXCEPTION_NOT_HANDLED; } else { Output( MsgArray[MSG_SAMPLE_4 - ERR_FIRST_MESSAGE] ); Output( "\r\n" ); doneSample = TRUE; TerminateProcess( processHandle, 0 ); report(); return; } break; default: continue_how = DBG_EXCEPTION_NOT_HANDLED; break; } break; case LOAD_DLL_DEBUG_EVENT: if( GetDllName( &debugEvent.u.LoadDll, utilBuff, sizeof( utilBuff ) ) ) { codeLoad( debugEvent.u.LoadDll.hFile, (DWORD) debugEvent.u.LoadDll.lpBaseOfDll, utilBuff, SAMP_CODE_LOAD ); } break; case CREATE_THREAD_DEBUG_EVENT: newThread( debugEvent.dwThreadId, debugEvent.u.CreateThread.hThread ); break; case EXIT_THREAD_DEBUG_EVENT: deadThread( debugEvent.dwThreadId ); break; case EXIT_PROCESS_DEBUG_EVENT: doneSample = TRUE; // TerminateProcess( processHandle, 0 ); - already gone!! report(); return; } } } /* StartProg */
/* * StartProg - start sampling a program */ void StartProg( const char *cmd, const char *prog, char *full_args, char *dos_args ) { DWORD code; DWORD tid; CONTEXT con; BOOL waiting_for_first_bp; DWORD continue_how; BOOL rc; DWORD ttid; HANDLE tth; uint_32 Fir; /* unused parameters */ (void)cmd; strcpy( utilBuff, prog ); strcat( utilBuff, " " ); strcat( utilBuff, full_args ); loadProg( prog, utilBuff ); tid = debugEvent.dwThreadId; tth = CreateThread( NULL, 2048, TimerThread, NULL, 0, &ttid ); if( !tth ) { internalError( MsgArray[MSG_SAMPLE_3 - ERR_FIRST_MESSAGE] ); } /* Attempt to ensure that we can record our samples in one shot */ SetThreadPriority( tth, THREAD_PRIORITY_TIME_CRITICAL ); Output( MsgArray[MSG_SAMPLE_1 - ERR_FIRST_MESSAGE] ); Output( prog ); Output( "\r\n" ); waiting_for_first_bp = TRUE; continue_how = DBG_CONTINUE; for( ;; ) { ContinueDebugEvent( taskPid, tid, continue_how ); rc = WaitForDebugEvent( &debugEvent, INFINITE ); continue_how = DBG_CONTINUE; tid = debugEvent.dwThreadId; switch( debugEvent.dwDebugEventCode ) { case EXCEPTION_DEBUG_EVENT: code = debugEvent.u.Exception.ExceptionRecord.ExceptionCode; switch( code ) { case STATUS_SINGLE_STEP: if( timeOut ) { myGetThreadContext( tid, &con ); Fir = LODWORD( con.Fir ); RecordSample( Fir, SEGMENT, tid ); timeOut = FALSE; } break; case STATUS_BREAKPOINT: /* Skip past the breakpoint in the startup code */ if( waiting_for_first_bp ) { SkipBreakpoint( tid ); waiting_for_first_bp = FALSE; } break; case STATUS_DATATYPE_MISALIGNMENT: case STATUS_ACCESS_VIOLATION: case STATUS_IN_PAGE_ERROR: case STATUS_NO_MEMORY: case STATUS_ILLEGAL_INSTRUCTION: case STATUS_NONCONTINUABLE_EXCEPTION: case STATUS_INVALID_DISPOSITION: case STATUS_ARRAY_BOUNDS_EXCEEDED: case STATUS_FLOAT_DENORMAL_OPERAND: case STATUS_FLOAT_DIVIDE_BY_ZERO: case STATUS_FLOAT_INVALID_OPERATION: case STATUS_FLOAT_OVERFLOW: case STATUS_FLOAT_STACK_CHECK: case STATUS_FLOAT_UNDERFLOW: case STATUS_INTEGER_DIVIDE_BY_ZERO: case STATUS_INTEGER_OVERFLOW: case STATUS_PRIVILEGED_INSTRUCTION: case STATUS_STACK_OVERFLOW: case STATUS_CONTROL_C_EXIT: if( debugEvent.u.Exception.dwFirstChance ) { continue_how = DBG_EXCEPTION_NOT_HANDLED; } else { Output( MsgArray[MSG_SAMPLE_4 - ERR_FIRST_MESSAGE] ); Output( "\r\n" ); doneSample = TRUE; TerminateProcess( processHandle, 0 ); report(); return; } break; default: continue_how = DBG_EXCEPTION_NOT_HANDLED; break; } break; case LOAD_DLL_DEBUG_EVENT: if( GetDllName( &debugEvent.u.LoadDll, utilBuff, sizeof( utilBuff ) ) ) { codeLoad( debugEvent.u.LoadDll.hFile, (DWORD) debugEvent.u.LoadDll.lpBaseOfDll, utilBuff, SAMP_CODE_LOAD ); } break; case CREATE_THREAD_DEBUG_EVENT: newThread( debugEvent.dwThreadId, debugEvent.u.CreateThread.hThread ); break; case EXIT_THREAD_DEBUG_EVENT: deadThread( debugEvent.dwThreadId ); break; case EXIT_PROCESS_DEBUG_EVENT: doneSample = TRUE; // TerminateProcess( processHandle, 0 ); - already gone!! report(); return; } } } /* StartProg */