⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dosacc.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
    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 + -