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, ®s->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 + -
显示快捷键?