/* Handle profiler marks (hardcoded breakpoints with a string) */ static bool ProcessMark( pid_t pid, user_regs_struct *regs ) { if( (regs->edx & 0xffff) != 0 ) { /* this is a mark */ char buff[BUFF_SIZE]; int len = 0; seg_offset where; /* read the mark string char by char */ for( ;; ) { if( len >= (BUFF_SIZE - 1) ) break; ReadMem( pid, buff + len, regs->eax + len, 1 ); if( buff[len] == '\0' ) break; ++len; } buff[len] = '\0'; where.segment = FlatSeg; where.offset = regs->eip; WriteMark( buff, where ); return( true ); } else { dbg_printf( "hardcoded breakpoint was not a mark!\n" ); return( false ); } }
/* * 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 */
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(); }