sampaxp.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 709 行 · 第 1/2 页
C
709 行
static void newThread( DWORD id, HANDLE th )
{
threadInfo = realloc( threadInfo, (threadCount+1)* sizeof( thread_info ) );
threadInfo[ threadCount ].id = id;
threadInfo[ threadCount ].th = th;
threadInfo[ threadCount ].live = TRUE;
threadInfo[ threadCount ].index = threadCount;
AllocSamples( id );
threadInfo[ threadCount ].Samples = Samples;
threadInfo[ threadCount ].SampleIndex = SampleIndex;
if( CallGraphMode ) {
threadInfo[ threadCount ].CallGraph = CallGraph;
threadInfo[ threadCount ].SampleCount = SampleCount;
}
threadCount++;
} /* newThread */
/*
* deadThread - a thread is dead
*/
static void deadThread( DWORD id )
{
thread_info *ti;
ti = getThreadInfo( id );
if( ti != NULL ) {
ti->live = FALSE;
}
} /* deadThread */
/*
* loadProg - load the task to sample
*/
static void loadProg( char *exe, char *cmdline )
{
STARTUPINFO sinfo;
PROCESS_INFORMATION pinfo;
int rc;
memset( &sinfo, 0, sizeof( sinfo ) );
sinfo.wShowWindow = SW_NORMAL;
rc = CreateProcess( NULL, /* application name */
cmdline, /* command line */
NULL, /* process attributes */
NULL, /* thread attributes */
FALSE, /* inherit handles */
DEBUG_PROCESS,//DEBUG_ONLY_THIS_PROCESS, /* creation flags */
NULL, /* environment block */
NULL, /* starting directory */
&sinfo, /* startup info */
&pinfo /* process info */
);
if( !rc ) {
internalError( MsgArray[MSG_SAMPLE_3-ERR_FIRST_MESSAGE] );
}
rc = WaitForDebugEvent( &debugEvent, -1 );
if( !rc || (debugEvent.dwDebugEventCode != CREATE_PROCESS_DEBUG_EVENT) ||
(debugEvent.dwProcessId != pinfo.dwProcessId) ) {
internalError( MsgArray[MSG_SAMPLE_3-ERR_FIRST_MESSAGE] );
}
taskPid = debugEvent.dwProcessId;
processHandle = debugEvent.u.CreateProcessInfo.hProcess;
newThread( debugEvent.dwThreadId, debugEvent.u.CreateProcessInfo.hThread );
codeLoad( debugEvent.u.CreateProcessInfo.hFile,
(DWORD) debugEvent.u.CreateProcessInfo.lpBaseOfImage,
exe,
SAMP_MAIN_LOAD );
} /* loadProg */
/*
* myGetThreadContext - get a thread's context
*/
static void myGetThreadContext( DWORD id, CONTEXT *pc )
{
thread_info *ti;
pc->ContextFlags = CONTEXT_TO_USE;
ti = getThreadInfo( id );
if( ti != NULL ) {
GetThreadContext( ti->th, pc );
}
} /* myGetThreadContext */
static void mySetThreadContext( DWORD id, CONTEXT *pc )
{
thread_info *ti;
pc->ContextFlags = CONTEXT_TO_USE;
ti = getThreadInfo( id );
if( ti != NULL ) {
SetThreadContext( ti->th, pc );
}
} /* mySetThreadContext */
/*
* TimerThread - handle timer ticks
*/
DWORD __stdcall TimerThread( LPVOID parms )
{
CONTEXT con;
int i;
uint_32 Fir;
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 );
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 */
static unsigned GetString( int unicode, LPVOID p, char *buff, unsigned max )
{
DWORD len;
--max;
if( ReadProcessMemory( processHandle, p, buff, max, &len ) ) {
buff[len] = '\0';
return( len );
}
len = 0;
if( unicode ) {
for( ;; ) {
if( max <= 1 ) break;
if( !ReadProcessMemory( processHandle, p, buff, 2, NULL ) ) break;
if( *(wchar_t *)buff == '\0' ) break;
buff += sizeof( wchar_t );
p = (wchar_t *)p + 1;
max -= sizeof( wchar_t );
len += sizeof( wchar_t );
}
*(wchar_t *)buff = '\0';
} else {
for( ;; ) {
if( max == 0 ) break;
if( !ReadProcessMemory( processHandle, p, buff, 1, NULL ) ) break;
if( *(char *)buff == '\0' ) break;
buff += sizeof( char );
p = (char *)p + 1;
max -= sizeof( char );
len += sizeof( char );
}
*(char *)buff = '\0';
}
return( len );
}
static int GetDllName( LOAD_DLL_DEBUG_INFO *ld, char *buff, unsigned max )
{
LPVOID name;
DWORD len;
wchar_t *p;
//NYI: spiffy up to scrounge around in the image
if( ld->lpImageName == 0 ) return( FALSE );
ReadProcessMemory( processHandle, ld->lpImageName, &name, sizeof( name ), &len );
if( len != sizeof( name ) ) return( FALSE );
if( name == 0 ) return( FALSE );
len = GetString( ld->fUnicode, name, buff, max );
if( len == 0 ) return( FALSE );
if( ld->fUnicode ) {
for( p = (wchar_t *)buff; *p != '\0'; ++p, ++buff ) {
*buff = *p;
}
*buff = '\0';
}
return( TRUE );
}
/*
* StartProg - start sampling a program
*/
void StartProg( char *cmd, char *prog, char *args )
{
DWORD code;
DWORD tid;
CONTEXT con;
BOOL waiting_for_first_bp;
DWORD len;
DWORD continue_how;
BOOL rc;
DWORD ttid;
HANDLE tth;
int i;
uint_32 Fir;
cmd = cmd;
strcpy( utilBuff, prog );
len = strlen( utilBuff );
utilBuff[ len++ ] = ' ';
for( i=0;i<args[0];i++ ) {
utilBuff[len++] = args[i+1];
}
utilBuff[len] = 0;
loadProg( prog, utilBuff );
tid = debugEvent.dwThreadId;
tth = CreateThread( NULL, 2048, (LPVOID) 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;
while( 1 ) {
ContinueDebugEvent( taskPid, tid, continue_how );
rc = WaitForDebugEvent( &debugEvent, -1 );
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 */
void SysDefaultOptions( void ) { }
void SysParseOptions( char c, char **cmd )
{
char buff[2];
switch( c ) {
case 'r':
SetTimerRate( cmd );
break;
default:
Output( MsgArray[MSG_INVALID_OPTION-ERR_FIRST_MESSAGE] );
buff[0] = c;
buff[1] = '\0';
Output( buff );
Output( "\r\n" );
fatal();
break;
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?