/* * 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 */
void GForce::RecordZeroSample( long inCurTime ) { int i; for ( i = 0; i < mNum_S_Steps; i++ ) mSampleFcn -> mFcn[ i ] = 0; RecordSample( inCurTime ); }
int main( int argc, char* argv[] ) { std::string uris[] = { "dc1394:[fps=30,dma=10,size=640x480,iso=400]//0", "convert:[fmt=RGB24]//v4l:///dev/video0", "convert:[fmt=RGB24]//v4l:///dev/video1", "" }; std::string filename = "video.pango"; if( argc >= 2 ) { const std::string uri = std::string(argv[1]); if( argc == 3 ) { filename = std::string(argv[2]); } RecordSample(uri, filename, filename + ".ui"); }else{ std::cout << "Usage : SimpleRepeatVideo [video-uri] [buffer-filename]" << std::endl << std::endl; std::cout << "Where video-uri describes a stream or file resource, e.g." << std::endl; std::cout << "\tfile:[realtime=1]///home/user/video/movie.pvn" << std::endl; std::cout << "\tfile:///home/user/video/movie.avi" << std::endl; std::cout << "\tfiles:///home/user/seqiemce/foo%03d.jpeg" << std::endl; std::cout << "\tdc1394:[fmt=RGB24,size=640x480,fps=30,iso=400,dma=10]//0" << std::endl; std::cout << "\tdc1394:[fmt=FORMAT7_1,size=640x480,pos=2+2,iso=400,dma=10]//0" << std::endl; std::cout << "\tv4l:///dev/video0" << std::endl; std::cout << "\tconvert:[fmt=RGB24]//v4l:///dev/video0" << std::endl; std::cout << "\tmjpeg://http://127.0.0.1/?action=stream" << std::endl; std::cout << std::endl; // Try to open some video device for(int i=0; !uris[i].empty(); ++i ) { try{ std::cout << "Trying: " << uris[i] << std::endl; RecordSample(uris[i], filename, filename + ".ui"); return 0; }catch(pangolin::VideoException) {} } } return 0; }
void GForce::RecordSample( long inCurTime, float* inSound, float inScale, long inNumBins, float* inFFT, float inFFTScale, long inFFTNumBins) { float mag, sum; int i, n; ExprUserFcn* fcn; // Only use/process bins we'll actually use if ( inNumBins > mNum_S_Steps ) inNumBins = mNum_S_Steps; // Calc a 1/RMS avg value... if ( mNormalizeInput ) { // Find an RMS amplitude for the sample for ( sum = 0.0001, i = 0; i < inNumBins; i++ ) { mag = inSound[ i ]; sum += mag * mag; } inScale = mMagScale * .009 * ( (float) inNumBins ) / ( sqrt( sum ) ); } else inScale *= mMagScale; // Now write the sample to memory, adjusted for amplitude... fcn = (ExprUserFcn*) mSampleFcn; fcn -> mNumFcnBins = inNumBins; for ( i = 0; i < inNumBins; i++ ) { mag = inSound[ i ]; fcn -> mFcn[ i ] = inSound[ i ] * inScale; } XFloatList::GaussSmooth( 1.3, inNumBins, fcn -> mFcn ); // Flatten the ends of the sample... n = inNumBins / 20 + 1; if ( n <= inNumBins ) { for ( i = 0; i < n; i++ ) { mag = sin( .5 * 3.1 * i / n ); fcn -> mFcn[ i ] *= mag; fcn -> mFcn[ inNumBins - i - 1 ] *= mag; } } // Now write the FFT data to memory, adjusted for amplitude... fcn = (ExprUserFcn*) mFFTFcn; fcn -> mNumFcnBins = inFFTNumBins; for ( i = 0; i < inFFTNumBins; i++ ) { fcn -> mFcn[ i ] = inFFT[ i ] * inFFTScale; } RecordSample( inCurTime ); }
/* * 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 */
void interrupt far timer_handler( union INTPACK r ) { if( --TimerMod == 0 ) { TimerMod = TimerMult; _CHAIN_TO( old_timer_handler ); } else { /* end of interrupt (expected by 8259 before you do RETI) */ outp( INT_CTRL, EOI ); } if( ! SamplerOff ) { if( InsiderTime == 0 ) { ++InsiderTime; if( SampleIndex == 0 ) { Samples->pref.tick = CurrTick; if( CallGraphMode ) { CallGraph->pref.tick = CurrTick; } } ++CurrTick; #ifdef __NETWARE__ /* avoid pointer truncation warning */ RecordSample( (union INTPACK *)FP_OFF(&r) ); #else RecordSample( &r ); #endif if( SampleIndex >= Margin ) { if( InDOS() ) { Save_Request = TRUE; } else { /* We are not in DOS so we can suspend things for a while and save our block of samples */ if( Save_Request ) { Save_Request = 0; } StopAndSave(); } if( SampleIndex >= Ceiling ) { if( CallGraphMode ) { --SampleCount; SampleIndex = LastSampleIndex; } else { --SampleIndex; } LostData = TRUE; } } --InsiderTime; } } }
/* * 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 */
/* Handle breakpoints - we expect to see breakpoints in the dynamic linker * (which we set ourselves) as well as profiler marks (embedded in the * profiled application's code). */ static bool ProcessBreakpoint( pid_t pid, u_long ip ) { static int ld_state = RT_CONSISTENT; // This ought to be per-pid int ptrace_sig = 0; #if defined( MD_x86 ) user_regs_struct regs; // on x86, when breakpoint was hit the EIP points to the next // instruction, so we must be careful ptrace( PTRACE_GETREGS, pid, NULL, ®s ); if( ip == Rdebug.r_brk + sizeof( opcode_type ) ) { #elif defined( MD_ppc ) if( ip == Rdebug.r_brk ) { #endif opcode_type brk_opcode = BRKPOINT; int status; int ret; /* The dynamic linker breakpoint was hit, meaning that * libraries are being loaded or unloaded. This gets a bit * tricky because we must restore the original code that was * at the breakpoint and execute it, but we still want to * keep the breakpoint. */ if( WriteMem( pid, &saved_opcode, Rdebug.r_brk, sizeof( saved_opcode ) ) != sizeof( saved_opcode ) ) printf( "WriteMem() #1 failed\n" ); ReadMem( pid, &Rdebug, (addr_off)DbgRdebug, sizeof( Rdebug ) ); dbg_printf( "ld breakpoint hit, state is " ); switch( Rdebug.r_state ) { case RT_ADD: dbg_printf( "RT_ADD\n" ); AddLibrary( pid, Rdebug.r_map ); ld_state = RT_ADD; break; case RT_DELETE: dbg_printf( "RT_DELETE\n" ); ld_state = RT_DELETE; break; case RT_CONSISTENT: dbg_printf( "RT_CONSISTENT\n" ); if( ld_state == RT_DELETE ) RemoveLibrary( pid, Rdebug.r_map ); ld_state = RT_CONSISTENT; break; default: dbg_printf( "error!\n" ); break; } #if defined( MD_x86 ) regs.eip--; ptrace( PTRACE_SETREGS, pid, NULL, ®s ); #endif // unset breakpoint, single step, re-set breakpoint if( ptrace( PTRACE_SINGLESTEP, pid, NULL, (void *)ptrace_sig ) < 0 ) perror( "ptrace()" ); do { // have to loop since SIGALRM can interrupt us here ret = waitpid( pid, &status, 0 ); } while( (ret < 0) && (errno == EINTR) ); if( ret == -1) perror( "waitpid()" ); if( WriteMem( pid, &brk_opcode, Rdebug.r_brk, sizeof( brk_opcode ) ) != sizeof( brk_opcode ) ) dbg_printf( "WriteMem() #2 failed with errno %d for pid %d, %d bytes (at %p)!\n", errno, pid, sizeof( brk_opcode ), Rdebug.r_brk ); return( true ); // indicate this was our breakpoint } else { dbg_printf( "Not an ld breakpoint, assuming mark\n" ); #if defined( MD_x86 ) return( ProcessMark( pid, ®s ) ); #endif } return( false ); } /* * Real time signal (SIGALRM) handler. All we really need to do is wake up * periodically to interrupt waitpid(), the signal handler need not do much * at all. */ static void alarm_handler( int signo ) { TimerTicked = true; } /* Install periodic real time alarm signal */ static void InstSigHandler( int msec_period ) { struct sigaction sigalrm; struct itimerval timer; sigalrm.sa_handler = (void *)alarm_handler; sigemptyset( &sigalrm.sa_mask ); sigalrm.sa_flags = 0; sigaction( SIGALRM, &sigalrm, NULL ); timer.it_interval.tv_sec = 0; timer.it_interval.tv_usec = msec_period * 1000; timer.it_value.tv_sec = 0; timer.it_value.tv_usec = msec_period * 1000; if( setitimer( ITIMER_REAL, &timer, NULL ) ) { InternalError( MsgArray[MSG_SAMPLE_6 - ERR_FIRST_MESSAGE] ); } } /* * Main sampler loop. We run the profiled application under the control of * ptrace(). The sampler installs a SIGALRM handler which ticks at the desired * rate. Whenever the SIGALRM interrupts our own waitpid(), we send a SIGSTOP * to the profiled app and when the child app notifies us of the SIGSTOP, we * remember the current execution point and continue the profiled app. Note * that we may miss some ticks but this is not a problem - the ticks don't * even need to be regular to provide usable results. */ static void SampleLoop( pid_t pid ) { static int ptrace_sig = 0; static bool do_cont = true; int status; user_regs_struct regs; bool sample_continue = true; int ret; opcode_type brk_opcode = BRKPOINT; TimerTicked = false; InstSigHandler( SleepTime ); do { if( do_cont && ptrace( PTRACE_CONT, pid, NULL, (void *)ptrace_sig ) == -1) perror( "ptrace()" ); ret = waitpid( pid, &status, 0 ); if( (ret < 0) && (errno == EINTR) ) { /* did we get woken up by SIGALRM? */ if( TimerTicked ) { TimerTicked = false; /* interrupt child process - next waitpid() will see this */ kill( pid, SIGSTOP ); } else { dbg_printf( "who the hell interrupted waitpid()?\n" ); } do_cont = false; continue; } if( ret < 0 ) perror( "waitpid()" ); do_cont = true; /* record current execution point */ #if defined( MD_x86 ) ptrace( PTRACE_GETREGS, pid, NULL, ®s ); #elif defined( MD_ppc ) regs.eip = ptrace( PTRACE_PEEKUSER, pid, REGSIZE * PT_NIP, NULL ); #endif if( WIFSTOPPED( status ) ) { /* If debuggee has dynamic section, try getting the r_debug struct * every time the child process stops. The r_debug data may not be * available immediately after the child process first loads. */ if( !HaveRdebug && (DbgDyn != NULL) ) { if( Get_ld_info( pid, DbgDyn, &Rdebug, &DbgRdebug ) ) { AddLibrary( pid, Rdebug.r_map ); HaveRdebug = true; /* Set a breakpoint in dynamic linker. That way we can be * informed on dynamic library load/unload events. */ ReadMem( pid, &saved_opcode, Rdebug.r_brk, sizeof( saved_opcode ) ); dbg_printf( "setting ld breakpoint at %p, old opcode was %X\n", Rdebug.r_brk, saved_opcode ); WriteMem( pid, &brk_opcode, Rdebug.r_brk, sizeof( brk_opcode ) ); } } sample_continue = false; switch( (ptrace_sig = WSTOPSIG( status )) ) { case SIGSEGV: dbg_printf( "SIGSEGV at %p\n", regs.eip ); sample_continue = true; break; case SIGILL: dbg_printf( "SIGILL at %p\n", regs.eip ); sample_continue = true; break; case SIGABRT: dbg_printf( "SIGABRT at %p\n", regs.eip ); sample_continue = true; break; case SIGINT: dbg_printf( "SIGINT at %p\n", regs.eip ); sample_continue = true; break; case SIGTRAP: dbg_printf( "SIGTRAP at %p\n", regs.eip ); if( ProcessBreakpoint( pid, regs.eip ) ) { // don't pass on SIGTRAP if we expected this breakpoint ptrace_sig = 0; } sample_continue = true; break; case SIGSTOP: /* presumably we were behind this SIGSTOP */ RecordSample( regs.eip, 1 ); ptrace_sig = 0; sample_continue = true; break; default: /* all other signals get passed down to the child and we let * the child handle them (or not handle and die) */ sample_continue = true; break; } } else if( WIFEXITED( status ) ) { dbg_printf( "WIFEXITED pid %d\n", pid ); report(); sample_continue = false; } else if( WIFSIGNALED( status ) ) { dbg_printf( "WIFSIGNALED pid %d\n", pid ); report(); sample_continue = false; } } while( sample_continue ); } static int GetExeNameFromPid( pid_t pid, char *buffer, int max_len ) { char procfile[24]; int len; sprintf( procfile, "/proc/%d/exe", pid ); len = readlink( procfile, buffer, max_len ); if( len < 0 ) len = 0; buffer[len] = '\0'; return( len ); }
void StartProg( const char *cmd, const char *prog, char *full_args, char *dos_args ) { const char *src; char *dst; USHORT drive; ULONG map; USHORT len; USHORT tid; USHORT rc; char buff[BSIZE]; seg_offset where; char *cmd_tail; /* unused parameters */ (void)cmd; MaxThread = 0; GrowArrays( 1 ); src = prog; dst = UtilBuff; DosQCurDisk( &drive, &map ); if( src[0] == '\0' || src[1] == '\0' || src[1] != ':' ) { *dst++ = drive - 1 + 'A'; *dst++ = ':'; } else { *dst++ = *src++; *dst++ = *src++; } if( src[0] != '\\' ) { ++dst; len = BUFF_SIZE - ( dst - UtilBuff ); DosQCurDir( drive, (PBYTE)dst, &len ); dst[-1] = '\\'; if( *dst == '\\' || *dst == '\0' ) { *dst = '\0'; } else { while( *dst != '\0' ) { ++dst; } *dst++ = '\\'; } } strcpy( dst, src ); dst = UtilBuff + strlen( UtilBuff ) + 1; cmd_tail = dst; strcpy( dst, full_args ); dst += strlen( dst ); *++dst = '\0'; /* Need two nulls at end */ LoadProg( UtilBuff, cmd_tail ); Output( MsgArray[MSG_SAMPLE_1 - ERR_FIRST_MESSAGE] ); Output( UtilBuff ); Output( "\r\n" ); Buff.pid = Pid; Buff.tid = 1; Buff.cmd = PT_CMD_STOP; LibLoadPTrace( &Buff ); if( OSVer < 0x1400 ) { /* OS/2 2.x already dumped out MainMod as a Module load */ CodeLoad( &Buff, MainMod, ExeName, SAMP_MAIN_LOAD ); } InitialCS = Buff.u.r.CS; rc = DosCreateThread( Sleeper, (PUSHORT)&tid, Stack + STACK_SIZE ); if( rc != 0 ) { InternalError( MsgArray[MSG_SAMPLE_4 - ERR_FIRST_MESSAGE] ); } rc = DosSetPrty( PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, tid ); if( rc != 0 ) { InternalError( MsgArray[MSG_SAMPLE_5 - ERR_FIRST_MESSAGE] ); } Buff.pid = Pid; Buff.tid = 1; for( ;; ) { Buff.cmd = PT_CMD_GO; if( LibLoadPTrace( &Buff ) != 0 ) { InternalError( MsgArray[MSG_SAMPLE_7 - ERR_FIRST_MESSAGE] ); } if( Buff.cmd == PT_RET_BREAK && Buff.u.r.DX != 0 ) { /* a mark */ len = 0; Buff.segv = Buff.u.r.DX; Buff.offv = Buff.u.r.AX; for( ;; ) { Buff.cmd = PT_CMD_READ_MEM_D; DosPTrace( &Buff ); buff[len] = Buff.value; if( Buff.cmd != PT_RET_SUCCESS ) buff[len] = '\0'; if( len == BSIZE ) buff[len] = '\0'; if( buff[len] == '\0' ) break; ++len; Buff.offv++; } where.segment = Buff.u.r.CS; where.offset = Buff.u.r.IP; WriteMark( buff, where ); Buff.cmd = PT_CMD_READ_REGS; DosPTrace( &Buff ); Buff.u.r.IP++; Buff.cmd = PT_CMD_WRITE_REGS; DosPTrace( &Buff ); continue; } else if( Buff.cmd == PT_RET_BREAK ) { /* common info pass */ CommonAddr.segment = Buff.u.r.CX; CommonAddr.offset = Buff.u.r.BX; Buff.cmd = PT_CMD_READ_REGS; DosPTrace( &Buff ); Buff.u.r.IP++; Buff.cmd = PT_CMD_WRITE_REGS; DosPTrace( &Buff ); continue; } if( Buff.cmd == PT_RET_FUNERAL ) break; if( Buff.cmd != PT_RET_LIB_LOADED && Buff.cmd != PT_RET_STOPPED && Buff.cmd != PT_RET_TRD_TERMINATE ) { InternalError( MsgArray[MSG_SAMPLE_6 - ERR_FIRST_MESSAGE] ); break; } RecordSample( Buff.u.r.IP, Buff.u.r.CS, Buff.tid ); } report(); }
void StartProg( char *cmd, char *prog, char *full_args, char *dos_args ) { seg_offset where; int error_num; char buff[BSIZE]; Fptr32 fp; short initial_cs; int len; cmd = cmd; SampleIndex = 0; CurrTick = 0L; D32HookTimer( TimerMult ); /* ask for timer - before D32DebugInit!! */ D32DebugBreakOp(&Break); /* Get the 1 byte break op */ error_num = D32DebugInit( &Proc ); if( error_num == 0 ) { strcpy( buff, full_args ); error_num = D32DebugLoad( prog, buff, &Proc ); } if( error_num != 0 ) { Output( MsgArray[MSG_SAMPLE_2-ERR_FIRST_MESSAGE] ); Output( prog ); Output( "\r\n" ); MsgFini(); exit(1); } where.offset = 0; where.segment = 0; WriteCodeLoad( where, ExeName, SAMP_MAIN_LOAD ); fp.sel = 1; fp.off = 0; D32Relocate(&fp); WriteAddrMap( 1, fp.sel, fp.off ); initial_cs = Proc.cs; for( ;; ) { D32DebugRun( &Proc ); if( SampleIndex > Margin && Proc.cs == initial_cs ) { StopAndSave(); } if( Proc.int_id == 8 ) { ++InsiderTime; RecordSample( Proc.eip, Proc.cs ); --InsiderTime; } else if( Proc.int_id == 3 && (Proc.edx & 0xffff) != 0 ) { len = 0; /* this is a mark */ where.segment = Proc.edx & 0xffff; where.offset = Proc.eax; for( ;; ) { if( !D32AddressCheck( where.segment, where.offset, 1, NULL ) ) break; D32DebugRead( where.offset, where.segment, 0, &buff[len], 1 ); if( len == BSIZE ) break; if( buff[len] == '\0' ) break; len++; where.offset++; } buff[len] = '\0'; where.segment = Proc.cs; where.offset = Proc.eip; WriteMark( buff, where ); Proc.eip++; } else if( Proc.int_id == 3 ) { /* remember common storage */ CommonAddr.segment = Proc.ecx & 0xffff; /* area ... */ CommonAddr.offset = Proc.ebx; Proc.eip++; } else { break; } } D32UnHookTimer(); if( Proc.int_id != 0x21 ) { Output( MsgArray[MSG_SAMPLE_1-ERR_FIRST_MESSAGE] ); Output( MsgArray[Exceptions[Proc.int_id]+MSG_EXCEPT_0-ERR_FIRST_MESSAGE] ); Output( "\r\n" ); } D32DebugTerm(); report(); }