dbgbrk.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,847 行 · 第 1/4 页

C
1,847
字号
/****************************************************************************
*
*                            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:  Breakpoint and watchpoint management.
*
****************************************************************************/


#include <string.h>
#include "dbgdefn.h"
#include "dbgtoken.h"
#include "dbgerr.h"
#include "dbginfo.h"
#include "dbgbreak.h"
#include "dbgitem.h"
#include "dbglit.h"
#include "dbgmem.h"
#include "dbgtoggl.h"
#include "dbginp.h"
#include "namelist.h"
#include "dbgstk.h"
#include "dbgrep.h"
#include "dbgreg.h"
#include "dbgio.h"
#include "trpcore.h"
#include "mad.h"
#include "dui.h"
#include "spawn.h"
#include "enterdb.h"


extern cue_file_id      CueFileId( cue_handle * );
extern unsigned         CueFile( cue_handle *ch, char *file, unsigned max );
extern unsigned long    CueLine( cue_handle *ch );
extern unsigned long    ReqLongExpr( void );
extern unsigned int     ReqExpr( void );
extern char             *ReScan( char * );
extern void             ReqMemAddr( memory_expr, address * );
extern bool             ScanQuote( char **, unsigned int * );
extern bool             ScanEOC( void );
extern int              AddrComp( address, address );
extern unsigned int     ScanCmd( char * );
extern void             ReqEOC( void );
extern void             Scan( void );
extern cmd_list         *AllocCmdList( char *, unsigned int );
extern void             FreeCmdList( cmd_list * );
extern void             PushCmdList( cmd_list * );
extern address          GetRegIP( void );
extern int              SectIsLoaded( unsigned int, int  );
extern dword            RemoteSetBreak( address );
extern void             RemoteRestoreBreak( address, dword );
OVL_EXTERN brk          *TypePoint( memory_expr );
OVL_EXTERN brk          *BadPoint( memory_expr );
OVL_EXTERN brk          *ImageBreak( memory_expr );
OVL_EXTERN brk          *ActivatePoint( memory_expr );
OVL_EXTERN brk          *ClearPoint( memory_expr );
OVL_EXTERN brk          *TogglePoint( memory_expr );
OVL_EXTERN brk          *ResumePoint( memory_expr );
OVL_EXTERN brk          *UnResumePoint( memory_expr );
OVL_EXTERN brk          *DeactivatePoint( memory_expr );
OVL_EXTERN brk          *SetBreak( memory_expr );
OVL_EXTERN brk          *SetWatch( memory_expr );
OVL_EXTERN brk          *SetPoint( memory_expr def_seg, mad_type_handle );
extern bool             RemoteSetWatch( address, unsigned, unsigned long * );
extern void             RemoteRestoreWatch( address, unsigned );
extern void             ErrorBox( char * );
extern bool             DlgBreak( address );
extern void             SetProgState( unsigned );
extern void             TypeInpStack( input_type );
extern char             *DupStr( char * );
extern char             *DupStrLen( char const *str, unsigned len );
extern bool             CheckBPIns( void );
extern char             *GetCmdEntry( char *, int, char * );
extern char             *Format( char *buff, char *fmt, ... );
extern void             InvokeAFile( char * );
extern void             CreateInvokeFile( char *name, void (*rtn)( void ) );
extern void             UnAsm( address addr, unsigned, char *buff );
extern char             *AddHexSpec( char * );
extern char             *GetCmdName( int );
extern bool             DlgAreYouNuts( unsigned long );
extern inspect_type     WndGetExprSPInspectType( address *paddr );
extern char             *StrCopy( char *, char * );
extern void             RecordEvent( char *p );
extern void             SetRecord( bool on );
extern unsigned         DefaultSize( default_kind );
extern void             ReadDbgRegs( void );
extern void             WriteDbgRegs( void );
extern bool             SetMsgText( char *, unsigned * );
extern unsigned         GetMADTypeNameForCmd( mad_type_handle th, unsigned max, char *p );
extern mad_type_handle  ScanType( mad_type_kind, mad_type_kind * );
extern mad_type_handle  FindMADTypeHandle( mad_type_kind tk, unsigned size );
extern char             *CnvULongHex( unsigned long value, char *p );
extern unsigned         NewCurrRadix( unsigned );
extern void             WriteDbgRegs( void );
extern void             BreakOnImageLoad( char *name, unsigned len, bool clear );
extern bool             ScanItem( bool blank_delim, char **start, unsigned *len );
extern void             InitMappableAddr( mappable_addr *loc );
extern void             FiniMappableAddr( mappable_addr *loc );
extern void             UnMapPoints( image_entry * );
extern void             ReMapPoints( image_entry * );
extern char             *StrAddr( address *addr, char *buff, unsigned max );
extern image_entry      *ImageEntry( mod_handle mh );
extern char             *AddrToString( address *a, mad_address_format af, char *p, unsigned );
extern bool             DlgScanCodeAddr( char *str, address *value );
extern void             DoInput( void );
extern char             *CnvNearestAddr( address, char *, unsigned );
extern void             DbgUpdate( update_list );
extern bool             DUIGetSourceLine( cue_handle *ch, char *buff, unsigned len );
extern void             DUIRemoveBreak( brk *bp );
extern void             CheckForNewThreads( bool );
extern void             LValue(stack_entry *);


extern char_ring        *DLLList;
extern unsigned char    CurrRadix;
extern brk              UserTmpBrk;
extern brk              DbgTmpBrk;
extern char             *TxtBuff;
extern tokens           CurrToken;
extern debug_level      DbgLevel;
extern brk              *BrkList;
extern address          NilAddr;
extern stack_entry      *ExprSP;
extern mod_handle       CodeAddrMod;
extern machine_state    *DbgRegs;
extern system_config    SysConfig;

static char PointNameTab[] = {
    "Activate\0"
    "Clear\0"
    "Deactivate\0"
    "Set\0"
    "Modify\0"
    "Toggle\0"
    "Resume\0"
    "UNResume\0"
    "INdex\0"
    "IMage\0"
    "Unmapped\0"
    "MAPaddress\0"
    "SYMaddress\0"
};

typedef enum {
    B_ACTIVATE = 1,
    B_CLEAR,
    B_DEACTIVATE,
    B_SET,
    B_MODIFY,
    B_TOGGLE,
    B_RESUME,
    B_UNRESUME,
    B_INDEX,
    B_IMAGE,
    B_UNMAPPED,
    B_MAPADDRESS,
    B_SYMADDRESS,
} brk_event;

typedef struct {
    brk *(* rtn)(memory_expr);
    memory_expr type;
} bpjmptab_type;

static bpjmptab_type BPJmpTab[] = {
    { &TypePoint,       EXPR_DATA },
    { &ActivatePoint,   EXPR_CODE },
    { &ClearPoint,      EXPR_CODE },
    { &DeactivatePoint, EXPR_CODE },
    { &SetBreak,        EXPR_CODE },
    { &SetWatch,        EXPR_DATA },
    { &TogglePoint,     EXPR_CODE },
    { &ResumePoint,     EXPR_CODE },
    { &UnResumePoint,   EXPR_CODE },
    { &BadPoint,        EXPR_DATA },
    { &ImageBreak,      EXPR_DATA },
};


static char *BrkFmt( void )
{
    return( (DbgLevel != ASM) ? "%l" : "%a" );
}


/*
 * InitBPs -- initialize breakpoints
 */

void InitBPs( void )
{
    NullStatus( &UserTmpBrk );
    NullStatus( &DbgTmpBrk );
    BrkList = NULL;
}



/*
 * InsertOneBP -- insert one break point into memory
 */

static bool InsertOneBP( brk *bp, bool force )
{
    bool    at_ip;

    at_ip = FALSE;
    if( bp->status.b.active ) {
        if( !force && AddrComp( bp->loc.addr, GetRegIP() ) == 0 ) {
            at_ip = TRUE;
        } else if( SectIsLoaded( bp->loc.addr.sect_id, OVL_MAP_EXE ) ) {
            bp->status.b.in_place = TRUE;
            bp->item.ud = RemoteSetBreak( bp->loc.addr );
        }
    }
    return( at_ip );
}



/*
 * InsertBPs -- put break points into memory
 */

bool InsertBPs( bool force )
{
    brk     *bp;
    bool    at_ip;

    at_ip = FALSE;
    for( bp = BrkList; bp != NULL; bp = bp->next ) {
        bp->status.b.cmds_pushed = FALSE;
        if( bp->th != MAD_NIL_TYPE_HANDLE ) continue;
        bp->status.b.in_place = FALSE;
        bp->status.b.hit = FALSE;
        if( (UserTmpBrk.status.b.active)
         && (AddrComp( UserTmpBrk.loc.addr, bp->loc.addr ) == 0) ) continue;
        if( (DbgTmpBrk.status.b.active)
         && (AddrComp( DbgTmpBrk.loc.addr, bp->loc.addr ) == 0) ) continue;
        at_ip |= InsertOneBP( bp, force );
    }
    UserTmpBrk.status.b.hit = FALSE;
    UserTmpBrk.status.b.in_place = FALSE;
    DbgTmpBrk.status.b.hit = FALSE;
    DbgTmpBrk.status.b.in_place = FALSE;
    if( UserTmpBrk.status.b.active ) {
        at_ip |= InsertOneBP( &UserTmpBrk, force );
    }
    if( DbgTmpBrk.status.b.active
     && ( !UserTmpBrk.status.b.active
       || ( AddrComp( UserTmpBrk.loc.addr, DbgTmpBrk.loc.addr ) != 0 ) ) ) {
        at_ip |= InsertOneBP( &DbgTmpBrk, force );
    }
    return( at_ip );
}



/*
 * RemoveOneBP -- remove one breakpoint from memory
 */

static void RemoveOneBP( brk *bp )
{
    if( (bp->status.b.in_place) && SectIsLoaded( bp->loc.addr.sect_id, OVL_MAP_EXE ) ) {
        RemoteRestoreBreak( bp->loc.addr, bp->item.ud );
    }
}

static void RemoveOneWP( brk *bp )
{
    mad_type_info       mti;

    if( (bp->status.b.in_place) && SectIsLoaded(bp->loc.addr.sect_id,OVL_MAP_EXE) ) {
        bp->status.b.in_place = FALSE;
        MADTypeInfo( bp->th, &mti );
        RemoteRestoreWatch( bp->loc.addr, mti.b.bits / BITS_PER_BYTE );
    }
}


/*
 * RemoveBPs -- remove breakpoints from memory
 */

void RemoveBPs( void )
{
    brk     *bp;

    for( bp = BrkList; bp != NULL; bp = bp->next ) {
        if( bp->th != MAD_NIL_TYPE_HANDLE ) {
            RemoveOneWP( bp );
        } else {
            RemoveOneBP( bp );
        }
    }
    if( UserTmpBrk.status.b.active ) {
        RemoveOneBP( &UserTmpBrk );
    }
    if( DbgTmpBrk.status.b.active ) {
        RemoveOneBP( &DbgTmpBrk );
    }
}


void GetBPAddr( brk *bp, char *buff )
{
    char                *p;

    if( bp->status.b.unmapped ) {
        p = StrCopy( LIT( Image_Not_Loaded ), buff );
        if( bp->image_name != NULL ) {
            *p++ = '(';
            p = StrCopy( bp->image_name, p );
            *p++ = ')';
        }
    } else if( bp->th != MAD_NIL_TYPE_HANDLE && bp->source_line != NULL ) {
        p = StrCopy( bp->source_line, buff );
    } else {
        p = CnvNearestAddr( bp->loc.addr, buff, TXT_LEN );
    }
    StrCopy( ":", p );
}


void GetBPText( brk *bp, char *buff )
{
    unsigned    max;

    //MAD: might be a different mad then when break set
    max = ~0;
    if( bp->th == MAD_NIL_TYPE_HANDLE ) {
        if( bp->source_line != NULL ) {
            strcpy( buff, bp->source_line );
        } else {
            if( IS_NIL_ADDR( bp->loc.addr ) ) {
                strcpy( buff, LIT( Quest_Marks ) );
            } else {
                UnAsm( bp->loc.addr, max, buff );
            }
        }
    } else {
        MADTypeHandleToString( CurrRadix, bp->th, &bp->item, &max, buff );
    }
}


extern brk *FindBreakByLine( mod_handle mod, cue_file_id id, unsigned line )
{
    brk         *bp;
    mod_handle  brk_mod;
    DIPHDL( cue, ch );


    for( bp = BrkList; bp != NULL; bp = bp->next ) {
        if( DeAliasAddrMod( bp->loc.addr, &brk_mod ) == SR_NONE )continue;
        if( brk_mod != mod )continue;
        if( DeAliasAddrCue( brk_mod, bp->loc.addr, ch ) == SR_NONE ) continue;
        if( CueFileId( ch ) != id ) continue;
        if( CueLine( ch ) != line ) continue;
        return( bp );
    }
    return( NULL );
}


extern brk *FindBreak( address addr )
{
    brk     *bp;

    if( IS_NIL_ADDR( addr ) ) return( NULL );
    for( bp = BrkList; bp != NULL; bp = bp->next ) {
        if( ( AddrComp( bp->loc.addr, addr ) == 0 ) ) {
            return( bp );
        }
    }
    return( NULL );
}


/*
 * DispBPMsg -- display breakpoints that were hit
 */

static char *StrVal( char *which, brk *wp, char *p )
{
    unsigned    max;

    for( *p++ = ' '; *which != NULLCHAR; *p++ = *which++ ) {}
    *p++ = '=';
    max = ~0;
    MADTypeHandleToString( CurrRadix, wp->th, &wp->item, &max, p );
    p += max;
    return( p );
}


static char     *GetBPAddrText( brk *bp, char *p )
{
    if( bp->th != MAD_NIL_TYPE_HANDLE ) {
        p = StrCopy( LIT( Break_on_write ), p );
        if( bp->source_line != NULL ) {
            p = StrCopy( bp->source_line, p );
        } else {
            p = Format( p, "%a", bp->loc.addr );
        }
    } else {
        p = Format( p, LIT( Break_on_execute ) );
        p = Format( p, BrkFmt(), bp->loc.addr );
    }
    return( p );
}


static void GetWPVal( brk *wp )
{
    wp->status.b.has_value = FALSE;
    if( ItemGetMAD( &wp->loc.addr, &wp->item, IT_NIL, wp->th ) ) {
        wp->status.b.has_value = TRUE;
    }
}


bool DispBPMsg( bool stack_cmds )
{
    brk     *bp, *next;
    char    *p;
    bool    ret;
    cmd_list    *cmds;

    ret = FALSE;
    for( bp = BrkList; bp != NULL; bp = bp->next ) {
        if( !bp->status.b.hit ) continue;
        if( !bp->status.b.silent ) {
            if( bp->th != MAD_NIL_TYPE_HANDLE ) {
                p = GetBPAddrText( bp, TxtBuff );
                p = StrCopy( " - ", p );
                p = StrVal( LIT( OldVal ), bp, p );
                GetWPVal( bp );

⌨️ 快捷键说明

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