dbgreg.c

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

C
1,064
字号
/****************************************************************************
*
*                            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 registers access and management.
*
****************************************************************************/


#include <string.h>
#include <stddef.h>
#include "dbgdefn.h"
#include "dbgreg.h"
#include "dbglit.h"
#include "dbgmem.h"
#include "dbgerr.h"
#include "dbgtoggl.h"
#include "dbginfo.h"
#include "dbgtback.h"
#include "dipwv.h"
#include "dbgrep.h"
#include "dbgitem.h"
#include "mad.h"
#include "dui.h"

extern int              AddrComp( address a, address b );
extern char             *Format( char * buff, char * fmt, ... );
extern void             RecordEvent( char *p );
extern char             *GetCmdName( int index );
extern bool             DlgUpTheStack( void );
extern bool             DlgBackInTime( bool lost_mem_state );
extern bool             DlgIncompleteUndo( void );
extern bool             TraceModifications( MAD_MEMREF_WALKER *wk, void *d );
extern void             ReportMADFailure( mad_status );

extern void             LocationCreate( location_list *ll, location_type lt, void *d );
extern dip_status       LocationAssign( location_list *dst, location_list *src, unsigned long len, bool sign_extend );
extern void             PushLocation( location_list *ll, type_info *ti );
extern void             DoAssign( void );
extern char             *StrCopy( char *, char * );
extern void             MadTypeToDipTypeInfo( mad_type_handle mt, type_info *ti );

extern machine_state    *DbgRegs;
extern machine_state    *PrevRegs;
extern unsigned         OvlSize;
extern address          NilAddr;
extern char             *TxtBuff;
extern unsigned char    CurrRadix;

static int              StackPos;
static bool             AlreadyWarnedUndo;
extern system_config    SysConfig;


#define MAX_DELTA_BITS  8
#define MAX_DELTA_BYTES ((1<<MAX_DELTA_BITS)-1)

typedef struct memory_delta {
    struct memory_delta *next;
    address             addr;
    unsigned            size            : MAX_DELTA_BITS;
    unsigned            after_set       : 1;
    unsigned            _volatile       : 1;
    unsigned_8          data[1]; /* variable sized */
} memory_delta;

typedef struct save_state {
    struct save_state   *prev;
    struct save_state   *next;
    unsigned            valid           : 1;
    unsigned            lost_mem_state  : 1;
    memory_delta        *mem;
    int                 action;
    machine_state       s;      /* variable sized */
} save_state;

static  save_state      *StateCurr;
static  save_state      *StateLast;
static  int             NumStateEntries = 0;

extern long             GetDataLong( void );
extern void             StartupErr( char * );
extern unsigned         ReqExpr( void );
extern void             ReqEOC( void );
extern void             DbgUpdate( update_list );
extern unsigned         SetCurrRadix( unsigned int );
extern void             Warn( char * );
extern void             LogLine( char * );
extern void             FindAddrSectId( address *, int );
extern void             SetStateOvlSect( machine_state *, unsigned int );
extern unsigned int     RemoteOvlSectSize( void );
extern void             ReleaseProgOvlay( bool );
extern void             SectTblRead( machine_state * );
extern char             *Rtrm( char * );
extern dtid_t           RemoteSetThread( dtid_t );
extern thread_state     *FindThread( dtid_t );
extern bool             InitOvlState( void );
extern void             FiniOvlState( void );
extern unsigned         ProgPoke( address addr, void *data, unsigned len );
extern unsigned         ProgPeek( address addr, void *data, unsigned len );
extern void             SetCodeLoc( address );
extern char             *NamePos( void );
extern unsigned int     NameLen( void );
extern void             Scan( void );
extern void             AddrFix( address * );
extern void             AddrFloat( address * );
extern void             AddrSection( address *, unsigned );
extern mad_reg_info     *LookupRegName( mad_reg_info *, lookup_item * );
extern void             LocationAppend( location_list *, location_list * );
extern dip_status       RegLocation( machine_state *regs, mad_reg_info const *ri, location_list *ll );
extern void             InitLC( location_context *new, bool use_real_regs );
extern address          DefAddrSpaceForAddr( address );


void DefAddr( memory_expr def_seg, address *addr )
{
    switch( def_seg ) {
    case EXPR_CODE:
        *addr = Context.execution;
        addr->mach.offset = 0;
        break;
    case EXPR_DATA:
        *addr = DefAddrSpaceForAddr( Context.execution );
        break;
    }
}

static address AddrRegIP( machine_state *regs )
{
    address    addr;

    MADRegSpecialGet( MSR_IP, &regs->mr, &addr.mach );
    AddrSection( &addr, OVL_MAP_CURR );
    return( addr );
}


address GetRegIP( void )
{
    return( AddrRegIP( DbgRegs ) );
}


void SetRegIP( address addr )
{
    AddrFix( &addr );
    MADRegSpecialSet( MSR_IP, &DbgRegs->mr, &addr.mach );
    SetStateOvlSect( DbgRegs, addr.sect_id );
}


void RecordSetRegIP( address addr )
{
    Format( TxtBuff, "%s %A", GetCmdName( CMD_SKIP ), addr );
    RecordEvent( TxtBuff );
    SetRegIP( addr );
}


void SetRegSP( address addr )
{
    AddrFix( &addr );
    MADRegSpecialSet( MSR_SP, &DbgRegs->mr, &addr.mach );
}


void SetRegBP( address addr )
{
    AddrFix( &addr );
    MADRegSpecialSet( MSR_FP, &DbgRegs->mr, &addr.mach );
}


address GetRegSP( void )
{
    address     addr;

    MADRegSpecialGet( MSR_SP, &DbgRegs->mr, &addr.mach );
    AddrSection( &addr, OVL_MAP_CURR );
    return( addr );
}


address GetRegBP( void )
{
    address     addr;

    MADRegSpecialGet( MSR_FP, &DbgRegs->mr, &addr.mach );
    AddrSection( &addr, OVL_MAP_CURR );
    return( addr );
}


static memory_delta *NewMemDelta( address addr, unsigned bytes )
{
    memory_delta *new;

    _Alloc( new, (sizeof( *new )-1) + 2*bytes );
    if( new == NULL ) return( NULL );
    memset( new, 0, sizeof( *new ) );
    new->addr = addr;
    new->next = StateCurr->mem;
    new->size = bytes;
    StateCurr->mem = new;
    return( new );
}

static walk_result FindMemRefs( address a, mad_type_handle th,
                        mad_memref_kind mk, void *d )
{
    mad_type_info       mti;
    memory_delta        *new;
    unsigned            bytes;


    d = d;
    if( (mk & (MMK_VOLATILE|MMK_WRITE)) == 0 ) return( WR_CONTINUE );
    MADTypeInfo( th, &mti );
    bytes = mti.b.bits / BITS_PER_BYTE;
    if( bytes > MAX_DELTA_BYTES ) return( WR_STOP ); /* don't fit */
    new = NewMemDelta( a, bytes );
    if( new == NULL ) return( WR_STOP );
    if( mk & MMK_VOLATILE ) new->_volatile = TRUE;
    /* can keep in target form */
    new->size = ProgPeek( a, &new->data[0], bytes );
    return( WR_CONTINUE );
}

void SetMemBefore( bool tracing )
{
    if( !tracing ) {
        StateCurr->lost_mem_state = TRUE;
        return;
    }
    if( !TraceModifications( FindMemRefs, NULL ) ) {
        StateCurr->lost_mem_state = TRUE;
    }
}


void SetMemAfter( bool tracing )
{
    memory_delta        **owner;
    memory_delta        *curr;

    if( !tracing ) return;
    if( StateCurr->lost_mem_state ) return;
    owner = &StateCurr->mem;
    for( ;; ) {
        curr = *owner;
        if( curr == NULL ) break;
        if( curr->after_set ) break;
        if( ProgPeek( curr->addr, &curr->data[curr->size], curr->size ) != curr->size ) {
            StateCurr->lost_mem_state = TRUE;
        }
        curr->after_set = TRUE;
        if( !curr->_volatile
          && memcmp( &curr->data[0], &curr->data[curr->size], curr->size ) == 0 ) {
            /* don't need the sucker */
            *owner = curr->next;
            _Free( curr );
        } else {
            owner = &curr->next;
        }
    }
}

static void FreeMemDelta( save_state *state )
{
    memory_delta        *mem;
    memory_delta        *junk;

    mem = state->mem;
    while( mem != NULL ) {
        junk = mem;
        mem = mem->next;
        _Free( junk );
    }
    state->mem = NULL;
}

static void FreeState( save_state *state )
{
    state->prev->next = state->next;
    state->next->prev = state->prev;
    _Free( state->s.ovl );
    FreeMemDelta( state );
    _Free( state );
    if( DbgRegs == &state->s ) DbgRegs = NULL;
    if( PrevRegs == &state->s ) PrevRegs = NULL;
    --NumStateEntries;
}

unsigned        CurrRegSize = 0;

void ResizeRegData( void )
{
    unsigned            new_size;
    bool                found_dbgregs;
    save_state          *state;
    save_state          *old;
    machine_state       *ms;

    new_size = MADRegistersSize();
    if( new_size > CurrRegSize ) {
        /* should I zero out new memory? */
        /* Yes, it is neccessary for debug version */
        found_dbgregs = FALSE;
        state = StateCurr;
        for( ;; ) {
            old = state;
            _Alloc( state, sizeof( save_state ) + new_size );
            if( state == NULL ) {
                ReportMADFailure( MS_NO_MEM );
                new_size = CurrRegSize;
            } else {
                memset( state, 0, sizeof( save_state ) + new_size );
                memcpy( state, old, sizeof( save_state ) );
            }
            if( old == StateCurr ) StateCurr = state;
            if( old == StateLast ) StateLast = state;
            state->prev->next = state;
            state->next->prev = state;
            if( &old->s == DbgRegs ) {
                found_dbgregs = TRUE;
                DbgRegs = &state->s;
            }
            if( &old->s == PrevRegs ) PrevRegs = &state->s;
            state = state->next;
            if( state == StateCurr ) break;
        }
        if( !found_dbgregs ) {
            /* just a machine state on it's own */
            ms = DbgRegs;
            _Alloc( ms, sizeof( machine_state ) + new_size );
            if( ms == NULL ) {
                ReportMADFailure( MS_NO_MEM );
                new_size = CurrRegSize;
            } else {
                memset( ms, 0, sizeof( machine_state ) + new_size );
                memcpy( ms, DbgRegs, sizeof( machine_state ) );
                if( DbgRegs == PrevRegs ) PrevRegs = ms;
                DbgRegs = ms;
            }
        }
        CurrRegSize = new_size;
    }
}

static save_state *AllocState( void )
{
    int         size;
    save_state  *state;

    size = sizeof( *state ) + CurrRegSize;
    _Alloc( state, size );
    if( state == NULL ) return( NULL );
    memset( state, 0, size );
    if( OvlSize != 0 ) {
        _Alloc( state->s.ovl, OvlSize );
        if( state->s.ovl == NULL ) {
            _Free( state );
            return( NULL );
        }
    }
    ++NumStateEntries;
    return( state );
}


void ClearMachState( void )
{
    save_state  *state, *next;

    state = StateCurr->next->next;
    while( state != StateCurr ) {
        next = state->next;
        FreeState( state );
        state = next;
    }
    OvlSize = 0;
    state = StateCurr;
    do {
        _Free( state->s.ovl );
        state->s.ovl = NULL;
        state->s.tid = 1;
        state->s.mad = MAD_NIL;
        FreeMemDelta( state );
        state = state->next;
    } while( state != StateCurr );
    PrevRegs = DbgRegs = &StateCurr->s;
    StateLast = StateCurr;
    AlreadyWarnedUndo = FALSE;
}


void InitMachState( void )
{
    save_state  *other;

    StateCurr = AllocState();
    StateCurr->action = ACTION_NONE;
    other = AllocState();
    other->action = ACTION_NONE;
    if( StateCurr == NULL || other == NULL ) {
        StartupErr( LIT( ERR_NO_MEMORY ) );
    }
    other->next = StateCurr;
    other->prev = StateCurr;
    StateCurr->next = other;
    StateCurr->prev = other;

    ClearMachState();
}


void FiniMachState( void )
{
    FiniOvlState();
    ClearMachState();
    FreeState( StateCurr->next );
    FreeState( StateCurr );
    StateCurr = NULL;
    StateLast = NULL;
}


void SetupMachState( void )
{
    save_state      *state;

    OvlSize = RemoteOvlSectSize();
    if( OvlSize == 0 ) return;
    state = StateCurr;
    do {
        _Free( state->s.ovl );
        _Alloc( state->s.ovl, OvlSize );
        if( state->s.ovl == NULL ) {
            ReleaseProgOvlay( FALSE );
            Error( ERR_NONE, LIT( ERR_NO_OVL_STATE ) );
        }
        state = state->next;
    } while( state != StateCurr );
    if( !InitOvlState() ) {
        ReleaseProgOvlay( FALSE );
        Error( ERR_NONE, LIT( ERR_NO_OVL_STATE ) );
    }
    SectTblRead( DbgRegs );
}

void CopyMachState( machine_state *from, machine_state *to )
{
    to->tid = from->tid;
    to->mad = from->mad;
    memcpy( &to->mr, &from->mr, CurrRegSize );
    if( to->ovl != NULL ) memcpy( to->ovl, from->ovl, OvlSize );
}

machine_state *AllocMachState( void )
{
    machine_state   *state;
    unsigned        state_size;

    state_size = sizeof( machine_state ) + CurrRegSize;
    state = DbgMustAlloc( state_size );
    memset( state, 0, sizeof( *state ) );
    if( OvlSize != 0 ) {
        _Alloc( state->ovl, OvlSize );
        if( state->ovl == NULL ) {
            _Free( state );
            state = NULL;
            Error( ERR_NONE, LIT( ERR_NO_MEMORY ) );
        }
    }
    return( state );
}

void FreeMachState( machine_state *state )
{
    _Free( state->ovl );
    _Free( state );
}


void CollapseMachState( void )
{
    machine_state       *curr, *prev;

    if( StateCurr == NULL ) return;
    if( !StateCurr->valid ) return;
    if( StateCurr->mem != NULL ) return;
    if( StateCurr->prev == NULL ) return;
    if( StateCurr->prev->mem != NULL ) return;
    if( StateCurr->s.mad != StateCurr->prev->s.mad ) return;
    curr = &StateCurr->s;
    if( !StateCurr->prev->valid ) return;
    prev = &StateCurr->prev->s;
    if( prev->tid != curr->tid ) return;
    if( memcmp( &prev->mr, &curr->mr, CurrRegSize ) != 0 ) return;
    StateCurr->valid = FALSE;
    StateCurr = StateCurr->prev;
    StateLast = StateCurr;
    PrevRegs = DbgRegs = &StateCurr->s;
    if( StateCurr->prev->valid ) {
        PrevRegs = &StateCurr->prev->s;
    }
}

bool CheckStackPos( void )
{

⌨️ 快捷键说明

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