debugger.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 268 行

C
268
字号
/****************************************************************************
*
*                            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 protected mode debugging test app (16-bit executable).
*
****************************************************************************/


#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <conio.h>
#include <i86.h>
#include <sys/types.h>
#include <fcntl.h>
#include <io.h>
#include "tinyio.h"

#define RM_STACK_SIZE   ( 8 * 1024 )
#define MAX_STATE_SIZE  100
#define NB_VECTORS      256
#define SAVE_STATE      0
#define RESTORE_STATE   1
#define NULLFAR         0L
#define _debug( s )     { cputs( s );                           \
                          cputs( "\n\rPress a key\n\r" );       \
                          getch();                              \
                        }
#define _debug16( s, n ){ char buff[ 5 ];               \
                          cputs( s );                   \
                          _debug( itoa( n, buff, 16 ) );\
                        }
#define _debug32( s, n ){ char buff[ 9 ];               \
                          cputs( s );                   \
                          _debug( ltoa( n, buff, 16 ) );\
                        }

typedef struct {
    uint_16     limit;
    uint_32     base;
} DTreg;

unsigned                Envseg;
DTreg                   GDT;
unsigned                LDT;
DTreg                   IDT;
void                    far *OldPMHandler;
char                    PMProcCalled = 0;

static struct SREGS     RMRegs;
static struct SREGS     PMRegs;
static struct SREGS     SaveRegs;
static unsigned         StateSize;
static char             RMStateMem[ MAX_STATE_SIZE ];
static char             RMStack[ RM_STACK_SIZE ];
static void             far *OldRMStackPtr;
static void             far *OldRMHandler;
static void             far *SavePMState;
static void             far *RawRMtoPMAddr;
static void             far *RawPMtoRMAddr;
static void             far *RMVTable[ NB_VECTORS ];
static void             far *PMVTable[ NB_VECTORS ];

extern void             StoreDTs( DTreg *, unsigned *, DTreg * );
extern int              _fork( char *, unsigned );
extern void far         *GetPModeAddr( unsigned * );
extern int              EnterPMode( void far *, unsigned );
extern int              GetRawAddrs( void far **, void far ** );
extern void interrupt   PM66Handler( void );
extern void             PMProc( void );
extern void             SaveState( unsigned, void *, void far * );
extern void             DoRawSwitch( void far *, void far *, unsigned,
                                     struct SREGS * );

#pragma aux DoRawSwitch \
        parm routine [] \
        modify exact [ax bx cx dx si di];

#pragma aux SaveState \
    parm [ax] [di] [cx bx] \
    modify exact [ax bx cx di];

extern void far *SwitchStacks( void far *, void far ** );
#pragma aux SwitchStacks = \
    "test bx, bx    ",  \
    "jz   L1        ",  \
    "mov  [bx], sp  ",  \
    "mov  [bx+2], ss",  \
    "L1:            ",  \
    "mov  ss, dx    ",  \
    "mov  sp, ax    "   \
    parm [ax dx] [bx]   \
    modify exact [sp];

extern void DoInt66( unsigned, unsigned );
#pragma aux DoInt66 =   \
    "xor  bx, bx "      \
    "push bp     "      \
    "int  0x66   "      \
    "pop  bp     "      \
    parm [ax] [dx]      \
    modify exact [ax bx cx dx si di];

extern void DPMIFini( void );
#pragma aux DPMIFini aborts = \
    "mov  ah, 0x4c"     \
    "mov  al, 0   "     \
    "int  0x21    "     \
    modify exact [ax];


static void save_vects( void far **rmvtable, void far **pmvtable )
{
    int                 fhandle;
    int                 intnb;

    for( intnb = 0; intnb < NB_VECTORS; ++intnb ) {
        rmvtable[ intnb ] = (void far *)TinyDPMIGetRealVect( intnb );
        pmvtable[ intnb ] = TinyDPMIGetProtectVect( intnb );
    }
    fhandle = open( "vtable", O_BINARY | O_CREAT | O_TRUNC | O_WRONLY,
                    S_IREAD | S_IWRITE );
    if( fhandle <= 0 ) {
        _debug16( "error: fhandle <= 0, fhandle=", fhandle );
    } else {
        write( fhandle, rmvtable, NB_VECTORS * sizeof( *rmvtable ) );
        write( fhandle, pmvtable, NB_VECTORS * sizeof( *pmvtable ) );
        write( fhandle, &RMRegs.cs, sizeof( RMRegs.ds ) );
        write( fhandle, &RMRegs.ds, sizeof( RMRegs.ds ) );
        close( fhandle );
    }
}

static void restore_vects( void far **rmvtable, void far **pmvtable )
{
    int                 intnb;

    for( intnb = 0; intnb < NB_VECTORS; ++intnb ) {
        TinyDPMISetRealVect( intnb, FP_SEG( rmvtable[ intnb ] ),
                             FP_OFF( rmvtable[ intnb ] ) );
        TinyDPMISetProtectVect( intnb, pmvtable[ intnb ] );
    }
}

static void interrupt rm_66_handler( unsigned pmcs, unsigned pmds )
{
    SaveRegs = PMRegs;
    PMRegs.cs = pmcs;
    PMRegs.ds = pmds;
    PMRegs.ss = pmds;
    PMRegs.es = 0;
    SwitchStacks( &RMStack[ RM_STACK_SIZE ], &OldRMStackPtr );
    SaveState( SAVE_STATE, RMStateMem, SavePMState );
    _debug( "Hi from rm_66_handler" );
    PMProcCalled = 0;
    _debug( "raw switching to the debugger's protected mode" );
    DoRawSwitch( RawRMtoPMAddr, RawPMtoRMAddr, FP_OFF( &PMProc ), &PMRegs );
    _debug( "made it back to rm_66_handler" );
    _debug( PMProcCalled ? "PMProc was called" : "PMProc was NOT called" );
    SaveState( RESTORE_STATE, RMStateMem, SavePMState );
    PMRegs = SaveRegs;
    SwitchStacks( OldRMStackPtr, NULLFAR );
}

static void hook_vects( void far *pmaddr, void far *rmaddr,
                        void far **oldpmaddr, void far **oldrmaddr )
{
    if( oldpmaddr ) {
        *oldpmaddr = TinyDPMIGetProtectVect( 0x66 );
    }
    if( TinyDPMISetProtectVect( 0x66, pmaddr ) ) {
        _debug( "error hooking protected mode vector 0x66" );
    }
    if( oldrmaddr ) {
        *oldrmaddr = (void far *)TinyDPMIGetRealVect( 0x66 );
    }
    if( TinyDPMISetRealVect( 0x66, FP_SEG( rmaddr ), FP_OFF( rmaddr ) ) ) {
        _debug( "error hooking real mode vector 0x66" );
    }
}

static void start_shell( void )
{
    void                *statemem;

    statemem = alloca( StateSize );
    SaveState( SAVE_STATE, statemem, SavePMState );
    _debug( "reached real mode, starting up task.exe" );
    _fork( "task.exe", 8 );
    //_fork( "", 0 );
    _debug( "raw switching back to the debugger's protected mode" );
    SaveState( RESTORE_STATE, statemem, SavePMState );
}

static int getaddrs( void )
{
    RawPMtoRMAddr = TinyDPMIRawPMtoRMAddr();
    RawRMtoPMAddr = (void far *)TinyDPMIRawRMtoPMAddr();
    SavePMState = (void far *)TinyDPMISavePMStateAddr();
    StateSize = TinyDPMISaveStateSize();
    return( ( RawPMtoRMAddr != NULLFAR ) && ( RawRMtoPMAddr != NULLFAR ) &&
            ( SavePMState != NULLFAR ) );
}

extern void main( void )
{
    unsigned            dpmisize;
    void                *dpmimem;
    unsigned            dpmiseg;
    void                far *switchaddr;

    segread( &RMRegs );
    Envseg = *(unsigned far *)MK_FP( _psp, 0x2c );
    switchaddr = GetPModeAddr( &dpmisize );
    dpmimem = malloc( dpmisize + 15 );
    dpmiseg = FP_SEG( dpmimem ) + ( FP_OFF( dpmimem ) + 15 ) / 16;
    if( ( switchaddr == NULLFAR ) || ( dpmimem == NULL ) ) {
        _debug( "error, DPMI host is not present" );
    } else if( !EnterPMode( switchaddr, dpmiseg ) ) {
        _debug( "could not enter protected mode" );
    } else {
        _debug( "entered protected mode" );
        if( !getaddrs() ) {
            _debug( "could not get raw switch and state save addresses" );
        } else {

            segread( &PMRegs );
            hook_vects( MK_FP( PMRegs.cs, FP_OFF( &PM66Handler ) ),
                        &rm_66_handler, &OldPMHandler, &OldRMHandler );
            _debug( "doing an int 0x66" );
            DoInt66( PMRegs.cs, PMRegs.ds );
            _debug( "completed int 0x66" );
            _debug( "raw switching to real mode" );
            save_vects( RMVTable, PMVTable );
            DoRawSwitch( RawPMtoRMAddr, RawRMtoPMAddr,
                         FP_OFF( &start_shell ), &RMRegs );
            _debug( "made it back to the debugger's protected mode" );
            restore_vects( RMVTable, PMVTable );
            hook_vects( OldPMHandler, OldRMHandler, NULLFAR, NULLFAR );
        }
        _debug( "press any key to terminate debugger" );
        DPMIFini();
    }
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?