📄 os2v2acc.c
字号:
/****************************************************************************
*
* 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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include <stddef.h>
#include <string.h>
#include <i86.h>
#define INCL_BASE
#define INCL_DOSDEVICES
#define INCL_DOSMEMMGR
#define INCL_DOSSIGNALS
#define INCL_DOSPROCESS
#undef INCL_DOSINFOSEG
#include <os2.h>
#include <os2dbg.h>
#include <string.h>
#include "trpimp.h"
#include "dosdebug.h"
#include "os2trap.h"
#include "os2v2acc.h"
#include "bsexcpt.h"
#include "wdpmhelp.h"
#include "softmode.h"
#include "madregs.h"
#define ERROR_DEFINE_CONSTS
#include "os2err.h"
#include "exedos.h"
#include "exeos2.h"
#include "exeflat.h"
#include "x86cpu.h"
__GINFOSEG *GblInfo;
dos_debug Buff;
static BOOL stopOnSecond;
USHORT TaskFS;
extern char SetHardMode( char );
extern VOID InitDebugThread(VOID);
#ifdef DEBUG_OUT
void Out( char *str )
{
USHORT written;
DosWrite( 1, str, _fstrlen( str ), &written );
}
#define NSIZE 20
void OutNum( ULONG i )
{
char numbuff[NSIZE];
char *ptr;
ptr = numbuff+NSIZE;
*--ptr = '\0';
if( i == 0 ) {
*--ptr = '0';
}
while( i != 0 ) {
*--ptr = "0123456789abcdef"[ i & 0x0f ];
i >>= 4;
}
Out( ptr );
}
#endif
#define EXE_NE 0x454e
#define EXE_LE 0x454c
#define EXE_LX 0x584c
#define OBJECT_IS_CODE 0x0004L
#define OBJECT_IS_BIG 0x2000L
#define EXE_IS_FULLSCREEN 0x0100
#define EXE_IS_PMC 0x0200
#define EXE_IS_PM 0x0300
static ULONG ExceptLinear;
static UCHAR TypeProcess;
static BOOL Is32Bit;
static watch WatchPoints[ MAX_WP ];
static short WatchCount = 0;
static short DebugRegsNeeded = 0;
static unsigned_16 lastCS;
static unsigned_16 lastSS;
static unsigned_32 lastEIP;
static unsigned_32 lastESP;
extern void bp( void );
bool ExpectingAFault;
char OS2ExtList[] = { ".exe\0" };
#pragma aux bp = 0xcc;
static bool Is32BitSeg( unsigned seg )
{
if( IsFlatSeg( seg ) ) return( TRUE );
if( IsUnknownGDTSeg( seg ) ) return( TRUE );
return( FALSE );
}
/*
* RecordModHandle - save module handle for later reference
*/
void RecordModHandle( ULONG value )
{
SEL sel;
if( ModHandles == NULL ) {
DosAllocSeg( sizeof( ULONG ), (PSEL)&sel, 0 );
ModHandles = MK_FP( sel, 0 );
} else {
DosReallocSeg( (NumModHandles+1)*sizeof( ULONG ),
FP_SEG( ModHandles ) );
}
ModHandles[ NumModHandles ] = value;
++NumModHandles;
}
/*
* SeekRead - seek to a file position, and read the data
*/
BOOL SeekRead( HFILE handle, ULONG newpos, void *ptr, USHORT size )
{
USHORT read;
ULONG pos;
if( DosChgFilePtr( handle, newpos, 0, &pos ) != 0 ) {
return( FALSE );
}
if( DosRead( handle, ptr, size, &read ) != 0 ) {
return( FALSE );
}
if( read != size ) {
return( FALSE );
}
return( TRUE );
} /* SeekRead */
/*
* FindNewHeader - get a pointer to the new exe header
*/
static BOOL FindNewHeader( char *name, HFILE *hdl,
ULONG *new_head, USHORT *id )
{
long open_rc;
HFILE h;
BOOL rc;
USHORT data;
open_rc = OpenFile( name, 0, OPEN_PRIVATE );
if( open_rc < 0 ) {
return( FALSE );
}
h = open_rc;
rc = FALSE;
while( 1 ) {
if( !SeekRead( h, 0x00, &data, sizeof( data ) ) ) {
break;
}
if( data != 0x5a4d ) break; /* MZ */
if( !SeekRead( h, 0x18, &data, sizeof( data ) ) ) {
break;
}
if( data < 0x40 ) break; /* offset of relocation header */
if( !SeekRead( h, 0x3c, new_head, sizeof( ULONG ) ) ) {
break;
}
if( !SeekRead( h, *new_head, id, sizeof( USHORT ) ) ) {
break;
}
rc = TRUE;
break;
}
if( !rc ) {
DosClose( h );
}
*hdl = h;
return( rc );
} /* FindNewHeader */
#define MAX_OBJECTS 128
static ULONG LastMTE;
static unsigned NumObjects;
static object_record ObjInfo[MAX_OBJECTS];
static void GetObjectInfo( ULONG mte )
{
HFILE hdl;
ULONG new_head;
USHORT type;
unsigned_32 objoff;
unsigned_32 numobjs;
char buff[256];
if( mte == LastMTE ) {
return;
}
memset( ObjInfo, 0, sizeof( ObjInfo ) );
DosGetModName( mte, 144, buff );
NumObjects = 0;
if( !FindNewHeader( buff, &hdl, &new_head, &type ) ) {
return;
}
if( type != EXE_LE && type != EXE_LX ) {
DosClose( hdl );
return;
}
SeekRead( hdl, new_head+0x40, &objoff, sizeof( objoff ) );
SeekRead( hdl, new_head+0x44, &numobjs, sizeof( numobjs ) );
if( numobjs <= MAX_OBJECTS ) {
SeekRead( hdl, new_head + objoff, ObjInfo, numobjs * sizeof( ObjInfo[0] ) );
NumObjects = numobjs;
}
LastMTE = mte;
DosClose( hdl );
}
bool DebugExecute( dos_debug *buff, ULONG cmd, bool stop_on_module_load )
{
EXCEPTIONREPORTRECORD ex;
ULONG value;
ULONG stopvalue;
ULONG notify=0;
BOOL got_second_notification;
ULONG fcp;
CONTEXTRECORD fcr;
buff->Cmd = cmd;
value = buff->Value;
if( cmd == DBG_C_Go ) {
value = 0;
}
stopvalue = XCPT_CONTINUE_EXECUTION;
got_second_notification = FALSE;
if( cmd == DBG_C_Stop ) {
stopvalue = XCPT_CONTINUE_STOP;
}
for( ;; ) {
buff->Value = value;
buff->Cmd = cmd;
CallDosDebug( buff );
value = stopvalue;
cmd = DBG_C_Continue;
/*
* handle the preemptive notifications
*/
switch( buff->Cmd ) {
case DBG_N_ModuleLoad:
RecordModHandle( buff->Value );
if( stop_on_module_load ) return( TRUE );
break;
case DBG_N_ModuleFree:
break;
case DBG_N_NewProc:
break;
case DBG_N_ProcTerm:
value = XCPT_CONTINUE_STOP; /* halt us */
notify = DBG_N_ProcTerm;
break;
case DBG_N_ThreadCreate:
break;
case DBG_N_ThreadTerm:
break;
case DBG_N_AliasFree:
break;
case DBG_N_Exception:
ExceptLinear = buff->Addr;
if( buff->Value == DBG_X_STACK_INVALID ) {
value = XCPT_CONTINUE_SEARCH;
break;
}
fcp = buff->Len;
if( buff->Value == DBG_X_PRE_FIRST_CHANCE ) {
ExceptNum = buff->Buffer;
if( ExceptNum == XCPT_BREAKPOINT ) {
notify = DBG_N_Breakpoint;
value = XCPT_CONTINUE_STOP;
break;
} else if( ExceptNum == XCPT_SINGLE_STEP ) {
notify = DBG_N_SStep;
value = XCPT_CONTINUE_STOP;
break;
}
}
//
// NOTE: Going to second chance causes OS/2 to report the
// exception in the debugee. However, if you report
// the fault at the first chance notification, the
// debugee's own fault handlers will not get invoked!
//
if( buff->Value == DBG_X_FIRST_CHANCE && !ExpectingAFault ) {
if( stopOnSecond && !got_second_notification ) {
value = XCPT_CONTINUE_SEARCH;
break;
}
}
notify = DBG_N_Exception;
value = XCPT_CONTINUE_STOP;
/*
* Buffer contains the ptr to the exception block
*/
buff->Cmd = DBG_C_ReadMemBuf;
buff->Addr = buff->Buffer;
buff->Buffer = MakeLocalPtrFlat( (void *) &ex );
buff->Len = sizeof( ex );
CallDosDebug( buff );
ExceptNum = ex.ExceptionNum;
if( ExceptNum == XCPT_PROCESS_TERMINATE ||
ExceptNum == XCPT_ASYNC_PROCESS_TERMINATE ||
ExceptNum == XCPT_GUARD_PAGE_VIOLATION ||
( ExceptNum & XCPT_CUSTOMER_CODE ) ) {
value = XCPT_CONTINUE_SEARCH;
break;
}
/*
* get the context record
*/
buff->Cmd = DBG_C_ReadMemBuf;
buff->Addr = fcp;
buff->Buffer = MakeLocalPtrFlat( (void *) &fcr );
buff->Len = sizeof( fcr );
CallDosDebug( buff );
buff->EAX = fcr.ctx_RegEax;
buff->EBX = fcr.ctx_RegEbx;
buff->ECX = fcr.ctx_RegEcx;
buff->EDX = fcr.ctx_RegEdx;
buff->ESI = fcr.ctx_RegEsi;
buff->EDI = fcr.ctx_RegEdi;
buff->ESP = fcr.ctx_RegEsp;
buff->EBP = fcr.ctx_RegEbp;
buff->DS = fcr.ctx_SegDs;
buff->CS = fcr.ctx_SegCs;
buff->ES = fcr.ctx_SegEs;
buff->FS = fcr.ctx_SegFs;
buff->GS = fcr.ctx_SegGs;
buff->SS = fcr.ctx_SegSs;
buff->EIP = fcr.ctx_RegEip;
buff->EFlags = fcr.ctx_EFlags;
WriteRegs( buff );
if( ExpectingAFault || got_second_notification ) {
break;
}
if( stopOnSecond ) {
value = XCPT_CONTINUE_EXECUTION;
got_second_notification = TRUE;
}
break;
default:
if( notify != 0 ) {
buff->Cmd = notify;
}
return( FALSE );
}
}
// return( FALSE );
}
void WriteRegs( dos_debug *buff )
{
buff->Cmd = DBG_C_WriteReg;
CallDosDebug( buff );
}
void ReadRegs( dos_debug *buff )
{
buff->Cmd = DBG_C_ReadReg;
CallDosDebug( buff );
}
void ReadLinear( char *data, ULONG lin, USHORT size )
{
Buff.Cmd = DBG_C_ReadMemBuf;
Buff.Addr = lin;
Buff.Buffer = MakeLocalPtrFlat( data );
Buff.Len = size;
CallDosDebug( &Buff );
}
void WriteLinear( char *data, ULONG lin, USHORT size )
{
Buff.Cmd = DBG_C_WriteMemBuf;
Buff.Addr = lin;
Buff.Buffer = MakeLocalPtrFlat( data );
Buff.Len = size;
CallDosDebug( &Buff );
}
USHORT WriteBuffer( char *data, USHORT segv, ULONG offv, USHORT size )
{
USHORT length;
bool iugs;
USHORT resdata;
ULONG flat;
if( segv < 4 ) {
return( 0 );
}
length = size;
if( Pid != 0 ) {
iugs = IsUnknownGDTSeg( segv );
if( !iugs ) {
flat = MakeItFlatNumberOne( segv, offv );
WriteLinear( data, flat, size );
if( Buff.Cmd == DBG_N_Success ) {
return( size );
}
}
while( length != 0 ) {
Buff.Cmd = DBG_C_WriteMem_D;
if( length == 1 ) {
if( iugs ) {
if( !TaskReadWord( segv, offv, &resdata )) {
break;
}
resdata &= 0xff00;
resdata |= *data;
if( !TaskWriteWord( segv, offv, resdata ) ) {
break;
}
} else {
Buff.Cmd = DBG_C_ReadMem_D;
Buff.Addr = MakeItFlatNumberOne( segv, offv );
CallDosDebug( &Buff );
Buff.Cmd = DBG_C_WriteMem_D;
Buff.Addr = MakeItFlatNumberOne( segv, offv );
Buff.Value &= 0xff00;
Buff.Value |= *data;
CallDosDebug( &Buff );
if( Buff.Cmd != DBG_N_Success ) {
break;
}
}
data++;
length--;
offv++;
} else {
resdata = *data;
data++;
resdata |= *data << 8;
data++;
if( iugs ) {
if( !TaskWriteWord( segv, offv, resdata ) ) {
break;
}
} else {
Buff.Value = resdata;
Buff.Addr = MakeItFlatNumberOne( segv, offv );
CallDosDebug( &Buff );
if( Buff.Cmd != DBG_N_Success ) {
break;
}
}
length -= 2;
offv += 2;
}
}
}
return( size - length ); /* return amount written */
}
static USHORT ReadBuffer( char *data, USHORT segv, ULONG offv, USHORT size )
{
USHORT length;
bool iugs;
USHORT resdata;
ULONG flat;
if( segv < 4 ) {
return( 0 );
}
length = size;
if( Pid != 0 ) {
iugs = IsUnknownGDTSeg( segv );
if( !iugs ) {
flat = MakeItFlatNumberOne( segv, offv );
ReadLinear( data, flat, size );
if( Buff.Cmd == DBG_N_Success ) {
return( size );
}
}
while( length != 0 ) {
if( iugs ) {
if( !TaskReadWord( segv, offv, &resdata ) ) {
break;
}
} else {
Buff.Cmd = DBG_C_ReadMem_D;
Buff.Addr = MakeItFlatNumberOne( segv, offv );
CallDosDebug( &Buff );
if( Buff.Cmd != DBG_N_Success ) {
break;
}
resdata = Buff.Value;
}
*data = resdata & 0xff;
data++;
offv++;
length--;
if( length != 0 ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -