📄 dosacc.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: DOS real mode debugger access functions.
*
****************************************************************************/
//#define DEBUG_ME
#include <string.h>
#include <i86.h>
#include "tinyio.h"
#include "dbg386.h"
#include "drset.h"
#include "doshdl.h"
#include "exedos.h"
#include "exeos2.h"
#include "exephar.h"
#include "trperr.h"
#define ERR_CODES
#include "dosmsgs.h"
#undef ERR_CODES
#include "trpimp.h"
#include "ioports.h"
#include "winchk.h"
#include "madregs.h"
#include "x86cpu.h"
#include "misc7086.h"
typedef enum {
EXE_UNKNOWN,
EXE_DOS, /* DOS */
EXE_OS2, /* OS/2 */
EXE_PHARLAP_SIMPLE, /* PharLap Simple */
EXE_PHARLAP_EXTENDED_286, /* PharLap Extended 286 */
EXE_PHARLAP_EXTENDED_386, /* PharLap Extended 386 (may be bound) */
EXE_RATIONAL_386, /* Rational DOS/4G app */
EXE_LAST_TYPE
} EXE_TYPE;
#pragma aux MoveBytes = \
/* MoveBytes( fromseg, fromoff, toseg, tooff, len ); */ \
" rep movsb " \
parm caller [ ds ] [ si ] [ es ] [ di ] [ cx ] \
modify [ si di ];
#pragma aux MyFlags = \
" pushf " \
" pop ax " \
value [ax];
extern void MoveBytes( short, short, short, short, short );
extern unsigned short MyCS( void );
extern unsigned short MyFlags( void );
typedef _Packed struct pblock {
addr_seg envstring;
addr32_ptr commandln;
addr32_ptr fcb01;
addr32_ptr fcb02;
addr32_ptr startsssp;
addr32_ptr startcsip;
} pblock;
#define CMD_OFFSET 0x80
//
// NOTE: if you change this structure, you must update DBGTRAP.ASM
//
typedef _Packed struct watch {
addr32_ptr addr;
dword value;
dword linear;
short dregs;
short len;
} watch;
#define MAX_WP 32
watch WatchPoints[ MAX_WP ];
short WatchCount;
typedef enum {
TRAP_SKIP = -1,
TRAP_NONE,
TRAP_TRACE_POINT,
TRAP_BREAK_POINT,
TRAP_WATCH_POINT,
TRAP_USER,
TRAP_TERMINATE,
TRAP_MACH_EXCEPTION,
TRAP_OVL_CHANGE_LOAD,
TRAP_OVL_CHANGE_RET
} trap_types;
/* user modifiable flags */
#define USR_FLAGS (FLG_C | FLG_P | FLG_A | FLG_Z | FLG_S | \
FLG_I | FLG_D | FLG_O)
extern void InitRedirect(void);
extern addr_seg DbgPSP(void);
extern long DOSLoadProg(char far *, pblock far *);
extern addr_seg DOSTaskPSP(void);
extern void EndUser(void);
extern unsigned_8 RunProg(trap_cpu_regs *, trap_cpu_regs *);
extern void SetWatch386( unsigned, watch far * );
extern void SetWatchPnt(unsigned, watch far *);
extern void SetSingleStep(void);
extern void SetSingle386(void);
extern void SetDbgTask(void);
extern void SetUsrTask(void);
extern void InitVectors(void);
extern void FiniVectors(void);
extern void TrapTypeInit(void);
extern void ClrIntVecs(void);
extern void SetIntVecs(void);
extern void DoRemInt(trap_cpu_regs *, unsigned);
extern char Have87Emu(void);
extern void Null87Emu( void );
extern void Read87EmuState( void far * );
extern void Write87EmuState( void far * );
extern tiny_ret_t FindFilePath( char *, char *, char * );
extern unsigned Redirect( bool );
extern unsigned ExceptionText( unsigned, char * );
extern unsigned StringToFullPath( char * );
extern int far NoOvlsHdlr( int, void * );
extern bool CheckOvl( addr32_ptr );
extern int NullOvlHdlr(void);
extern word far SegmentChain;
static tiny_handle_t EXEhandle;
static tiny_ftime_t EXETime;
static tiny_fdate_t EXEDate;
#define ReadEXE( x ) TinyRead( EXEhandle, &x, sizeof(x) )
#define WriteEXE( x ) TinyWrite( EXEhandle, &x, sizeof(x) )
#define SeekEXEset( x ) TinySeek( EXEhandle, x, TIO_SEEK_START )
static dword NEOffset;
static word NumSegments;
static dword SegTable;
static dword StartByte;
static byte SavedByte;
static addr48_ptr BadBreak;
static bool GotABadBreak;
static int ExceptNum;
static unsigned_8 RealNPXType;
static unsigned_8 CPUType;
trap_cpu_regs TaskRegs;
char DOS_major;
char DOS_minor;
bool BoundAppLoading;
bool IsBreak[4];
struct {
unsigned Is386 : 1;
unsigned IsMMX : 1;
unsigned IsXMM : 1;
unsigned DRsOn : 1;
unsigned com_file : 1;
unsigned NoOvlMgr : 1;
unsigned BoundApp : 1;
} Flags;
#ifdef DEBUG_ME
int out( char * str )
{
char *p;
p = str;
while( *p ) ++p;
TinyWrite( 1, str, p - str );
return 0;
}
#define out0 out
static char hexbuff[80];
char * hex( unsigned long num )
{
char *p;
p = &hexbuff[79];
*p = 0;
if( num == 0 ) {
*--p = '0';
return( p );
}
while( num != 0 ) {
*--p = "0123456789abcdef"[ num & 15 ];
num >>= 4;
}
return( p );
}
#else
#define out( s )
#define out0( s ) 0
#define hex( n )
#endif
unsigned ReqGet_sys_config( void )
{
get_sys_config_ret *ret;
ret = GetOutPtr(0);
ret->sys.os = OS_DOS;
ret->sys.osmajor = DOS_major;
ret->sys.osminor = DOS_minor;
ret->sys.cpu = CPUType;
if( Have87Emu() ) {
ret->sys.fpu = X86_EMU;
} else if( RealNPXType != X86_NO ) {
if( CPUType < X86_486 ) {
ret->sys.fpu = RealNPXType;
} else {
ret->sys.fpu = CPUType & X86_CPU_MASK;
}
} else {
ret->sys.fpu = X86_NO;
}
ret->sys.huge_shift = 12;
ret->sys.mad = MAD_X86;
return( sizeof( *ret ) );
}
unsigned ReqMap_addr( void )
{
word seg;
int count;
word far *segment;
map_addr_req *acc;
map_addr_ret *ret;
acc = GetInPtr(0);
ret = GetOutPtr(0);
seg = acc->in_addr.segment;
switch( seg ) {
case MAP_FLAT_CODE_SELECTOR:
case MAP_FLAT_DATA_SELECTOR:
seg = 0;
break;
}
if( Flags.BoundApp ) {
count = NumSegments - seg;
segment = MK_FP( SegmentChain, 14 );
while( count != 0 ) {
segment = MK_FP( *segment, 14 );
--count;
}
ret->out_addr.segment = FP_SEG( segment ) + 1;
} else {
ret->out_addr.segment = DOSTaskPSP() + seg;
if( !Flags.com_file ) ret->out_addr.segment += 0x10;
}
ret->out_addr.offset = acc->in_addr.offset;
ret->lo_bound = 0;
ret->hi_bound = ~(addr48_off)0;
return( sizeof( *ret ) );
}
//OBSOLETE - use ReqMachine_data
unsigned ReqAddr_info( void )
{
addr_info_ret *ret;
ret = GetOutPtr( 0 );
ret->is_32 = FALSE;
return( sizeof( *ret ) );
}
unsigned ReqMachine_data( void )
{
machine_data_ret *ret;
unsigned_8 *data;
ret = GetOutPtr( 0 );
data = GetOutPtr( sizeof( *ret ) );
ret->cache_start = 0;
ret->cache_end = ~(addr_off)0;
*data = 0;
return( sizeof( *ret ) + sizeof( *data ) );
}
unsigned ReqChecksum_mem( void )
{
unsigned_8 far *ptr;
unsigned long sum = 0;
unsigned len;
checksum_mem_req *acc;
checksum_mem_ret *ret;
acc = GetInPtr(0);
ret = GetOutPtr(0);
ptr = MK_FP( acc->in_addr.segment, acc->in_addr.offset );
for( len = acc->len; len != 0; --len ) {
sum += *ptr++;
}
ret->result = sum;
return( sizeof( *ret ) );
}
static bool IsInterrupt( addr48_ptr addr, unsigned length )
{
unsigned long start, end;
start = ((unsigned long)addr.segment << 4) + addr.offset;
end = start + length;
return( start < 0x400 || end < 0x400 );
}
unsigned ReqRead_mem( void )
{
bool int_tbl;
read_mem_req *acc;
void *data;
unsigned len;
acc = GetInPtr(0);
data = GetOutPtr( 0 );
acc->mem_addr.offset &= 0xffff;
int_tbl = IsInterrupt( acc->mem_addr, acc->len );
if( int_tbl )
SetIntVecs();
len = acc->len;
if( ( acc->mem_addr.offset + len ) > 0xffff ) {
len = 0x10000 - acc->mem_addr.offset;
}
MoveBytes( acc->mem_addr.segment, acc->mem_addr.offset,
FP_SEG( data ), FP_OFF( data ), len );
if( int_tbl )
ClrIntVecs();
return( len );
}
unsigned ReqWrite_mem( void )
{
bool int_tbl;
write_mem_req *acc;
write_mem_ret *ret;
unsigned len;
void *data;
acc = GetInPtr(0);
ret = GetOutPtr(0);
data = GetInPtr(sizeof(*acc));
len = GetTotalSize() - sizeof(*acc);
acc->mem_addr.offset &= 0xffff;
int_tbl = IsInterrupt( acc->mem_addr, len );
if( int_tbl )
SetIntVecs();
if( ( acc->mem_addr.offset + len ) > 0xffff ) {
len = 0x10000 - acc->mem_addr.offset;
}
MoveBytes( FP_SEG( data ), FP_OFF( data ),
acc->mem_addr.segment, acc->mem_addr.offset, len );
if( int_tbl )
ClrIntVecs();
ret->len = len;
return( sizeof( *ret ) );
}
unsigned ReqRead_io( void )
{
read_io_req *acc;
void *data;
unsigned len;
acc = GetInPtr(0);
data = GetOutPtr(0);
if( acc->len == 1 ) {
*( (byte far *)data ) = In_b( acc->IO_offset );
len = 1;
} else if( acc->len == 2 ) {
*( (word far *)data ) = In_w( acc->IO_offset );
len = 2;
} else if( Flags.Is386 ) {
*( (dword far *)data ) = In_d( acc->IO_offset );
len = 4;
} else {
len = 0;
}
return( len );
}
unsigned ReqWrite_io( void )
{
write_io_req *acc;
write_io_ret *ret;
void *data;
unsigned len;
acc = GetInPtr(0);
data = GetInPtr( sizeof( *acc ) );
len = GetTotalSize() - sizeof( *acc );
ret = GetOutPtr(0);
if( len == 1 ) {
Out_b( acc->IO_offset, *( (byte far *)data ) );
ret->len = 1;
} else if( len == 2 ) {
Out_w( acc->IO_offset, *( (word far *)data ) );
ret->len = 2;
} else if ( Flags.Is386 ) {
Out_d( acc->IO_offset, *( (dword far *)data ) );
ret->len = 4;
} else {
ret->len = 0;
}
return( sizeof( *ret ) );
}
//OBSOLETE - use ReqRead_regs
unsigned ReqRead_cpu( void )
{
void *regs;
read_cpu_ret *ret;
ret = GetOutPtr( 0 );
regs = GetOutPtr( sizeof( *ret ) );
ret->cpu = TaskRegs;
return( sizeof( *ret ) );
}
//OBSOLETE - use ReqRead_regs
unsigned ReqRead_fpu( void )
{
void far *regs;
regs = GetOutPtr(0);
if( Have87Emu() ) {
Read87EmuState( regs );
} else if( RealNPXType != X86_NO ) {
Read8087( regs );
} else {
return( 0 );
}
return( sizeof( trap_fpu_regs ) );
}
//OBSOLETE - use ReqWrite_regs
unsigned ReqWrite_cpu( void )
{
trap_cpu_regs *regs;
regs = GetInPtr(sizeof(write_cpu_req));
TaskRegs = *regs;
return( 0 );
}
//OBSOLETE - use ReqWrite_regs
unsigned ReqWrite_fpu( void )
{
void far *regs;
regs = GetInPtr(sizeof(write_fpu_req));
if( Have87Emu() ) {
Write87EmuState( regs );
} else if( RealNPXType != X86_NO ) {
Write8087( regs );
}
return( 0 );
}
unsigned ReqRead_regs( void )
{
mad_registers *mr;
mr = GetOutPtr(0);
mr->x86.cpu = *(struct x86_cpu *)&TaskRegs;
if( Have87Emu() ) {
Read87EmuState( &mr->x86.fpu );
} else if( RealNPXType != X86_NO ) {
Read8087( &mr->x86.fpu );
} else {
memset( &mr->x86.fpu, 0, sizeof( mr->x86.fpu ) );
}
return( sizeof( mr->x86 ) );
}
unsigned ReqWrite_regs( void )
{
mad_registers *mr;
mr = GetInPtr(sizeof(write_regs_req));
*(struct x86_cpu *)&TaskRegs = mr->x86.cpu;
if( Have87Emu() ) {
Write87EmuState( &mr->x86.fpu );
} else if( RealNPXType != X86_NO ) {
Write8087( &mr->x86.fpu );
}
return( 0 );
}
static EXE_TYPE CheckEXEType( char *name )
{
tiny_ret_t rc;
union {
tiny_ret_t rc;
tiny_file_stamp_t stamp;
} exe_time;
word value;
byte breakpt;
static dos_exe_header head;
static os2_exe_header os2_head;
Flags.com_file = FALSE;
EXEhandle = 0;
rc = TinyOpen( name, TIO_READ_WRITE );
if( TINY_ERROR( rc ) )
return( EXE_UNKNOWN );
EXEhandle = rc;
exe_time.rc = TinyGetFileStamp( EXEhandle );
EXETime = exe_time.stamp.time;
EXEDate = exe_time.stamp.date;
if( TINY_ERROR( ReadEXE( head ) ) )
return( EXE_UNKNOWN ); /* MZ Signature */
switch( head.signature ) {
case SIMPLE_SIGNATURE: // mp
case REX_SIGNATURE: // mq
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -