⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 accrun.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Handles interfaces to Windows NT debugger functions
*               to handle all debug events (single step, breakpoints etc).
*
****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <direct.h>
#include "madregs.h"
#include "stdnt.h"

typedef enum {
    T_OFF,
    T_ON_CURR,
    T_ON_NEXT
}   set_t;

/*
 * setATBit - control if we are tracing
 */
static void setATBit( thread_info *ti, set_t set )
{
    CONTEXT con;

    con.ContextFlags = CONTEXT_CONTROL;
    MyGetThreadContext( ti, &con );
#if defined( MD_x86 )
    if( set != T_OFF ) {
        con.EFlags |= TRACE_BIT;
    } else {
        con.EFlags &= ~TRACE_BIT;
    }
    con.ContextFlags = CONTEXT_CONTROL;
    MySetThreadContext( ti, &con );
#elif defined( MD_axp )
    {
        DWORD           bytes;
        brkpnt_type     brk = BRK_POINT;

        if( set != T_OFF ) {
            ti->brk_addr = AdjustIP( &con, 0 );
            if( set == T_ON_NEXT )
                ti->brk_addr += 4;
                ReadProcessMemory( ProcessInfo.process_handle,
                    ( LPVOID )ti->brk_addr, ( LPVOID )&ti->brk_opcode,
                    sizeof( ti->brk_opcode ), ( LPDWORD )&bytes );
            if( ti->brk_opcode != brk ) {
                WriteProcessMemory( ProcessInfo.process_handle,
                    ( LPVOID )ti->brk_addr, ( LPVOID )&brk, sizeof( brk ),
                    ( LPDWORD )&bytes );
            } else {
                ti->brk_addr = 0;
            }
        } else if( ti->brk_addr != 0 ) {
            WriteProcessMemory( ProcessInfo.process_handle,
                ( LPVOID )ti->brk_addr, ( LPVOID )&ti->brk_opcode,
                sizeof( ti->brk_opcode ), ( LPDWORD )&bytes );
            ti->brk_addr = 0;
        }
    }
#elif defined( MD_ppc )
    if( set != T_OFF ) {
        con.Msr |= TRACE_BIT;
    } else {
        con.Msr &= ~TRACE_BIT;
    }
    con.ContextFlags = CONTEXT_CONTROL;
    MySetThreadContext( ti, &con );
#else
    #error setATBit not configured
#endif
}

/*
 * setTBitsetTBitInAllThreads - turn the t-bit on or off in all threads.
 */
static void setTBitInAllThreads( set_t set )
{
    thread_info *ti;

    ti = ProcessInfo.thread_list;
    while( ti != NULL ) {
        if( ti->alive ) {
            SuspendThread( ti->thread_handle );
        }
        ti = ti->next;
    }

    ti = ProcessInfo.thread_list;
    while( ti != NULL ) {
        if( ti->alive ) {
            setATBit( ti, set );
        }
        ti = ti->next;
    }

    ti = ProcessInfo.thread_list;
    while( ti != NULL ) {
        if( ti->alive ) {
            ResumeThread( ti->thread_handle );
        }
        ti = ti->next;
    }
}

void InterruptProgram( void )
{
    setTBitInAllThreads( T_ON_CURR );
    // a trick to make app execute long enough to hit a breakpoint
    PostMessage( HWND_TOPMOST, WM_NULL, 0, 0 );
    PendingProgramInterrupt = TRUE;
}

bool Terminate( void )
{
    HANDLE  hp;

    hp = OpenProcess( PROCESS_ALL_ACCESS, FALSE, DebugeePid );
    if( hp != NULL ) {
        TerminateProcess( hp, 0 );
        CloseHandle( hp );
        return( TRUE );
    } else {
        return( FALSE );
    }
}

/*
 * consoleHandler - handle console ctrl c
 */
static BOOL WINAPI consoleHandler( DWORD type )
{
    if( type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT ) {
        /*
         * Since NT has no way do an async stop of a process, this is the next
         * best thing.  By turning on the the T-bit in all threads, we force
         * the process to stop the next time any one of its threads stop.
         * If all threads are blocked waiting for an event, then the process
         * will not stop until the event is satisfied.  Most often, the
         * main thread of the process will be blocked awaiting input, and
         * just running the mouse over the window will cause the app to
         * run and then trace-trap
         */
        InterruptProgram();
        return( TRUE );
    } else {
        return( FALSE );
    }
}


/*
 * setTBit - control if we are tracing
 */
static void setTBit( set_t set )
{
    thread_info *ti;

    ti = FindThread( DebugeeTid );
    setATBit( ti, set );
}

/*
 * handleInt3 - process an encountered break point
 */
#if defined( MD_x86 )
static DWORD    BreakFixed;
#endif

static int handleInt3( DWORD state )
{
#if defined( MD_x86 )
    thread_info *ti;
    CONTEXT     con;

    (void)state; // Unused
    ti = FindThread( DebugeeTid );
    if( ti == NULL ) {
        HANDLE  th;

        if( pOpenThread == NULL ) {
            return( 0 );
        }
        th = pOpenThread( DebugeeTid );
        AddThread( DebugeeTid, th, NULL );
        ti = FindThread( DebugeeTid );
        ti->is_foreign = TRUE;
    }
    if( ti->is_foreign ) {
        HANDLE  proc;
        DWORD   written;
        BYTE    ch;

        MyGetThreadContext( ti, &con );
        con.Eip--;
        if( !FindBreak( ( WORD ) con.SegCs, ( DWORD ) con.Eip, &ch ) ) {
            MySetThreadContext( ti, &con );
            return( COND_BREAK );
        }
        BreakFixed = con.Eip;
        proc = OpenProcess( PROCESS_ALL_ACCESS, FALSE, DebugeePid );
        WriteProcessMemory( proc, ( LPVOID ) con.Eip, &ch, 1, &written );
        con.EFlags |= TRACE_BIT;
        MySetThreadContext( ti, &con );
        CloseHandle( proc );
        return( 0 );
    } else {
        MyGetThreadContext( ti, &con );
        con.Eip--;
        MySetThreadContext( ti, &con );
    }
#elif defined( MD_axp )
    thread_info *ti;
    CONTEXT     con;

    ti = FindThread( DebugeeTid );
    MyGetThreadContext( ti, &con );
    if( ti->brk_addr != 0 && AdjustIP( &con, 0 ) == ti->brk_addr ) {
        return( handleInt1( state ) );
    }
#elif defined( MD_ppc )
    /* nothing special to do */
#else
    #error handleInt3 not configured
#endif
    return( COND_BREAK );
}

/*
 * handleInt1 - process a trace or watch point
 */
static int handleInt1( DWORD state )
{
    if( PendingProgramInterrupt ) {
        /*
         * this was really an async stop request, so turn the t-bit
         * off in all the threads
         */
        setTBitInAllThreads( T_OFF );
        PendingProgramInterrupt = FALSE;
        return( COND_USER );
    }

#if defined( MD_x86 )
    if( state & STATE_WATCH_386 ) {
        if( GetDR6() & 0xf ) {
            return( COND_WATCH );
        }
    }
#endif
    if( state & STATE_WATCH ) {
        if( CheckWatchPoints() ) {
            return( COND_WATCH );
        }
    } else {
#if defined( MD_x86 )
        HANDLE      proc;
        DWORD       written;
        brkpnt_type ch;
        thread_info *ti;

        if( BreakFixed == 0 ) {
            return( COND_TRACE );
        }
        ti = FindThread( DebugeeTid );
        if( ti && !ti->is_foreign ) {
            return( COND_TRACE );
        }
        ch = BRK_POINT;
        proc = OpenProcess( PROCESS_ALL_ACCESS, FALSE, DebugeePid );
        WriteProcessMemory( proc, ( LPVOID ) BreakFixed, &ch, 1, &written );
        CloseHandle( proc );
        BreakFixed = 0;
        return( 0 );
#else
        return( COND_TRACE );
#endif
    }
    return( 0 );
}

#ifdef WOW
/*
 * getImageNote - get current image note structure (WOW)
 */
static void getImageNote( IMAGE_NOTE *pin )
{
    ReadMem( FlatDS, ( DWORD ) DW3( DebugEvent.u.Exception.ExceptionRecord ),
                         pin, sizeof( IMAGE_NOTE ) );
}
#endif

/*
 * DebugExecute - execute program under debug control
 */
int DebugExecute( DWORD state, int *tsc, bool stop_on_module_load )
{
    DWORD       continue_how;
    DWORD       code;
    DWORD       len;
    msg_list    **owner;
    msg_list    *new;
    int         cond;
    char        *p;
    char        *q;
    bool        rc;
#ifdef WOW
    thread_info *ti;
    DWORD       subcode;
    IMAGE_NOTE  imgnote;
#endif
    int         returnCode;

    if( tsc != NULL ) {
        *tsc = FALSE;
    }
    /*
     * "Slaying" gets set by AccKillProg.  Because a dead WOW app
     * will set the DebugeeEnded flag, and we still need to kill WOW,
     * we ignore the DebugeeEnded setting if we are doing a kill
     */
    if( !Slaying ) {
        if( DebugeeEnded || DebugeePid == NULL ) {
            returnCode = COND_TERMINATE;
            goto done;
        }
    }

    continue_how = DBG_CONTINUE;

    for( ;; ) {
        PendingProgramInterrupt = FALSE;
        if( ( state & STATE_WATCH ) && !( state & STATE_WATCH_386 ) ) {
            setTBit( T_OFF ); /* turn off previous T-bit */
#if defined( MD_axp )
            /*
               We're doing watch points on an Alpha. If we run into a
               control transfer instruction, return a spurious watchpoint
               indication. The debugger will simulate the instruction for
               us. This keeps the trap file from having to figure out
               if a conditional branch is going to happen or not.
            */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -