dbgtrace.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 724 行 · 第 1/2 页

C
724
字号
/****************************************************************************
*
*                            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:  User program step and trace support.
*
****************************************************************************/


#include "dbgdefn.h"
#include "dbgtoken.h"
#include "dbgreg.h"
#include "dbgerr.h"
#include "dbgtoggl.h"
#include "dbginfo.h"
#include "dbgbreak.h"
#include "dbglit.h"
#include "dbginp.h"
#include "dbgrep.h"
#include "dbgmem.h"
#include "trpcore.h"
#include "mad.h"


enum {
    TS_NONE,
    TS_ACTIVE,
    TS_POSTPONED,
    TS_REACTIVATED
};

#pragma pack( push, 8 ) /* make sure everything's aligned for speed */
typedef struct {
     address            brkpt;          /* address of DbgTmpBrk */
     address            watch_stack;    /* stack pointer at call */
     brk_status         userstat;       /* initial state of UserTmpBrk */
     debug_level        req_level;      /* trace level requested */
     debug_level        cur_level;      /* trace level we are in */
     address            oldaddr;        /* address where this trace started */
     int                type;           /* trace type */
     address            savecode;       /* old Code{Loc/Dot} */
     address            saveaddr;       /* original CS:IP */
     unsigned           state : 3;      /* is there a trace active */
     unsigned           stop_on_call : 1;/* we've returned -- stop on call */
     unsigned           stop_now : 1;   /* did we execute a call since ^ set ?*/
     unsigned           trace_out : 1;  /* want to trace out of a call */
     unsigned           doing_call : 1;  /* are we doing a call instruction? */
     unsigned           in_thunk : 1;   /* inside a THUNK routine */
     unsigned           in_dll_thunk : 1;       /* inside a DLL THUNK routine */
     unsigned           give_it_up : 1; /* inside a DLL THUNK routine */
     unsigned           unwinding : 1;  /* unwinding from a recursive breakpoint ? */
     dtid_t             etid;           /* thread id that we're tracing */
     address            curraddr;       /* current address being traced */
     mad_disasm_control prev_control;   /* control information for prev ins */
     mad_disasm_control curr_control;   /* control information for curr ins */
     mad_trace_how      how;            /* how to trace this instruction */
     unsigned           ddsize;         /* size of a mad_disasm_data */
     unsigned           tdsize;         /* size of a mad_trace_data */
     mad_disasm_data    *dd;            /* disasm info for curr instr */
     mad_trace_data     *td;            /* trace info for curr instr */
} trace_state;
#pragma pack( pop )

#define         KEEPGOING       0
#define         STOP            1
#define         PROCCMD         2

static trace_state      TraceState;

extern brk              UserTmpBrk;
extern brk              DbgTmpBrk;
extern debug_level      DbgLevel;
extern debug_level      ActiveWindowLevel;
extern machine_state    *DbgRegs;
extern tokens           CurrToken;
extern char             Opcode;
extern char             SecondByte;
extern char             *TxtBuff;
extern unsigned         OvlSize;
extern system_config    SysConfig;
extern address          NilAddr;


extern void             FDoneSource( void * );
extern void             *OpenSrcFile( cue_handle *ch );
extern cue_file_id      CueFileId( cue_handle * );
extern unsigned         CueFile( cue_handle *ch, char *file, unsigned max );
extern unsigned long    CueLine( cue_handle *ch );
extern void             OptMemAddr( memory_expr, address * );
extern int_16           GetDataWord( void );
extern long             GetDataLong( void );
extern void             Scan( void );
extern unsigned int     ScanCmd( char * );
extern void             ReqEOC( void );
extern int              AddrComp( address, address );
extern unsigned         Execute( bool, bool );
extern void             GetCurrOpcode( void );
extern void             Warn( char * );
extern char             *GetCmdEntry( char *, int, char * );
extern char             *GetCmdName( int );
extern void             ConfigLine( char * );
extern bool             SimIntr( char, unsigned int );
extern void             WndPmtNormal( void );
extern address          GetRegIP( void );
extern void             SetRegIP( address );
extern address          GetRegSP( void );
extern bool             RemoteOvlTransAddr( address * );
extern bool             TransOvlRetAddr( address *, unsigned int );
extern void             PushInpStack( void *, bool (*)(), bool );
extern char             *ReScan( char * );
extern void             TypeInpStack( input_type );
extern void             SetCodeLoc( address );
extern void             SetCodeDot( address );
extern address          GetCodeDot( void );
extern void             AddrFloat( address * );
extern void             AddrFix( address * );
extern void             AddrSection( address *, unsigned );
extern bool             IsSupportRoutine( sym_handle * );
extern char             *Format( char *buff, char *fmt, ... );
extern void             RecordEvent( char *p );
extern void             CheckEventRecorded( void );
extern dtid_t           RemoteSetThread( dtid_t );
extern void             ReadDbgRegs( void );
extern void             WriteDbgRegs( void );
extern void             ReportMADFailure( mad_status );

static char LevelTab[] = {
    #define pick( a,b ) b
    #include "dbglevel.h"
};

static char TraceTab2[] = {
    #define pick( a,b ) b
    #include "dbgtrace.h"
};


void            ResizeTraceData( void )
{
    void        *new;
    unsigned    size;

    size = MADDisasmDataSize();
    if( size > TraceState.ddsize ) {
        new = TraceState.dd;
        _Realloc( new, size );
        if( new == NULL ) {
            ReportMADFailure( MS_NO_MEM );
        } else {
            TraceState.dd = new;
            TraceState.ddsize = size;
        }
    }
    size = MADTraceSize();
    if( size > TraceState.tdsize ) {
        new = TraceState.td;
        _Realloc( new, size );
        if( new == NULL ) {
            ReportMADFailure( MS_NO_MEM );
        } else {
            TraceState.td = new;
            TraceState.tdsize = size;
        }
    }
}

static void TraceGetData( void )
{
    address     addr;

    addr = GetRegIP();
    if( AddrComp( TraceState.curraddr, addr ) != 0 ) {
        TraceState.curraddr = addr;
        MADDisasm( TraceState.dd, &addr, 0 );
        TraceState.prev_control = TraceState.curr_control;
        TraceState.curr_control = MADDisasmControl( TraceState.dd, &DbgRegs->mr );
    }
}

bool TraceStart( bool tracing )
{
    MADTraceInit( TraceState.td, &DbgRegs->mr );
    return( tracing );
}

mad_trace_how TraceHow( bool force_into )
{
    static const mad_trace_kind MTRKind[] = { MTRK_INTO, MTRK_OVER, MTRK_NEXT };
    mad_trace_kind      kind;
    mad_trace_how       how;

    TraceGetData();
    switch( TraceState.curr_control & MDC_TYPE_MASK ) {
    case MDC_CALL:
    case MDC_SYSCALL:
        TraceState.doing_call = TRUE;
        break;
    default:
        TraceState.doing_call = FALSE;
        break;
    }
    if( TraceState.give_it_up ) {
        DbgTmpBrk.status.b.active = FALSE;
        TraceState.give_it_up = FALSE;
        how = MTRH_BREAK;
        return( how );
    } else if( force_into ) {
        kind = MTRK_INTO;
    } else if( TraceState.trace_out ) {
        TraceState.trace_out = FALSE;
        TraceState.in_dll_thunk = FALSE;
        kind = MTRK_OUT;
    } else {
        kind = MTRKind[ TraceState.type ];
    }
    if( !force_into && DbgTmpBrk.status.b.active ) {
        how = MTRH_BREAK;
        _SwitchOn( SW_EXECUTE_LONG );
    } else {
        how = MADTraceOne( TraceState.td, TraceState.dd, kind,
                                    &DbgRegs->mr, &DbgTmpBrk.loc.addr );
    }
    switch( how ) {
    case MTRH_BREAK:
    case MTRH_STEPBREAK:
        DbgTmpBrk.status.b.active = TRUE;
    }
    if( DbgTmpBrk.status.b.active ) {
        /* for recursion detection */
        if( !TraceState.unwinding ) TraceState.watch_stack = GetRegSP();
    }
    TraceState.how = how;
    return( how );
}

bool TraceSimulate( void )
{
    mad_status  ms;

    ReadDbgRegs();      /* only SP & IP are valid on entry */
    ms = MADTraceSimulate( TraceState.td, TraceState.dd,
        &DbgRegs->mr, &DbgRegs->mr );
    if( ms != MS_OK ) return( FALSE );
    WriteDbgRegs();
    return( TRUE );
}

bool TraceModifications( MAD_MEMREF_WALKER *wk, void *d )
{
    switch( TraceState.how ) {
    case MTRH_SIMULATE:
    case MTRH_STEP:
    case MTRH_STEPBREAK:
        if( MADDisasmInsUndoable( TraceState.dd ) != MS_OK ) return( FALSE );
        if( MADDisasmMemRefWalk( TraceState.dd, wk, &DbgRegs->mr, d ) == WR_CONTINUE ) {
            return( TRUE );
        }
        break;
    }
    return( FALSE );
}

void TraceStop( bool tracing )
{
    MADTraceFini( TraceState.td );
}

void TraceKill( void )
{
    TraceState.state = TS_NONE;
}

static void TracePostponed( void )
{
    switch( TraceState.state ) {
    case TS_ACTIVE:
    case TS_REACTIVATED:
        TraceState.state = TS_POSTPONED;
        TraceState.brkpt = DbgTmpBrk.loc.addr;
    }
}

bool SourceStep( void )
{
    return( TraceState.cur_level == SOURCE );
}

/*
 * CheckTraceSourceStop - see if we want this trap because it ends a
 *                      a source level trace command
 */


static bool CheckTraceSourceStop( bool *have_source )
{
    DIPHDL( cue, line );
    DIPHDL( cue, oldline );
    DIPHDL( sym, sym );
    address                     line_addr;
    search_result               sr;
    sym_info                    info;
    void                        *viewhndl;

    *have_source = FALSE;
    TraceState.in_thunk = FALSE;
    sr = DeAliasAddrSym( NO_MOD, TraceState.curraddr, sym );
    if( sr != SR_NONE
     && SymInfo( sym, NULL, &info ) == DS_OK
     && info.kind == SK_PROCEDURE
     && info.compiler ) {
        /* in a thunk */
        TraceState.in_thunk = TRUE;
        return( FALSE );
    }
    viewhndl = NULL;
    *have_source = DeAliasAddrCue( NO_MOD, TraceState.curraddr, line ) != SR_NONE;
    if( *have_source && _IsOn( SW_CHECK_SOURCE_EXISTS ) &&
        ( viewhndl = OpenSrcFile( line ) ) != NULL ) {
        if( viewhndl != NULL ) FDoneSource( viewhndl );
        line_addr = CueAddr( line );
        if( AddrComp( TraceState.oldaddr, line_addr ) != 0 ) {
            if( DeAliasAddrCue( NO_MOD, TraceState.oldaddr, oldline ) != SR_NONE
                && CueLine( line ) == CueLine( oldline )
                && CueColumn( line ) == CueColumn( oldline )
                && CueFileId( line ) == CueFileId( oldline )
                && CueMod( line ) == CueMod( oldline ) ) {
                /*
                    We've moved to a different starting address for the
                    cue, but all the source information is the same, so
                    update the current cue start address and keep on going.
                    (This can happen with C++ switch statements since
                    there's a jump in the middle of the switch code.)
                */
                TraceState.oldaddr = line_addr;
                return( FALSE );
            }
            switch( TraceState.curr_control & MDC_TYPE_MASK ) {
            case MDC_RET:
            case MDC_SYSRET:
                break;

⌨️ 快捷键说明

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