static void RecordSample( unsigned offset, unsigned tid ) { samp_block *old_samples; unsigned old_sample_index; unsigned old_sample_count; if( tid > MaxThread ) { GrowArrays( tid ); } --tid; LastSampleIndex = SampleIndexP[tid]; if( SampleIndexP[tid] == 0 ) { SamplesP[tid]->pref.tick = CurrTick; if( CallGraphMode ) { CallGraphP[tid]->pref.tick = CurrTick; } } ++CurrTick; SamplesP[tid]->d.sample.sample[SampleIndexP[tid]].offset = offset; SamplesP[tid]->d.sample.sample[SampleIndexP[tid]].segment = FlatSeg; SampleIndexP[tid]++; if( CallGraphMode ) { SampleCountP[tid]++; } if( CallGraphMode && tid == 0 ) { old_sample_count = SampleCount; old_samples = Samples; /* since RecordCGraph isn't */ old_sample_index = SampleIndex; /* used to threads, we fool */ Samples = SamplesP[tid]; /* it into storing the info */ SampleIndex = SampleIndexP[tid]; /* in the right place by */ SampleCount = SampleCountP[tid]; RecordCGraph(); /* changing its pointers */ SamplesP[tid] = Samples; /* and restoring them later */ SampleIndexP[tid] = SampleIndex; SampleCountP[tid] = SampleCount; Samples = old_samples; SampleIndex = old_sample_index; SampleCount = old_sample_count; } if( SampleIndexP[tid] >= Margin ) { StopAndSave(); } }
void StartProg( char *cmd, char *prog, char *full_args, char *dos_args ) { char exe_name[PATH_MAX]; pid_t save_pgrp; pid_t pid; int status; MaxThread = 0; GrowArrays( 1 ); HaveRdebug = false; DbgDyn = NULL; OrigPGrp = getpgrp(); Attached = true; pid = Pid = SamplePid; /* allow attaching to existing process by pid */ if( pid == 0 || ptrace( PTRACE_ATTACH, pid, NULL, NULL ) == -1 ) { int num_args; size_t len; const char **argv; Attached = false; /* massage 'full_args' into argv format */ len = strlen( full_args ); num_args = SplitParms( full_args, NULL, len ); argv = alloca( ( num_args + 2 ) * sizeof( *argv ) ); argv[SplitParms( full_args, argv + 1, len ) + 1] = NULL; argv[0] = prog; Output( MsgArray[MSG_SAMPLE_1 - ERR_FIRST_MESSAGE] ); Output( prog ); Output( "\n" ); save_pgrp = getpgrp(); setpgid( 0, OrigPGrp ); pid = fork(); if( pid == -1 ) InternalError( MsgArray[MSG_SAMPLE_3 - ERR_FIRST_MESSAGE] ); if( pid == 0 ) { int rc; if( ptrace( PTRACE_TRACEME, 0, NULL, NULL ) < 0 ) { InternalError( MsgArray[MSG_SAMPLE_4 - ERR_FIRST_MESSAGE] ); } dbg_printf( "executing '%s'\n", prog ); for( rc = 0; argv[rc] != NULL; ++rc ) dbg_printf( "argv[%d] = '%s'\n", rc, argv[rc] ); rc = execve( prog, (char const * const *)argv, (char const * const *)environ ); dbg_printf( "execve() failed, returned %d\n", rc ); InternalError( MsgArray[MSG_SAMPLE_3 - ERR_FIRST_MESSAGE] ); // failsafe } setpgid( 0, save_pgrp ); strcpy( exe_name, prog ); } else if( pid ) { GetExeNameFromPid( pid, exe_name, PATH_MAX ); Output( MsgArray[MSG_SAMPLE_1 - ERR_FIRST_MESSAGE] ); Output( exe_name ); Output( "\n" ); } if( (pid != -1) && (pid != 0) ) { /* wait until it hits _start (upon execve) or gives us a SIGSTOP (if attached) */ if( waitpid( pid, &status, 0 ) < 0 ) goto fail; if( !WIFSTOPPED( status ) ) goto fail; if( Attached ) { if( WSTOPSIG( status ) != SIGSTOP ) { goto fail; } } else { if( WSTOPSIG( status ) != SIGTRAP ) { goto fail; } } DbgDyn = GetDebuggeeDynSection( exe_name ); errno = 0; } if( errno != 0 ) { pid = 0; } else { /* record information about main executable and initialize shared * library tracking */ InitLibMap(); CodeLoad( exe_name, 0, SAMP_MAIN_LOAD ); SampleLoop( pid ); FiniLibMap(); } return; fail: if( pid != 0 && pid != -1 ) { if( Attached ) { ptrace( PTRACE_DETACH, pid, NULL, NULL ); Attached = false; } else { ptrace( PTRACE_KILL, pid, NULL, NULL ); waitpid( pid, &status, 0 ); } } InternalError( MsgArray[MSG_SAMPLE_5 - ERR_FIRST_MESSAGE] ); }
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(); }