📄 dosacc.c
字号:
case EXTENDED_SIGNATURE: // 'P3'
return( EXE_PHARLAP_SIMPLE );
case DOS_SIGNATURE:
if( head.reloc_offset != OS2_EXE_HEADER_FOLLOWS )
return( EXE_DOS );
if( TINY_ERROR( SeekEXEset( OS2_NE_OFFSET ) ) )
return( EXE_UNKNOWN );/* offset of new exe */
if( TINY_ERROR( ReadEXE( NEOffset ) ) )
return( EXE_UNKNOWN );
if( TINY_ERROR( SeekEXEset( NEOffset ) ) )
return( EXE_UNKNOWN );
if( TINY_ERROR( ReadEXE( os2_head ) ) )
return( EXE_UNKNOWN );/* NE Signature */
if( os2_head.signature == RAT_SIGNATURE_WORD )
return( EXE_RATIONAL_386 );
if( os2_head.signature != OS2_SIGNATURE_WORD )
return( EXE_UNKNOWN );
NumSegments = os2_head.segments;
SegTable = NEOffset + os2_head.segment_off;
if( os2_head.align == 0 )
os2_head.align = 9;
SeekEXEset( SegTable+(os2_head.entrynum-1)*8 );
ReadEXE( value );
StartByte = ( (long)value << os2_head.align ) + os2_head.IP;
SeekEXEset( StartByte );
ReadEXE( SavedByte );
breakpt = 0xCC;
SeekEXEset( StartByte );
rc = WriteEXE( breakpt );
return( EXE_OS2 );
default:
Flags.com_file = TRUE;
return( EXE_UNKNOWN );
}
}
static char DosExtList[] = { ".com\0.exe\0" };
unsigned ReqProg_load( void )
{
addr_seg psp;
pblock parmblock;
long rc;
char far *parm;
char far *src;
char far *dst;
char exe_name[128];
char ch;
EXE_TYPE exe;
prog_load_ret *ret;
char *end;
ExceptNum = -1;
ret = GetOutPtr( 0 );
memset( &TaskRegs, 0, sizeof( TaskRegs ) );
TaskRegs.EFL = MyFlags() & ~USR_FLAGS;
/* build a DOS command line parameter in our PSP command area */
Flags.BoundApp = FALSE;
psp = DbgPSP();
parm = GetInPtr( sizeof( prog_load_req ) );
if( TINY_ERROR( FindFilePath( parm, exe_name, DosExtList ) ) ) {
exe_name[0] = '\0';
}
while( *parm != '\0' )
++parm;
src = ++parm;
dst = MK_FP( psp, CMD_OFFSET+1 );
end = (char *)GetInPtr( GetTotalSize()-1 );
for( ;; ) {
if( src > end )
break;
ch = *src;
if( ch == '\0' )
ch = ' ';
*dst = ch;
++dst;
++src;
}
if( src > parm )
--dst;
*dst = '\r';
parm = MK_FP( psp, CMD_OFFSET );
*parm = FP_OFF( dst ) - (CMD_OFFSET+1);
parmblock.envstring = NULL;
parmblock.commandln.segment = psp;
parmblock.commandln.offset = CMD_OFFSET;
parmblock.fcb01.segment = psp;
parmblock.fcb02.segment = psp;
parmblock.fcb01.offset = 0X005C;
parmblock.fcb02.offset = 0X006C;
exe = CheckEXEType( exe_name );
if( EXEhandle != 0 ) {
TinyClose( EXEhandle );
EXEhandle = 0;
}
switch( exe ) {
case EXE_RATIONAL_386:
ret->err = ERR_RATIONAL_EXE;
return( sizeof( *ret ) );
case EXE_PHARLAP_SIMPLE:
ret->err = ERR_PHARLAP_EXE;
return( sizeof( *ret ) );
}
SegmentChain = 0;
BoundAppLoading = FALSE;
rc = DOSLoadProg( exe_name, &parmblock );
if( rc >= 0 ) {
rc = 0;
TaskRegs.SS = parmblock.startsssp.segment;
/* for some insane reason DOS returns a starting SP two less then
normal */
TaskRegs.ESP = parmblock.startsssp.offset + 2;
TaskRegs.CS = parmblock.startcsip.segment;
TaskRegs.EIP = parmblock.startcsip.offset;
psp = DOSTaskPSP();
} else {
psp = TinyAllocBlock( TinyAllocBlock( 0xffff ) );
TinyFreeBlock( psp );
TaskRegs.SS = psp + 0x10;
TaskRegs.ESP = 0xfffe;
TaskRegs.CS = psp + 0x10;
TaskRegs.EIP = 0x100;
}
TaskRegs.DS = psp;
TaskRegs.ES = psp;
if( rc == 0 ) {
if( Flags.NoOvlMgr || !CheckOvl( parmblock.startcsip ) ) {
if( exe == EXE_OS2 ) {
BoundAppLoading = TRUE;
RunProg( &TaskRegs, &TaskRegs );
parm = MK_FP(TaskRegs.CS, TaskRegs.EIP);
if( *parm == 0xCC ) {
*parm = SavedByte;
}
BoundAppLoading = FALSE;
rc = TinyOpen( exe_name, TIO_READ_WRITE );
if( TINY_OK( rc ) ) {
EXEhandle = rc;
SeekEXEset( StartByte );
WriteEXE( SavedByte );
TinySetFileStamp( EXEhandle, EXETime, EXEDate );
TinyClose( EXEhandle );
EXEhandle = 0;
rc = 0;
Flags.BoundApp = TRUE;
}
}
}
}
ret->err = rc;
ret->task_id = psp;
ret->flags = 0;
ret->mod_handle = 0;
return( sizeof( *ret ) );
}
unsigned ReqProg_kill( void )
{
prog_kill_ret *ret;
out( "in AccKillProg\r\n" );
ret = GetOutPtr( 0 );
InitRedirect();
if( DOSTaskPSP() != NULL ) {
out( "enduser\r\n" );
EndUser();
out( "done enduser\r\n" );
}
out( "null87emu\r\n" );
Null87Emu();
NullOvlHdlr();
ExceptNum = -1;
ret->err = 0;
out( "done AccKillProg\r\n" );
return( sizeof( *ret ) );
}
unsigned ReqSet_watch( void )
{
watch *curr;
set_watch_req *wp;
set_watch_ret *wr;
int i,needed;
wp = GetInPtr( 0 );
wr = GetOutPtr( 0 );
wr->err = 1;
wr->multiplier = 0;
if( WatchCount < MAX_WP ) {
wr->err = 0;
curr = WatchPoints + WatchCount;
curr->addr.segment = wp->watch_addr.segment;
curr->addr.offset = wp->watch_addr.offset;
curr->value = *(dword far *)MK_FP( wp->watch_addr.segment, wp->watch_addr.offset );
curr->linear = ( (unsigned long)wp->watch_addr.segment << 4 ) + wp->watch_addr.offset;
curr->len = wp->size;
curr->linear &= ~(curr->len-1);
curr->dregs = ( wp->watch_addr.offset & (curr->len-1) ) ? 2 : 1;
++WatchCount;
if( Flags.DRsOn ) {
needed = 0;
for( i = 0; i < WatchCount; ++i ) {
needed += WatchPoints[ i ].dregs;
}
if( needed <= 4 ) {
wr->multiplier |= USING_DEBUG_REG;
}
}
}
wr->multiplier |= 200;
return( sizeof( *wr ) );
}
unsigned ReqClear_watch( void )
{
WatchCount = 0;
return( 0 );
}
unsigned ReqSet_break( void )
{
char far *loc;
set_break_req *acc;
set_break_ret *ret;
acc = GetInPtr( 0 );
ret = GetOutPtr( 0 );
loc = MK_FP( acc->break_addr.segment, acc->break_addr.offset );
ret->old = *loc;
*loc = 0xCC;
if( *loc != 0xCC ) {
BadBreak = acc->break_addr;
GotABadBreak = TRUE;
}
return( sizeof( *ret ) );
}
unsigned ReqClear_break( void )
{
clear_break_req *bp;
bp = GetInPtr( 0 );
*(char far *)MK_FP( bp->break_addr.segment, bp->break_addr.offset ) = bp->old;
GotABadBreak = FALSE;
return( 0 );
}
static unsigned long SetDRn( int i, unsigned long linear, long type )
{
switch( i ) {
case 0:
SetDR0( linear );
break;
case 1:
SetDR1( linear );
break;
case 2:
SetDR2( linear );
break;
case 3:
SetDR3( linear );
break;
}
return( ( type << DR7_RWLSHIFT(i) )
// | ( DR7_GEMASK << DR7_GLSHIFT(i) ) | DR7_GE
| ( DR7_LEMASK << DR7_GLSHIFT(i) ) | DR7_LE );
}
static int ClearDebugRegs( int trap )
{
long dr6;
int i;
if( Flags.DRsOn ) {
out( "tr=" ); out( hex( trap ) );
out( " dr6=" ); out( hex( GetDR6() ) );
out( "\r\n" );
if( trap == TRAP_WATCH_POINT ) { /* could be a 386 break point */
dr6 = GetDR6();
if( ( ( dr6 & DR6_B0 ) && IsBreak[0] )
|| ( ( dr6 & DR6_B1 ) && IsBreak[1] )
|| ( ( dr6 & DR6_B2 ) && IsBreak[2] )
|| ( ( dr6 & DR6_B3 ) && IsBreak[3] ) ) {
trap = TRAP_BREAK_POINT;
}
}
for( i = 0; i < 4; ++i ) {
IsBreak[ i ] = FALSE;
}
SetDR6( 0 );
SetDR7( 0 );
}
return( trap );
}
static bool SetDebugRegs( void )
{
int needed;
int i;
int dr;
unsigned long dr7;
unsigned long linear;
watch *wp;
bool watch386;
if( !Flags.DRsOn )
return( FALSE );
needed = 0;
for( i = WatchCount, wp = WatchPoints; i != 0; --i, ++wp ) {
needed += wp->dregs;
}
dr = 0;
dr7 = 0;
if( needed > 4 ) {
watch386 = FALSE;
} else {
for( i = WatchCount, wp = WatchPoints; i != 0; --i, ++wp ) {
dr7 |= SetDRn( dr, wp->linear, DRLen( wp->len ) | DR7_BWR );
++dr;
if( wp->dregs == 2 ) {
dr7 |= SetDRn( dr, wp->linear+4, DRLen( wp->len ) | DR7_BWR );
++dr;
}
watch386 = TRUE;
}
}
if( GotABadBreak && dr < 4 ) {
linear = ( (unsigned long)BadBreak.segment << 4 ) + BadBreak.offset;
dr7 |= SetDRn( dr, linear, DR7_L1 | DR7_BINST );
IsBreak[ dr ] = TRUE;
++dr;
}
SetDR7( dr7 );
return( watch386 );
}
static unsigned MapReturn( int trap )
{
out( "cond=" );
switch( trap ) {
case TRAP_TRACE_POINT:
out( "trace point" );
return( COND_TRACE );
case TRAP_BREAK_POINT:
out( "break point" );
return( COND_BREAK );
case TRAP_WATCH_POINT:
out( "watch point" );
return( COND_WATCH );
case TRAP_USER:
out( "user" );
return( COND_USER );
case TRAP_TERMINATE:
out( "terminate" );
return( COND_TERMINATE );
case TRAP_MACH_EXCEPTION:
out( "exception" );
ExceptNum = 0;
return( COND_EXCEPTION );
case TRAP_OVL_CHANGE_LOAD:
out( "overlay load" );
return( COND_SECTIONS );
case TRAP_OVL_CHANGE_RET:
out( "overlay ret" );
return( COND_SECTIONS );
default:
break;
}
out( "none" );
return( 0 );
}
static unsigned ProgRun( bool step )
{
bool watch386;
prog_go_ret *ret;
ret = GetOutPtr( 0 );
if( Flags.DRsOn ) {
SetSingle386();
} else {
SetSingleStep();
}
if( step ) {
TaskRegs.EFL |= FLG_T;
} else {
watch386 = SetDebugRegs();
if( WatchCount != 0 && !watch386 ) {
if( Flags.DRsOn ) {
SetWatch386( WatchCount, WatchPoints );
} else {
SetWatchPnt( WatchCount, WatchPoints );
}
TaskRegs.EFL |= FLG_T;
}
}
out( "in CS:EIP=" ); out( hex( TaskRegs.CS ) ); out(":" ); out( hex( TaskRegs.EIP ) );
out( " SS:ESP=" ); out( hex( TaskRegs.SS ) ); out(":" ); out( hex( TaskRegs.ESP ) );
out( "\r\n" );
ret->conditions = MapReturn( ClearDebugRegs( RunProg( &TaskRegs, &TaskRegs ) ) );
ret->conditions |= COND_CONFIG;
// out( "cond=" ); out( hex( ret->conditions ) );
out( " CS:EIP=" ); out( hex( TaskRegs.CS ) ); out(":" ); out( hex( TaskRegs.EIP ) );
out( " SS:ESP=" ); out( hex( TaskRegs.SS ) ); out(":" ); out( hex( TaskRegs.ESP ) );
out( "\r\n" );
ret->stack_pointer.segment = TaskRegs.SS;
ret->stack_pointer.offset = TaskRegs.ESP;
ret->program_counter.segment = TaskRegs.CS;
ret->program_counter.offset = TaskRegs.EIP;
TaskRegs.EFL &= ~FLG_T;
WatchCount = 0;
return( sizeof( *ret ) );
}
unsigned ReqProg_go( void )
{
return( ProgRun( FALSE ) );
}
unsigned ReqProg_step( void )
{
return( ProgRun( TRUE ) );
}
unsigned ReqGet_next_alias( void )
{
get_next_alias_ret *ret;
ret = GetOutPtr( 0 );
ret->seg = 0;
ret->alias = 0;
return( sizeof( *ret ) );
}
unsigned ReqGet_lib_name( void )
{
char *ch;
get_lib_name_ret *ret;
ret = GetOutPtr( 0 );
ret->handle = 0;
ch = GetOutPtr( sizeof( *ret ) );
*ch = '\0';
return( sizeof( *ret ) + 1 );
}
unsigned ReqGet_err_text( void )
{
static const char *const DosErrMsgs[] = {
#include "dosmsgs.h"
};
get_err_text_req *acc;
char *err_txt;
acc = GetInPtr( 0 );
err_txt = GetOutPtr( 0 );
if( (unsigned_16)acc->err > ( (sizeof(DosErrMsgs)/sizeof(char *)-1) ) ) {
strcpy( err_txt, TRP_ERR_unknown_system_error );
} else {
strcpy( err_txt, DosErrMsgs[ (unsigned_16)acc->err ] );
}
return( strlen( err_txt ) + 1 );
}
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 {
ExceptionText( ExceptNum, err_txt );
ExceptNum = -1;
}
ret->flags = MSG_NEWLINE | MSG_ERROR;
return( sizeof( *ret ) + strlen( err_txt ) + 1 );
}
char *GetExeExtensions( void )
{
return( DosExtList );
}
trap_version TRAPENTRY TrapInit( char *parm, char *err, bool remote )
{
trap_version ver;
out( "in TrapInit\r\n" );
out( " checking environment:\r\n" );
CPUType = X86CPUType();
Flags.Is386 = ( CPUType >= X86_386 );
if( parm[0] == 'D' || parm[0] == 'd' ) {
Flags.DRsOn = FALSE;
++parm;
} else if( out0( " CPU type\r\n" ) || ( Flags.Is386 == 0 ) ) {
Flags.DRsOn = FALSE;
} else if( out0( " WinEnh\r\n" ) || ( EnhancedWinCheck() & 0x7f ) ) {
/* Enhanced Windows 3.0 VM kernel messes up handling of debug regs */
Flags.DRsOn = FALSE;
} else if( out0( " DOSEMU\r\n" ) || DOSEMUCheck() ) {
/* no fiddling with debug regs in Linux DOSEMU either */
Flags.DRsOn = FALSE;
} else {
Flags.DRsOn = TRUE;
}
if( parm[0] == 'O' || parm[0] == 'o' ) {
Flags.NoOvlMgr = TRUE;
}
out( " done checking environment\r\n" );
err[0] = '\0'; /* all ok */
Flags.IsMMX = ( ( CPUType & X86_MMX ) != 0 );
Flags.IsXMM = ( ( CPUType & X86_XMM ) != 0 );
/* NPXType initializes '87, so check for it before a program
starts using the thing */
RealNPXType = NPXType();
InitVectors();
if( DOS_major >= 20 ) {
/* In an OS/2 2.0 DOS box. It doesn't let us fiddle the debug
registers. The check is done here because InitVectors is the
routine that sets up DOS_major */
Flags.DRsOn = FALSE;
}
Null87Emu();
NullOvlHdlr();
TrapTypeInit();
InitRedirect();
ExceptNum = -1;
WatchCount = 0;
ver.major = TRAP_MAJOR_VERSION;
ver.minor = TRAP_MINOR_VERSION;
ver.remote = FALSE;
out( "done TrapInit\r\n" );
return( ver );
}
void TRAPENTRY TrapFini( void )
{
out( "in TrapFini\r\n" );
FiniVectors();
out( "done TrapFini\r\n" );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -