dbgreg.c

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

C
1,064
字号
    if( StackPos != 0 ) {
        if( _IsOff( SW_IN_REPLAY_MODE ) ) {
            if( !DlgUpTheStack() ) return( FALSE );
        }
        SetRegIP( Context.execution );
        SetRegSP( Context.stack );
        SetRegBP( Context.frame );
        StackPos = 0;
    }
    return( TRUE );
}


bool AdvMachState( int action )
{
    save_state          *new;
    bool                warn;

    warn = FALSE;
    new = StateCurr;
    while( new != StateLast ) {
        new = new->next;
        if( new->lost_mem_state ) warn = TRUE;
    }
    if( StateCurr != StateLast && _IsOff( SW_IN_REPLAY_MODE ) ) {
        if( !DlgBackInTime( warn ) ) return( FALSE );
    }
    new = StateCurr;
    while( new != StateLast ) {
        new = new->next;
        new->valid = FALSE;
    }
    PrevRegs = DbgRegs;
    StateCurr->valid = TRUE;
    if( SysConfig.mad != MAD_MSJ ) {
        if( !StateCurr->next->valid ) {
            StateCurr = StateCurr->next;
        } else {
            new = AllocState();
            new->action = action;
            if( new == NULL ) {
                StateCurr = StateCurr->next;
            } else {
                new->prev = StateCurr;
                new->next = StateCurr->next;
                new->next->prev = new;
                StateCurr->next = new;
                StateCurr = new;
            }
        }
    }
    StateCurr->valid = TRUE;
    DbgRegs = &StateCurr->s;
    StateLast = StateCurr;

    FreeMemDelta( StateCurr );
    CopyMachState( PrevRegs, DbgRegs );
    AlreadyWarnedUndo = FALSE;
    return( TRUE );
}


unsigned ChangeMem( address addr, void * to, unsigned size )
{
    memory_delta        *curr;
    unsigned_8          *p;
    unsigned            amount;
    unsigned            left;

    p = to;
    left = size;
    for( ;; ) {
        if( left == 0 ) break;
        amount = left;
        if( amount > MAX_DELTA_BYTES ) amount = MAX_DELTA_BYTES;
        curr = NewMemDelta( addr, amount );
        if( curr == NULL ) {
            StateCurr->lost_mem_state = TRUE;
        } else {
            if( ProgPeek( addr, &curr->data[0], amount ) != amount ) {
                StateCurr->lost_mem_state = TRUE;
            }
            curr->after_set = TRUE;
            memcpy( &curr->data[amount], p, amount );
        }
        addr.mach.offset += amount;
        p += amount;
        left -= amount;
    }
    addr.mach.offset -= size;
    return( ProgPoke( addr, to, size ) );
}

static void ReverseMemList( save_state * state )
{
    memory_delta        *curr;
    memory_delta        *next;
    memory_delta        *reverse;

    curr = state->mem;
    reverse = NULL;
    while( curr != NULL ) {
         next = curr->next;
         curr->next = reverse;
         reverse = curr;
         curr = next;
    }
    state->mem = reverse;
}


unsigned UndoLevel( void )
{
    int         count;
    save_state  *state;

    count = 0;
    for( state = StateCurr; state != StateLast; state = state->next ) {
        ++count;
    }
    return( count );
}

static unsigned RedoLevel( void )
{
    int         count;
    save_state  *state;

    count = 0;
    state = StateCurr;
    for( ;; ) {
        state = state->prev;
        if( state == StateLast ) break;
        if( !state->valid ) break;
        ++count;
    }
    return( count );
}


#ifdef DEADCODE
bool MachStateInfoRelease( void )
{
    save_state  *state, *next;
    bool        freed;

    state = StateCurr;
    freed = FALSE;
    do {
        next = state->next;
        if( !state->valid ) {
            FreeState( state );
            freed = TRUE;
        }
        state = next;
    } while( state != StateCurr );
    if( !freed ) {
        if( StateLast->next != StateCurr ) {;
            FreeState( StateLast->next );
            freed = TRUE;
        }
    }
    if( PrevRegs == NULL ) PrevRegs = &StateCurr->s;
    if(  DbgRegs == NULL )  DbgRegs = &StateCurr->s;
    return( freed );
}
#endif


typedef struct {
    location_context    lc;
    int                 targ;
    int                 curr;
    bool                success;
} move_info;

static CALL_CHAIN_RTN CheckOneLevel;

void SetStackPos( location_context *lc, int pos )
{
    StackPos = pos;
    Context.execution = lc->execution;
    Context.stack = lc->stack;
    Context.frame = lc->frame;
    Context.up_stack_level = lc->up_stack_level;
    Context.maybe_have_frame = lc->maybe_have_frame;
    Context.have_frame = lc->have_frame;
    SetCodeLoc( GetRegIP() );
    DbgUpdate( UP_STACKPOS_CHANGE );
}

void MoveStackPos( int by )
{
    move_info   info;

    if( StackPos + by > 0 ) {
        Warn( LIT( Bottom_Of_Stack ) );
        return;
    }
    info.targ = StackPos + by;
    info.curr = 0;
    info.success = FALSE;
    WalkCallChain( CheckOneLevel, &info );
    if( info.success ) {
        SetStackPos( &info.lc, info.targ );
    } else {
        Warn( LIT( Top_Of_Stack ) );
    }
}


void PosMachState( int rel_pos )
{
    save_state          *new;
    int                 adv,bkup;
    int                 i;
    save_state          *curr;
    memory_delta        *mem;
    int                 stack_pos;
    bool                lost_mem_state;

    new = StateCurr;
    if( rel_pos == 0 ) return;
    if( rel_pos > 0 ) {
        adv = UndoLevel();
        if( rel_pos > adv ) {
            Warn( LIT( No_More_Undos ) );
            rel_pos = adv;
        }
        for( i = rel_pos; i > 0; --i ) {
            new = new->next;
        }
    } else {
        bkup = RedoLevel();
        if( -rel_pos > bkup ) {
            Warn( LIT( No_More_Undos ) );
            rel_pos = -bkup;
        }
        for( i = rel_pos; i < 0; ++i ) {
            new = new->prev;
        }
    }
    if( new->s.tid != DbgRegs->tid ) {
        if( FindThread( new->s.tid ) == NULL ) {
            Warn( LIT( Thread_Not_Exist ) );
            rel_pos = 0;
        } else {
            RemoteSetThread( new->s.tid );
        }
    }
    if( rel_pos == 0 ) return;
    stack_pos = GetStackPos();
    MoveStackPos( -stack_pos );
    if( rel_pos > 0 ) {
        curr = StateCurr;
        do {
            curr = curr->next;
            ReverseMemList( curr );
            for( mem = curr->mem; mem != NULL; mem = mem->next ) {
                ProgPoke( mem->addr, &mem->data[mem->size], mem->size );
            }
            ReverseMemList( curr );
        } while( curr != new );
    } else {
        lost_mem_state = FALSE;
        for( curr = StateCurr; curr != new; curr = curr->prev ) {
            if( curr->lost_mem_state ) {
                lost_mem_state = TRUE;
            }
        }
        curr = StateCurr;
        if( lost_mem_state ) {
            if( AlreadyWarnedUndo ) {
                lost_mem_state = FALSE;
            } else if( DlgIncompleteUndo() ) {
                lost_mem_state = FALSE;
                AlreadyWarnedUndo = TRUE;
            }
        }
        if( !lost_mem_state ) {
            do {
                for( mem = curr->mem; mem != NULL; mem = mem->next ) {
                    ProgPoke( mem->addr, &mem->data[0], mem->size );
                }
                curr = curr->prev;
            } while( curr != new );
        }
    }
    StateCurr = curr;
    PrevRegs = DbgRegs;
    DbgRegs = &StateCurr->s;
    InitLC( &Context, TRUE );
    SetCodeLoc( GetRegIP() );
    DbgUpdate(UP_MEM_CHANGE | UP_CSIP_JUMPED | UP_CSIP_CHANGE | UP_REG_CHANGE | UP_THREAD_STATE);
    MoveStackPos( stack_pos );
    if( StateCurr == StateLast ) {
        AlreadyWarnedUndo = FALSE;
    }
}

void LastMachState( void )
{
    PosMachState( UndoLevel() );
}

static bool CheckOneLevel( call_chain_entry *entry, void *_info )
{
    move_info  *info = _info;

    if( info->curr == info->targ ) {
        info->success = TRUE;
        info->lc = entry->lc;
        return( FALSE );
    } else {
        info->curr--;
        return( TRUE );
    }
}


void LastStackPos( void )
{
    if( StackPos != 0 ) {
        MoveStackPos( -StackPos );
    }
}


int GetStackPos( void )
{
    return( StackPos );
}

/************************ command language stuff ***********************/

void ProcRegister( void )
{
    int         val;
    unsigned    old;

    old = SetCurrRadix( 10 );
    val = (int) ReqExpr();
    ReqEOC();
    if( val != 0 ) {
        PosMachState( val );
    }
    SetCurrRadix( old );
}


void ProcUndo( void )
{
    int         val;
    unsigned    old;

    old = SetCurrRadix( 10 );
    val = (int) ReqExpr();
    SetCurrRadix( old );
    ReqEOC();
    if( val != 0 ) {
        PosMachState( -val );
    }
}


char *GetActionString( int action )
/*********************************/
{
    switch( action ) {
    case ACTION_EXECUTE:
        return( LIT( Str_ACTION_EXECUTE ) );
    case ACTION_ASSIGNMENT:
        return( LIT( Str_ACTION_ASSIGNMENT ) );
    case ACTION_THREAD_CHANGE:
        return( LIT( Str_ACTION_THREAD_CHANGE ) );
    case ACTION_MODIFY_IP:
        return( LIT( Str_ACTION_MODIFY_IP ) );
    case ACTION_MODIFY_MEMORY:
        return( LIT( Str_ACTION_MODIFY_MEMORY ) );
    case ACTION_MODIFY_REGISTER:
        return( LIT( Str_ACTION_MODIFY_REGISTER ) );
    case ACTION_MODIFY_VARIABLE:
        return( LIT( Str_ACTION_MODIFY_VARIABLE ) );
    case ACTION_NONE:
        return( NULL );
    default:
        return( "" );
    }
}

char *GetUndoString( void )
/*************************/
{
    if( StateCurr == NULL ) return( NULL );
    return( GetActionString( StateCurr->action ) );
}

char *GetRedoString( void )
/*************************/
{
    if( StateCurr == NULL ) return( NULL );
    if( UndoLevel() == 0 ) return( GetActionString( ACTION_NONE ) );
    return( GetActionString( StateCurr->next->action ) );
}

void ProcStackPos( void )
{
    int         val;
    unsigned    old;

    old = SetCurrRadix( 10 );
    val = (int) ReqExpr();
    SetCurrRadix( old );
    ReqEOC();
    MoveStackPos( val - StackPos );
}


void GoHome( void )
{
    LastStackPos();
    LastMachState();
    DbgUpdate( UP_CSIP_CHANGE );
}

/*
 * ParseRegSet - create a register set location list
 */

struct parsed_regs {
    struct parsed_regs  *prev;
    mad_reg_info        *ri;
};

void ParseRegSet( bool multiple, location_list *ll, type_info *ti )
{
    lookup_item         li;
    struct parsed_regs  *list, *new;
    mad_reg_info        *ri;
    location_list       reg_loc;

    li.scope.start = NULL;
    li.type = ST_NONE;
    li.case_sensitive = FALSE;
    list = NULL;
    for( ;; ) {
        li.name.start = NamePos();
        li.name.len = NameLen();
        ri = LookupRegName( NULL, &li );
        if( ri == NULL ) break;
        Scan();
        _AllocA( new, sizeof( *new ) );
        /* build the list backwards because the location list wants
           to be little endian */
        new->ri = ri;
        new->prev = list;
        list = new;
        if( !multiple ) break;
    }
    ti->size = 0;
    ll->num = 0;
    ll->flags = 0;
    while( list != NULL ) {
        ti->size += list->ri->bit_size / BITS_PER_BYTE;
        RegLocation( DbgRegs, list->ri, &reg_loc );
        LocationAppend( ll, &reg_loc );
        list = list->prev;
    }
    //MAD: hmmm.... get typing info out of list->ri->type?
    switch( ti->size ) {
    case 1:
    case 2:
    case 4:
        ti->kind = TK_INTEGER;
        ti->modifier = TM_UNSIGNED;
        break;
    case 6:
        ti->kind = TK_ADDRESS;
        ti->modifier = TM_FAR;
        break;
    case 8:
        ti->kind = TK_REAL;
        ti->modifier = TM_NONE;
        break;
    default:
        ti->kind = TK_NONE;
        ti->modifier = TM_NONE;
        break;
    }
}

void RegValue( item_mach *value, const mad_reg_info *reginfo, machine_state *mach )
{
    location_list               src_ll;
    location_list               dst_ll;
    unsigned                    size;

    size = ( reginfo->bit_size + (BITS_PER_BYTE-1) ) / BITS_PER_BYTE;
    RegLocation( mach, reginfo, &src_ll );
    LocationCreate( &dst_ll, LT_INTERNAL, value );
    LocationAssign( &dst_ll, &src_ll, size, FALSE );
}

void RegNewValue( const mad_reg_info *reginfo,
                      item_mach *new_val,
                      mad_type_handle type )
{
    char                        *p;
    location_list               dst_ll,src_ll;
    type_info                   dst_ti,src_ti;
    unsigned                    max;

    if( !AdvMachState( ACTION_MODIFY_REGISTER ) ) return;
    RegLocation( DbgRegs, reginfo, &dst_ll );
    MadTypeToDipTypeInfo( reginfo->type, &dst_ti );
    PushLocation( &dst_ll, &dst_ti );
    LocationCreate( &src_ll, LT_INTERNAL, new_val );
    MadTypeToDipTypeInfo( type, &src_ti );
    PushLocation( &src_ll, &src_ti );
    DoAssign();
    p = StrCopy( GetCmdName( CMD_ASSIGN ), TxtBuff );
    p = StrCopy( " ", p );
    p += MADRegFullName( reginfo, ".", TXT_LEN, p );
    p = StrCopy( "=", p );
    max = TXT_LEN - ( p - TxtBuff );
    MADTypeHandleToString( CurrRadix, type, new_val, &max, p );
    p += max;
    RecordEvent( TxtBuff );
    CollapseMachState();
    DbgUpdate( UP_REG_CHANGE );
}

⌨️ 快捷键说明

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