예제 #1
0
파일: EventSuite.cpp 프로젝트: Stretto/mago
void EventSuite::RunDebuggee( RefPtr<IProcess>& process )
{
    Exec    exec;

    TEST_ASSERT_RETURN( SUCCEEDED( exec.Init( mCallback ) ) );

    LaunchInfo      info = { 0 };
    wchar_t         cmdLine[ MAX_PATH ] = L"";
    IProcess*       proc = NULL;
    const wchar_t*  Debuggee = EventsDebuggee;

    swprintf_s( cmdLine, L"\"%s\"", Debuggee );

    info.CommandLine = cmdLine;
    info.Exe = Debuggee;

    TEST_ASSERT_RETURN( SUCCEEDED( exec.Launch( &info, proc ) ) );

    uint32_t    pid = proc->GetId();
    mCallback->SetTrackEvents( true );

    process = proc;
    proc->Release();

    for ( int i = 0; !mCallback->GetProcessExited(); i++ )
    {
        HRESULT hr = exec.WaitForEvent( DefaultTimeoutMillis );

        // this should happen after process exit
        if ( hr == E_TIMEOUT )
            break;

        TEST_ASSERT_RETURN( SUCCEEDED( hr ) );
        TEST_ASSERT_RETURN( SUCCEEDED( exec.DispatchEvent() ) );

        if ( process->IsStopped() )
            TEST_ASSERT_RETURN( SUCCEEDED( exec.Continue( process, true ) ) );
    }

    TEST_ASSERT( mCallback->GetLoadCompleted() );
    TEST_ASSERT( mCallback->GetProcessExited() );

    //AssertProcessFinished( pid );
}
예제 #2
0
    void EventCallback::OnLoadComplete( IProcess* process, DWORD threadId )
    {
        OutputDebugStringA( "EventCallback::OnLoadComplete\n" );

        HRESULT     hr = S_OK;
        RefPtr<LoadCompleteEvent>   event;
        RefPtr<Program>             prog;
        RefPtr<Thread>              thread;

        if ( !mEngine->FindProgram( process->GetId(), prog ) )
            return;

        if ( !prog->FindThread( threadId, thread ) )
            return;

        hr = MakeCComObject( event );
        if ( FAILED( hr ) )
            return;

        hr = SendEvent( event.Get(), prog.Get(), thread.Get() );

        IProcess*   coreProc = prog->GetCoreProcess();

        mEntryPoint = coreProc->GetEntryPoint();

        if ( mEntryPoint != 0 )
        {
            RefPtr<Module> mod;

            if ( prog->FindModuleContainingAddress( mEntryPoint, mod ) )
            {
                Address userEntryPoint = 0;
                if ( FindUserEntryPoint( mod, userEntryPoint ) )
                    mEntryPoint = userEntryPoint;
            }

            hr = prog->SetInternalBreakpoint( mEntryPoint, EntryPointCookie );
            // if we couldn't set the BP, then don't expect it later
            if ( FAILED( hr ) )
                mEntryPoint = 0;
        }
    }
예제 #3
0
void StepOneThreadSuite::RunDebuggee( Step* steps, int stepsCount )
{
    Exec    exec;

    TEST_ASSERT_RETURN( SUCCEEDED( exec.Init( mCallback ) ) );

    LaunchInfo  info = { 0 };
    wchar_t     cmdLine[ MAX_PATH ] = L"";
    IProcess*   proc = NULL;
    const wchar_t*  Debuggee = StepOneThreadDebuggee;

    Symbol funcs[] =
    {
        { NULL, 0 },
        { L"Scenario1Func0", 0 },
        { L"Scenario1Func1", 0 },
        { L"Scenario1Func2", 0 },
        { L"Scenario1Func3", 0 },
    };
    TEST_ASSERT_RETURN( SUCCEEDED( FindSymbols( Debuggee, funcs, _countof( funcs ) ) ) );

    swprintf_s( cmdLine, L"\"%s\" 1", Debuggee );

    info.CommandLine = cmdLine;
    info.Exe = Debuggee;

    TEST_ASSERT_RETURN( SUCCEEDED( exec.Launch( &info, proc ) ) );

    uint32_t            pid = proc->GetId();
    int                 nextStep = 0;
    char                msg[1024] = "";
    RefPtr<IProcess>    process;

    process = proc;
    proc->Release();
    mCallback->SetTrackLastEvent( true );

    for ( int i = 0; !mCallback->GetProcessExited(); i++ )
    {
        bool    continued = false;
        HRESULT hr = exec.WaitForEvent( DefaultTimeoutMillis );

        // this should happen after process exit
        if ( hr == E_TIMEOUT )
            break;

        TEST_ASSERT_RETURN( SUCCEEDED( hr ) );
        TEST_ASSERT_RETURN( SUCCEEDED( hr = exec.DispatchEvent() ) );

        if ( !process->IsStopped() )
            continue;

        if ( (mCallback->GetLastEvent()->Code != ExecEvent_ModuleLoad)
            && (mCallback->GetLastEvent()->Code != ExecEvent_ModuleUnload)
            && (mCallback->GetLastEvent()->Code != ExecEvent_ThreadStart)
            && (mCallback->GetLastEvent()->Code != ExecEvent_ThreadExit)
            && (mCallback->GetLastEvent()->Code != ExecEvent_LoadComplete) )
        {
            Step*   curStep = &steps[nextStep];
            nextStep++;

            RefPtr<Thread>  thread;
            CONTEXT_X86     context = { 0 };
            if ( mCallback->GetLastThreadId() != 0 )
            {
                TEST_ASSERT_RETURN( process->FindThread( mCallback->GetLastThreadId(), thread.Ref() ) );
                TEST_ASSERT_RETURN( exec.GetThreadContext( 
                    process, thread->GetId(), CONTEXT_X86_FULL, 0, &context, sizeof context ) == S_OK );
            }

            uintptr_t   baseAddr = 0;
            RefPtr<IModule> procMod = mCallback->GetProcessModule();
            if ( procMod.Get() != NULL )
                baseAddr = (uintptr_t) procMod->GetImageBase();

            // TODO: test threadId

            if ( mCallback->GetLastEvent()->Code != curStep->Event.Code )
            {
                sprintf_s( msg, "Expected event '%s', got '%s'.", 
                    GetEventName( curStep->Event.Code ),
                    GetEventName( mCallback->GetLastEvent()->Code ) );
                TEST_FAIL_MSG( msg );
                break;
            }
            else if ( (curStep->Event.Code == ExecEvent_Exception)
                && (curStep->Event.ExceptionCode != ((ExceptionEventNode*) mCallback->GetLastEvent().get())->Exception.ExceptionCode) )
            {
                sprintf_s( msg, "Expected exception %08x, got %08x.", 
                    curStep->Event.ExceptionCode, 
                    ((ExceptionEventNode*) mCallback->GetLastEvent().get())->Exception.ExceptionCode );
                TEST_FAIL_MSG( msg );
                break;
            }
            else if ( (curStep->Event.Code == ExecEvent_Exception)
                || (curStep->Event.Code == ExecEvent_StepComplete) 
                || (curStep->Event.Code == ExecEvent_Breakpoint) )
            {
                uintptr_t   funcRva = funcs[curStep->Event.FunctionIndex].RelativeAddress;
                uintptr_t   addr = (funcRva + curStep->Event.AddressOffset + baseAddr);

                if ( context.Eip != addr )
                {
                    sprintf_s( msg, "Expected instruction pointer at %08x, got %08x.", addr, context.Eip );
                    TEST_FAIL_MSG( msg );
                    break;
                }
            }

            mCallback->SetCanStepInFunctionReturnValue( curStep->Action.CanStepInFunction );

            if ( curStep->Action.BPAddressOffset != 0 )
            {
                uintptr_t   funcRva = funcs[curStep->Action.FunctionIndex].RelativeAddress;
                uintptr_t   addr = (funcRva + curStep->Action.BPAddressOffset + baseAddr);
                TEST_ASSERT_RETURN( SUCCEEDED( exec.SetBreakpoint( process.Get(), addr ) ) );
            }

            if ( curStep->Action.Action == Action_StepInstruction )
            {
                TEST_ASSERT_RETURN( SUCCEEDED( 
                    exec.StepInstruction( process.Get(), curStep->Action.StepIn, true ) ) );
                continued = true;
            }
            else if ( curStep->Action.Action == Action_StepRange )
            {
                AddressRange range = { context.Eip, context.Eip };
                TEST_ASSERT_RETURN( SUCCEEDED( 
                    exec.StepRange( process.Get(), curStep->Action.StepIn, range, true ) ) );
                continued = true;
            }
        }

        if ( !continued )
            TEST_ASSERT_RETURN( SUCCEEDED( exec.Continue( process, true ) ) );
    }

    TEST_ASSERT( mCallback->GetLoadCompleted() );
    TEST_ASSERT( mCallback->GetProcessExited() );
}
예제 #4
0
int _tmain( int argc, _TCHAR* argv[] )
{
    BOOL                bRet = FALSE;
    STARTUPINFO         startupInfo = { sizeof startupInfo };
    PROCESS_INFORMATION procInfo = { 0 };
    DEBUG_EVENT         event = { 0 };
    _EventCallback   callback;
    Exec        exec;
    HRESULT     hr = S_OK;
    LaunchInfo  info = { 0 };

    InitDebug();

    //char*   s1 = new ( _NORMAL_BLOCK, __FILE__, __LINE__ ) char[100];
    //strcpy( s1, "hello, yo!" );
    //char*   s2 = (char*) malloc( 300 );
    //strcpy( s2, "say what?" );

    callback.SetExec( &exec );

    hr = exec.Init( &callback );
    if ( FAILED( hr ) )
        goto Error;
    
#if 0
    bRet = CreateProcess( L"F:\\Users\\Magus\\Documents\\Visual Studio 2008\\Projects\\test1\\Debug\\test1.exe",
    //bRet = CreateProcess( L"F:\\Users\\Magus\\Documents\\Visual Studio 2008\\Projects\\test1\\x64\\Debug\\test1.exe",
        NULL,
        NULL,
        NULL,
        FALSE,
        DEBUG_ONLY_THIS_PROCESS,
        NULL,
        NULL,
        &startupInfo,
        &procInfo );
    if ( !bRet )
        goto Error;
#else

//#define TEST_APP64

#ifndef TEST_APP64
    info.CommandLine = L"\"F:\\Users\\Magus\\Documents\\Visual Studio 2008\\Projects\\Debugger1\\Debug\\test1.exe\"";
    info.Exe = L"F:\\Users\\Magus\\Documents\\Visual Studio 2008\\Projects\\Debugger1\\Debug\\test1.exe";
#else
    info.CommandLine =L"\"F:\\Users\\Magus\\Documents\\Visual Studio 2008\\Projects\\Debugger1\\x64\\Debug\\test1.exe\"";
    info.Exe = L"\"F:\\Users\\Magus\\Documents\\Visual Studio 2008\\Projects\\Debugger1\\x64\\Debug\\test1.exe\"";
#endif

    IProcess*   proc = NULL;

    //hr = exec.Attach( 5336, proc );
    hr = exec.Launch( &info, proc );
    if ( FAILED( hr ) )
        goto Error;
#endif

#if 0
    bRet = WaitForDebugEvent( &event, INFINITE );
    if ( !bRet )
        goto Error;
#else
    int stepCount = 0;

    for ( int i = 0; /* doesn't end */ ; i++ )
    {
        hr = exec.WaitForEvent( 1000 );
        if ( FAILED( hr ) )
            goto Error;

        hr = exec.DispatchEvent();
        if ( FAILED( hr ) )
            goto Error;

#if 1
        if ( proc->IsStopped() )
        {
            if ( callback.GetHitBp() )
            {
                stepCount++;

                //11728
                IModule*    mod = NULL;
                UINT_PTR    baseAddr = 0;

                callback.GetModule( mod );
                baseAddr = (UINT_PTR) mod->GetImageBase();
                mod->Release();

                //hr = exec.StepOut( proc, (void*) (baseAddr + 0x00011728) );
                //hr = exec.StepInstruction( proc, true );

                if ( stepCount > 1 )
                    hr = exec.StepInstruction( proc, true, true );
                else
                {
                    //113A5
                    AddressRange    range = { baseAddr + 0x0001137A, baseAddr + 0x000113A5 };
                    hr = exec.StepRange( proc, false, range, true );
                }

                if ( FAILED( hr ) )
                    goto Error;
            }
            else
            {
                hr = exec.Continue( proc, true );
                if ( FAILED( hr ) )
                    goto Error;
            }
        }
#endif

#if 1
        if ( i == 0 )
        {
            IModule*    mod = NULL;
            UINT_PTR    baseAddr = 0;

            callback.GetModule( mod );
            baseAddr = (UINT_PTR) mod->GetImageBase();

            // 0x003C137A, 0x003C1395
            // 1137A, 11395

            //exec.SetBreakpoint( proc, baseAddr + 0x0001138C, 255 );
            exec.SetBreakpoint( proc, baseAddr + 0x0001137A );
            //exec.SetBreakpoint( proc, baseAddr + 0x00011395, 129 );

            mod->Release();
        }
#endif
    }
#endif

Error:
    //exec.Detach( proc );

    // when the debugger goes away, so does the debuggee automatically

    //if ( procInfo.hThread != NULL )
    //{
    //    CloseHandle( procInfo.hThread );
    //}

    //if ( procInfo.hProcess != NULL )
    //{
    //    TerminateProcess( procInfo.hProcess, MAXINT );
    //    CloseHandle( procInfo.hProcess );
    //}

    if ( proc != NULL )
        proc->Release();

    return 0;
}
예제 #5
0
파일: EventSuite.cpp 프로젝트: Stretto/mago
void EventSuite::TestExceptionNotHandledAllChances()
{
    enum State
    {
        State_Init,
        State_FirstNotHandled,
        State_SecondNotHandled,
        State_Done
    };

    Exec    exec;
    State   state = State_Init;

    TEST_ASSERT_RETURN( SUCCEEDED( exec.Init( mCallback ) ) );

    LaunchInfo      info = { 0 };
    wchar_t         cmdLine[ MAX_PATH ] = L"";
    IProcess*       proc = NULL;
    const wchar_t*  Debuggee = EventsDebuggee;

    swprintf_s( cmdLine, L"\"%s\" exception 1", Debuggee );

    info.CommandLine = cmdLine;
    info.Exe = Debuggee;

    TEST_ASSERT_RETURN( SUCCEEDED( exec.Launch( &info, proc ) ) );

    uint32_t    pid = proc->GetId();
    RefPtr<IProcess>    process( proc );

    proc->Release();
    mCallback->SetTrackLastEvent( true );

    for ( int i = 0; !mCallback->GetProcessExited(); i++ )
    {
        bool        handled = true;
        uint32_t    timeoutMillis = DefaultTimeoutMillis;

        // it can take more than half a second to get the ProcessExit event 
        // after an unhandled exception
        if ( state == State_SecondNotHandled )
            timeoutMillis = 5 * 1000;

        HRESULT hr = exec.WaitForEvent( timeoutMillis );

        // this should happen after process exit
        if ( hr == E_TIMEOUT )
        {
            // Timing out is still an error, but it's only expected sometimes 
            // after SecondNotHandled, if the timeout to wait for the process
            // to end is still not enough. See where the timeout is set above.
            TEST_ASSERT( state == State_SecondNotHandled );
            break;
        }

        TEST_ASSERT_RETURN( SUCCEEDED( hr ) );
        TEST_ASSERT_RETURN( SUCCEEDED( exec.DispatchEvent() ) );

        if ( state == State_SecondNotHandled )
        {
            TEST_ASSERT( mCallback->GetProcessExited() );
            state = State_Done;
        }

        if ( process->IsStopped() )
        {
            if ( (mCallback->GetLastEvent().get() != NULL) 
                && (mCallback->GetLastEvent()->Code == ExecEvent_Exception) )
            {
                ExceptionEventNode* node = (ExceptionEventNode*) mCallback->GetLastEvent().get();

                if ( node->Exception.ExceptionCode == EXCEPTION_INT_DIVIDE_BY_ZERO )
                {
                    if ( state == State_Init )
                    {
                        TEST_ASSERT( node->FirstChance );
                        state = State_FirstNotHandled;
                        handled = false;
                    }
                    else if ( state == State_FirstNotHandled )
                    {
                        TEST_ASSERT( !node->FirstChance );
                        state = State_SecondNotHandled;
                        handled = false;
                    }
                    else
                    {
                        TEST_FAIL( "Too many Integer divides by zero." );
                        exec.Terminate( process.Get() );
                    }
                }
                else
                {
                    TEST_FAIL( "Unexpected exception." );
                    exec.Terminate( process.Get() );
                }
            }

            TEST_ASSERT_RETURN( SUCCEEDED( exec.Continue( process, handled ) ) );
        }
    }

    TEST_ASSERT( mCallback->GetLoadCompleted() );
    TEST_ASSERT( mCallback->GetProcessExited() );

    TEST_ASSERT( state == State_Done );
}
예제 #6
0
파일: EventSuite.cpp 프로젝트: Stretto/mago
void EventSuite::TestExceptionNotHandledFirstChanceCaught()
{
    enum State
    {
        State_Init,
        State_FirstNotHandled,
        State_Done
    };

    Exec    exec;
    State   state = State_Init;

    TEST_ASSERT_RETURN( SUCCEEDED( exec.Init( mCallback ) ) );

    LaunchInfo      info = { 0 };
    wchar_t         cmdLine[ MAX_PATH ] = L"";
    IProcess*       proc = NULL;
    const wchar_t*  Debuggee = EventsDebuggee;

    swprintf_s( cmdLine, L"\"%s\" exception 2", Debuggee );

    info.CommandLine = cmdLine;
    info.Exe = Debuggee;

    TEST_ASSERT_RETURN( SUCCEEDED( exec.Launch( &info, proc ) ) );

    uint32_t    pid = proc->GetId();
    RefPtr<IProcess>    process( proc );

    proc->Release();
    mCallback->SetTrackLastEvent( true );

    for ( int i = 0; !mCallback->GetProcessExited(); i++ )
    {
        bool    handled = true;

        HRESULT hr = exec.WaitForEvent( DefaultTimeoutMillis );

        // this should happen after process exit
        if ( hr == E_TIMEOUT )
            break;

        TEST_ASSERT_RETURN( SUCCEEDED( hr ) );
        TEST_ASSERT_RETURN( SUCCEEDED( exec.DispatchEvent() ) );

        if ( process->IsStopped() )
        {
            if ( (mCallback->GetLastEvent().get() != NULL) 
                && (mCallback->GetLastEvent()->Code == ExecEvent_Exception) )
            {
                ExceptionEventNode* node = (ExceptionEventNode*) mCallback->GetLastEvent().get();

                TEST_ASSERT( node->FirstChance );

                if ( node->Exception.ExceptionCode == EXCEPTION_INT_DIVIDE_BY_ZERO )
                {
                    if ( state == State_Init )
                    {
                        state = State_FirstNotHandled;
                        handled = false;
                    }
                    else
                    {
                        TEST_FAIL( "Too many Integer divides by zero." );
                        exec.Terminate( process.Get() );
                    }
                }
                else
                {
                    TEST_FAIL( "Unexpected exception." );
                    exec.Terminate( process.Get() );
                }
            }
            else if ( (mCallback->GetLastEvent().get() != NULL) 
                && (mCallback->GetLastEvent()->Code == ExecEvent_Breakpoint)
                && (state == State_FirstNotHandled) )
            {
                state = State_Done;

                CONTEXT_X86     context = { 0 };
                RefPtr<Thread>  thread;

                TEST_ASSERT_RETURN( process->FindThread( mCallback->GetLastThreadId(), thread.Ref() ) );
                context.ContextFlags = CONTEXT_X86_FULL;
                TEST_ASSERT_RETURN( GetThreadContextX86( thread->GetHandle(), &context ) );
                TEST_ASSERT( context.Eax == 1877514773 );
            }

            TEST_ASSERT_RETURN( SUCCEEDED( exec.Continue( process, handled ) ) );
        }
    }

    TEST_ASSERT( mCallback->GetLoadCompleted() );
    TEST_ASSERT( mCallback->GetProcessExited() );

    TEST_ASSERT( state == State_Done );
}