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, ®_loc );
LocationAppend( ll, ®_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 + -
显示快捷键?