Esempio n. 1
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() );
}
Esempio n. 2
0
void EventSuite::TryHandlingException( bool firstTimeHandled, bool expectedChanceSecondTime )
{
    enum State
    {
        State_Init,
        State_FirstHandled,
        State_SecondHandled,
        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;

        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() )
        {
            CONTEXT_X86     context = { 0 };
            RefPtr<Thread>  thread;

            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 );

            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_FirstHandled;
                        handled = firstTimeHandled;
                    }
                    else if ( state == State_FirstHandled )
                    {
                        TEST_ASSERT( node->FirstChance == expectedChanceSecondTime );
                        state = State_SecondHandled;

                        context.Ebx = 455;
                        TEST_ASSERT_RETURN( context.Eax != 237 );
                        TEST_ASSERT_RETURN( 
                            exec.SetThreadContext( 
                                process, thread->GetId(), &context, sizeof context ) == S_OK );
                    }
                    else
                    {
                        TEST_FAIL( "Too many Integer divides by zero." );
                        exec.Terminate( process.Get() );
                    }
                }
                else
                {
                    TEST_ASSERT( node->FirstChance );
                    TEST_FAIL( "Unexpected exception." );
                    exec.Terminate( process.Get() );
                }
            }
            else if ( (mCallback->GetLastEvent().get() != NULL) 
                && (mCallback->GetLastEvent()->Code == ExecEvent_StepComplete)
                && (state == State_SecondHandled) )
            {
                state = State_Done;
                TEST_ASSERT( context.Eax == 237 );
            }

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

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

    TEST_ASSERT( state == State_Done );
}