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