📄 os2v2acc.c
字号:
dst = src = WatchPoints;
for( i = 0; i < WatchCount; ++i ) {
if( src->addr.segment != acc->watch_addr.segment ||
src->addr.offset != acc->watch_addr.offset ) {
*dst = *src;
++dst;
} else {
DebugExecute( &Buff, DBG_C_Stop, FALSE );
Buff.Cmd = DBG_C_ClearWatch;
Buff.Index = 0; // src->id;
CallDosDebug( &Buff );
}
++src;
}
DebugRegsNeeded -= (acc->watch_addr.offset & (acc->size - 1)) ? 2 : 1;
--WatchCount;
return( 0 );
}
static volatile bool BrkPending;
void SetBrkPending( void )
{
BrkPending = TRUE;
}
static unsigned MapReturn( unsigned conditions )
{
if( BrkPending ) {
/* Get CS:EIP & SS:ESP correct */
ReadRegs( &Buff );
return( conditions | COND_USER );
}
Out( "Map Return - " );
OutNum( Buff.Cmd );
Out( "\r\n" );
switch( Buff.Cmd ) {
case DBG_N_Success:
return( conditions );
case DBG_N_AsyncStop:
return( conditions | COND_USER );
// case DBG_N_Signal:
// return( TRAP_USER );
case DBG_N_SStep:
return( conditions | COND_TRACE );
case DBG_N_Breakpoint:
return( conditions | COND_BREAK );
case DBG_N_Exception:
switch( ExceptNum ) {
case XCPT_PROCESS_TERMINATE:
case XCPT_ASYNC_PROCESS_TERMINATE:
return( conditions | COND_TERMINATE );
default:
return( conditions | COND_EXCEPTION );
}
case DBG_N_Watchpoint:
return( conditions | COND_WATCH );
case DBG_N_ModuleLoad:
return( conditions | COND_LIBRARIES );
case DBG_N_ThreadTerm:
return( conditions );
case DBG_N_Error: // must terminate application - system semaphore locked
Buff.Cmd = DBG_C_Term;
Buff.Pid = Pid;
CallDosDebug( &Buff );
default:
AtEnd = TRUE;
CanExecTask = FALSE;
return( conditions | COND_TERMINATE );
}
}
static bool setDebugRegs(void)
{
int needed;
int i;
needed = 0;
for( i = 0; i < WatchCount; ++i ) {
needed += WatchPoints[i].addr.offset & (WatchPoints[i].len - 1) ? 2 : 1;
if( needed > 4 ) {
return( FALSE );
}
}
for( i = 0; i < WatchCount; ++i ) {
Buff.Cmd = DBG_C_SetWatch;
Buff.Addr = MakeItFlatNumberOne( WatchPoints[i].addr.segment,
WatchPoints[i].addr.offset & ~(WatchPoints[i].len - 1) );
Buff.Len = WatchPoints[i].len;
Buff.Index = 0;
Buff.Value = DBG_W_Write | DBG_W_Local;
CallDosDebug( &Buff );
if( WatchPoints[i].addr.offset & (WatchPoints[i].len - 1) ) {
Buff.Cmd = DBG_C_SetWatch;
Buff.Addr += WatchPoints[i].len;
Buff.Index = 0;
CallDosDebug( &Buff );
}
}
return( TRUE );
}
static void watchSingleStep(void)
{
uDB_t save;
dword memval;
int i;
DebugExecute( &Buff, DBG_C_SStep, TRUE );
while( Buff.Cmd == DBG_N_SStep ) {
for (i = 0; i < WatchCount; ++i) {
ReadRegs( &save );
ReadBuffer( (char *)&memval, WatchPoints[i].addr.segment,
WatchPoints[i].addr.offset, sizeof( memval ) );
WriteRegs(&save);
if( WatchPoints[i].value != memval ) {
Buff.Cmd = DBG_N_Watchpoint;
return;
}
}
DebugExecute( &Buff, DBG_C_SStep, TRUE );
}
}
/* This break handler ensures that upon hitting Ctrl-C or Ctrl-Break when
the debugger has focus, the debuggee will be actually interrupted instead
of killing the debugger. We do NOT handle XCPT_SIGNAL_KILLPROC, hence
the debugger can still be killed by another app (a Good Thing).
Note: Ctrl-C doesn't seem to be sending signals for some reason, but
Ctrl-Break is working so it doesn't really matter.
*/
ULONG _System BreakHandler( PEXCEPTIONREPORTRECORD pExRec,
PEXCEPTIONREGISTRATIONRECORD pRegRec,
PCONTEXTRECORD pCtxRec,
PVOID args )
{
switch( pExRec->ExceptionNum ) {
case XCPT_SIGNAL: {
switch( pExRec->ExceptionInfo[0] ) {
case XCPT_SIGNAL_INTR:
case XCPT_SIGNAL_BREAK:
SetBrkPending();
return( XCPT_CONTINUE_EXECUTION );
}
}
}
/* Pass everything else further down */
return( XCPT_CONTINUE_SEARCH );
}
static unsigned progRun( bool step )
{
prog_go_ret *ret;
ULONG ulTimes;
EXCEPTIONREGISTRATIONRECORD RegRec = {0}; // must be on stack!
RegRec.ExceptionHandler = BreakHandler;
ret = GetOutPtr( 0 );
if( NumModHandles > CurrModHandle ) {
ret->conditions = COND_LIBRARIES;
ret->stack_pointer.segment = lastSS;
ret->stack_pointer.offset = lastESP;
ret->program_counter.segment = lastCS;
ret->program_counter.offset = lastEIP;
return( sizeof( *ret ) );
}
BrkPending = FALSE;
// Set exception handler and don't forget to set signal focus!
DosSetExceptionHandler( &RegRec );
DosSetSignalExceptionFocus( SIG_SETFOCUS, &ulTimes );
if( AtEnd ) {
Buff.Cmd = DBG_N_ProcTerm;
} else if( step ) {
DebugExecute( &Buff, DBG_C_SStep, TRUE );
} else if( !setDebugRegs() ) {
watchSingleStep();
} else {
DebugExecute( &Buff, DBG_C_Go, TRUE );
if( Buff.Cmd == DBG_N_Success ) {
Buff.Cmd = DBG_N_ProcTerm;
}
}
DosSetSignalExceptionFocus( SIG_UNSETFOCUS, &ulTimes );
DosUnsetExceptionHandler( &RegRec );
ret->conditions = ( COND_CONFIG | COND_THREAD );
if( NumModHandles > CurrModHandle ) {
ret->conditions |= COND_LIBRARIES;
}
ret->conditions = MapReturn( ret->conditions );
lastSS = ret->stack_pointer.segment = Buff.SS;
lastESP = ret->stack_pointer.offset = Buff.ESP;
lastCS = ret->program_counter.segment = Buff.CS;
lastEIP = ret->program_counter.offset = Buff.EIP;
//runret->thread = Buff.Tid;
//if( runret->returnvalue == TRAP_TERMINATE ) {
// AtEnd = TRUE;
// CanExecTask = FALSE;
//}
return( sizeof( *ret ) );
}
unsigned ReqProg_go( void )
{
unsigned rc;
PMUnLock();
rc = progRun( FALSE );
PMLock( Buff.Pid, Buff.Tid );
return( rc );
}
unsigned ReqProg_step( void )
{
unsigned rc;
PMUnLock();
rc = progRun( TRUE );
PMLock( Buff.Pid, Buff.Tid );
return( rc );
}
unsigned ReqFile_write_console( void )
{
ULONG len;
ULONG written_len;
char *ptr;
file_write_console_ret *ret;
ptr = GetInPtr( sizeof( file_write_console_req ) );
len = GetTotalSize() - sizeof( file_write_console_req );
ret = GetOutPtr( 0 );
if( CanExecTask ) {
/* print/program request */
ret->len = len;
ret->err = 0;
TaskPrint( ptr, len );
} else {
ret->err = DosWrite( 2, ptr, len, &written_len );
ret->len = written_len;
}
return( sizeof( *ret ) );
}
struct thd_state {
unsigned char dbg_state;
unsigned char thread_state;
unsigned short priority;
};
static int ValidThread( TID thread )
{
struct thd_state state; /* TStat_t with IBM headers */
TID save;
if( thread == 0 )
return( 0 );
save = Buff.Tid;
Buff.Tid = thread;
Buff.Cmd = DBG_C_ThrdStat;
Buff.Buffer = (ULONG)&state;
Buff.Len = 4;
CallDosDebug( &Buff );
Buff.Tid = save;
return( Buff.Cmd == DBG_N_Success );
}
unsigned ReqThread_get_next( void )
{
thread_get_next_req *acc;
thread_get_next_ret *ret;
TID thread;
acc = GetInPtr( 0 );
ret = GetOutPtr( 0 );
if( Pid != 0 ) {
thread = acc->thread;
while( ++thread <= 256 ) {
if( ValidThread( thread ) ) {
ret->thread = thread;
//NYI:Assume all threads can be run
ret->state = THREAD_THAWED;
return( sizeof( *ret ) );
}
}
}
ret->thread = (acc->thread == 0) ? 1 : 0;
return( sizeof( *ret ) );
}
unsigned ReqThread_set( void )
{
thread_set_req *acc;
thread_set_ret *ret;
acc = GetInPtr( 0 );
ret = GetOutPtr( 0 );
ret->err = 0;
ret->old_thread = Buff.Tid;
if( ValidThread( acc->thread ) ) {
Buff.Pid = Pid;
Buff.Tid = acc->thread;
Buff.Cmd = DBG_C_ReadReg;
CallDosDebug( &Buff );
} else if( acc->thread != 0 ) {
ret->err = 1;
}
return( sizeof( *ret ) );
}
typedef enum { /* values for .cmd field */
PT_CMD_READ_MEM_I = 1, /* read I-space */
PT_CMD_READ_MEM_D, /* read D-space */
PT_CMD_READ_REGS, /* read registers */
PT_WRITE_CMD_MEM_I, /* write I-space */
PT_CMD_WRITE_MEM_D, /* write D-space */
PT_CMD_WRITE_REGS, /* write registers */
PT_CMD_GO, /* go (with signal) */
PT_CMD_TERMINATE, /* terminate child process */
PT_CMD_SINGLE_STEP, /* single step */
PT_CMD_STOP, /* stop child process */
PT_CMD_FREEZE, /* freeze child process */
PT_CMD_RESUME, /* resume child process */
PT_CMD_SEG_TO_SEL, /* resume child process */
PT_CMD_READ_8087, /* read npx */
PT_CMD_WRITE_8087, /* write npx */
PT_CMD_GET_LIB_NAME, /* get library module name */
PT_CMD_THREAD_STAT, /* get thread status */
#if 0 /* depends on which documentation you believe */
PT_CMD_READ_MEM_B, /* read memory block */
PT_CMD_WRITE_MEM_B, /* write memory block */
#else
PT_CMD_MAP_RO_ALIAS, /* create a read only segment alias */
PT_CMD_MAP_WR_ALIAS, /* create a read/write segment alias */
PT_CMD_UNMAP_ALIAS /* unmap a segment alias */
#endif
} trace_codes;
static unsigned DoThread( trace_codes code )
{
TID save;
thread_thaw_req *acc;
thread_thaw_ret *ret;
acc = GetInPtr( 0 );
ret = GetOutPtr( 0 );
if( ValidThread( acc->thread ) ) {
save = Buff.Tid;
Buff.Pid = Pid;
Buff.Tid = acc->thread;
Buff.Cmd = code;
CallDosDebug( &Buff );
Buff.Tid = save;
ret->err = 0;
} else {
ret->err = 1; // failed
}
return( sizeof( *ret ) );
}
unsigned ReqThread_freeze( void )
{
return( DoThread( DBG_C_Freeze ) );
}
unsigned ReqThread_thaw( void )
{
return( DoThread( DBG_C_Resume ) );
}
unsigned ReqGet_message_text( void )
{
get_message_text_ret *ret;
char *err_txt;
ret = GetOutPtr( 0 );
err_txt = GetOutPtr( sizeof( *ret ) );
if( ExceptNum == -1 ) {
err_txt[0] = '\0';
} else {
strcpy( err_txt, GetExceptionText() );
}
ExceptNum = -1;
ret->flags = MSG_NEWLINE | MSG_ERROR;
return( sizeof( *ret ) + strlen( err_txt ) + 1 );
}
unsigned ReqGet_next_alias( void )
{
get_next_alias_req *acc;
get_next_alias_ret *ret;
ret = GetOutPtr( 0 );
ret->seg = 0;
ret->alias = 0;
acc = GetInPtr( 0 );
if( Is32Bit && acc->seg == 0 ) {
ret->seg = FlatCS;
ret->alias = FlatDS;
}
return( sizeof( *ret ) );
}
void TRAPENTRY TellHandles( HAB hab, HWND hwnd )
{
TellSoftModeHandles( hab, hwnd );
}
char TRAPENTRY TellHardMode( char hard )
{
return( SetHardMode( hard ) );
}
trap_version TRAPENTRY TrapInit( char *parm, char *err, bool remote )
{
trap_version ver;
PTIB ptib;
PPIB ppib;
parm = parm;
Remote = remote;
err[0] = '\0';
ver.major = TRAP_MAJOR_VERSION;
ver.minor = TRAP_MINOR_VERSION;
ver.remote = FALSE;
SaveStdIn = NIL_DOS_HANDLE;
SaveStdOut = NIL_DOS_HANDLE;
Screen = DEBUG_SCREEN;
if( parm[0] == '2' ) {
stopOnSecond = TRUE;
}
DosGetInfoBlocks( &ptib, &ppib );
TypeProcess = ppib->pib_ultype;
InitSoftDebug();
InitDebugThread();
return( ver );
}
void TRAPENTRY TrapFini( void )
{
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -