dbgwass.c

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

C
1,095
字号
/****************************************************************************
*
*                            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:  Processing of pop-up menu for assembly view.
*
****************************************************************************/


#include <string.h>
#include "dbgdefn.h"
#include "dbgreg.h"
#include "dbgio.h"
#include "dbgwind.h"
#include "dbgadget.h"
#include "dbginfo.h"
#include "dbgtoken.h"
#include "dbgerr.h"
#include "dbgmem.h"
#include "dbgtoggl.h"
#include "dbgitem.h"
#include "dbgbreak.h"
#include "mad.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 bool             WndEvalInspectExpr( char *item, bool pop );
extern void             WndInspectExprSP( char *item );
extern int              AddrComp(address ,address );
extern void             InitCache(address,unsigned);
extern void             FiniCache(void);
extern bool             DlgBreak(address);
extern void             GoToAddr( address addr );
extern void             WndFuncInspect( mod_handle mod );
extern a_window         *WndAsmInspect( address addr );
extern bool             DlgCodeAddr( char *title, address *value );
extern void             ToggleBreak(address);
extern void             SetCodeDot(address);
extern address          GetCodeDot(void);
extern bool             HasLineInfo(address);
extern brk              *FindBreak(address);
extern unsigned         NewCurrRadix(unsigned int );
extern bool             SrcMoveDot( a_window *, address );
extern void             SrcJoinAsm( a_window *, a_window * );
extern void             SrcFreeAsm( a_window * );
extern void             SrcNewAsmNotify( a_window *, mod_handle, bool track );
extern a_window         *SrcWndFind( a_window*src, address addr,bool track );
extern void             SkipToAddr( address );
extern char             *StrAddr(address *,char *,unsigned);
extern void             FileBreakGadget( a_window *,wnd_line_piece *line, bool curr, brk *bp );
extern a_window         *DoWndAsmOpen( address addr, bool track );
extern unsigned         ProgPeek(address ,void *,unsigned int );
extern bool             DlgModName( char *title, mod_handle *mod );
extern void             WndVarInspect( char * );
extern char             *StrCopy(char*src,char*dst);
extern void             SetUnderLine( a_window*, wnd_line_piece *);
extern void             PushAddr( address );
extern void             BreakOnExprSP( char *comment );
extern char             *AddrToString( address *, mad_address_format, char *, unsigned );
extern void             ReportMADFailure( mad_status );

extern void             *OpenSrcFile(cue_handle * );
extern int              FReadLine(void   *,int ,int ,char *,int );
extern void             FDoneSource(void         *);
extern char             *Format(char *,char *,... );
extern void             StepIntoFunction( char * );
extern void             BreakOnSelected( char *item );
extern void             GoHome(void);
extern address          ModFirstAddr( mod_handle mod );
extern gui_menu_struct *WndAppendToggles( mad_toggle_strings const *toggles, unsigned *pnum_toggles,
                                   gui_menu_struct *old, unsigned num_old, int id );
extern void             WndDeleteToggles( gui_menu_struct *popup, unsigned num_old, unsigned num_toggles );
extern char             *StrAddr( address *addr, char *p, unsigned max );
extern char             *ModImageName( mod_handle handle );
extern mad_type_handle  GetMADTypeHandleDefaultAt( address a, mad_type_kind mtk );
extern bool             InsMemRef( mad_disasm_data *dd );
extern void             DbgUpdate( update_list );

extern machine_state    *DbgRegs;
extern char             *TxtBuff;
extern address          NilAddr;
extern debug_level      ActiveWindowLevel;
extern unsigned char    CurrRadix;


#include "menudef.h"

static gui_menu_struct AsmShowMenu[] = {
    #define pick( a,b,c,d,e,f,g ) MENU_ITEM( a, b )
    #include "masmshow.h"
};

static gui_menu_struct AsmMenu[] = {
    #include "menuasm.h"
};


enum {
    PIECE_BREAK,
    PIECE_ADDRESS,
    PIECE_CURRENT = PIECE_ADDRESS,
    PIECE_BRANCH_INDICATOR,
    PIECE_OPCODE,
    PIECE_OPERANDS,
    PIECE_MEMREF
};

#define AVG_INS_SIZE    7

#define TITLE_SIZE      1

typedef struct {
    address     addr;
    unsigned    line;
} asm_addr;

typedef struct {
        asm_addr        *ins;
        int             ins_size;
        address         active;
        address         dotaddr;
        address         cache_addr;
        mad_disasm_data *cache_dd;
        unsigned        ddsize;
        gui_ord         ins_end;
        gui_ord         address_end;
        gui_ord         last_width;
        a_window        *src;
        mod_handle      mod;
        struct {
            mod_handle  mod;
            cue_file_id file_id;
        }               src_list;
        void            *viewhndl;
        unsigned        num_toggles;
        gui_menu_struct *popup;
        mad_type_handle def_addr;
        unsigned        addr_len;
        unsigned        track           : 1;
        unsigned        toggled_break   : 1;
        unsigned        source          : 1;
        unsigned        hex             : 1;
} asm_window;
#define WndAsm( wnd ) ( (asm_window *)WndExtra( wnd ) )

static bool ExactCueAt( asm_window *asm, address addr, cue_handle *ch )
{
    if( !asm->source ) return( FALSE );
    if( DeAliasAddrCue( NO_MOD, addr, ch ) == SR_NONE ) return( FALSE );
    if( AddrComp( CueAddr( ch ), addr ) ) return( FALSE );
    return( TRUE );
}

static  void    AsmResize( a_window *wnd );

static void AsmSetFirst( a_window *wnd, address addr, bool use_first_source )
{
    int                 row,rows;
    asm_window          *asm = WndAsm( wnd );
    char                chr;
    mad_disasm_data     *dd;
    unsigned            addr_len;
    DIPHDL( cue, ch );

    _AllocA( dd, asm->ddsize );


    if( IS_NIL_ADDR( addr ) || ProgPeek( addr, &chr, 1 ) != 1 ) {
        addr = NilAddr;
    }
    asm->ins[ 0 ].addr = addr;
    asm->ins[ 0 ].line = 0;
    addr_len = AddrToString( &addr, MAF_OFFSET, TxtBuff, TXT_LEN ) - TxtBuff;
    if( addr_len != asm->addr_len ) {
        asm->addr_len = addr_len;
        AsmResize( wnd ); // recusively calls this routine!
        WndZapped( wnd );
        return;
    }
    rows = WndRows( wnd );
    for( row = 0; row < rows; ++row ) {
        asm->ins[ row ].addr = addr;
        if( IS_NIL_ADDR( addr ) ) continue;
        if( ExactCueAt( asm, addr, ch ) ) {
            if( row != 0 || use_first_source ) {
                asm->ins[ row ].addr = addr;
                asm->ins[ row ].line = CueLine( ch );
                ++row;
                if( row >= rows ) break;
            }
        }
        asm->ins[ row ].addr = addr;
        asm->ins[ row ].line = 0;
        if( MADDisasm( dd, &addr, 0 ) != MS_OK ) {
            addr = NilAddr;
        }
    }
}

static  void    CalcAddrLen( a_window *wnd, address addr )
{
    asm_window  *asm = WndAsm( wnd );
    unsigned    old;

    old = NewCurrRadix( asm->hex ? 16 : 10 );
    AddrToString( &addr, MAF_OFFSET, TxtBuff, TXT_LEN );
    asm->address_end = MaxGadgetLength;
    asm->address_end += ( strlen( TxtBuff ) + 1 ) * WndMidCharX( wnd );
    NewCurrRadix( old );
}

static  void    AsmResize( a_window *wnd )
{
    asm_window          *asm = WndAsm( wnd );
    asm_addr            *new_ins;
    address             first;
    int         size;

    size = WndRows( wnd );
    if( size <= 0 ) size = 1;
    first = asm->ins[ 0 ].addr;
    new_ins = WndAlloc( size*sizeof( *new_ins ) );
    memset( new_ins, 0, size*sizeof( *new_ins ) );
    if( new_ins == NULL ) {
        WndClose( wnd );
        WndNoMemory();
    }
    WndFree( asm->ins );
    asm->ins = new_ins;
    asm->ins_size = size;
    AsmSetFirst( wnd, first, asm->ins[ 0 ].line != 0 );
    CalcAddrLen( wnd, first );
    if( asm->last_width != WndWidth( wnd ) ) {
        WndZapped( wnd );
    }
    asm->last_width = WndWidth( wnd );
    WndFixedThumb( wnd );
}

static int AsmAddrRow( a_window *wnd, address ip )
{
    int         row;
    asm_window *asm = WndAsm( wnd );

    for( row = 0; row < WndRows( wnd ); ++row ) {
        if( asm->ins[ row ].line != 0 ) continue;
        if( AddrComp( asm->ins[ row ].addr, ip ) == 0 ) break;
    }
    return( row );
}

extern  void    AsmJoinSrc( a_window *wnd, a_window *src )
{
    WndAsm( wnd )->src = src;
}

extern  void    AsmNewSrcNotify( a_window *src, mod_handle mod, bool track )
{
    asm_window  *asm;
    a_window    *wnd;

    for( wnd = WndNext( NULL ); wnd != NULL; wnd = WndNext( wnd ) ) {
        if( WndClass( wnd ) != WND_ASSEMBLY ) continue;
        asm = WndAsm( wnd );
        if( track != asm->track ) continue;
        if( mod != asm->mod ) continue;
        if( asm->src != NULL ) continue;
        SrcJoinAsm( src, wnd );
        AsmJoinSrc( wnd, src );
        break;
    }
}

static void AsmSetTitle( a_window *wnd )
{
    char        *p;
    char        *image_name;
    asm_window  *asm = WndAsm( wnd );

    p = StrCopy( ": ", StrCopy( LIT( WindowAssembly ), TxtBuff ) );
    p += ModName( asm->mod, p, TXT_LEN );
    image_name = ModImageName( asm->mod );
    if( image_name[0] != '\0' ) {
        p = StrCopy( "(", StrCopy( " ", p ) );
        p = StrCopy( ")", StrCopy( SkipPathInfo( image_name, OP_REMOTE ), p ) );
    }
    WndSetTitle( wnd, TxtBuff );
}

static void AsmSetDotAddr( a_window *wnd, address addr )
{
    mod_handle  mod;
    asm_window  *asm = WndAsm( wnd );

    if( AddrComp( asm->dotaddr, addr ) != 0 ) {
        WndRowDirty( wnd, -TITLE_SIZE );
        asm->dotaddr = addr;
        DeAliasAddrMod( addr, &mod );
        if( mod != asm->mod ) {
            DbgUpdate( UP_OPEN_CHANGE );
            asm->mod = mod;
            AsmSetTitle( wnd );
        }
        if( IS_NIL_ADDR( addr ) ) return;
        if( wnd == WndFindActive() ) {
            SrcMoveDot( asm->src, addr );
            SetCodeDot( addr );
        }
    }
}

extern  void    AsmMoveDot( a_window *wnd, address addr )
{
    int         row;
    asm_window  *asm;
    DIPHDL( cue, ch1 );
    DIPHDL( cue, ch2 );

    if( wnd == NULL ) return;

    asm = WndAsm( wnd );
    if( DeAliasAddrCue( asm->mod, addr, ch1 ) != SR_NONE &&
        DeAliasAddrCue( asm->mod, asm->dotaddr, ch2 ) != SR_NONE ) {
        if( CueMod( ch1 )    == CueMod( ch2 ) &&
            CueFileId( ch1 ) == CueFileId( ch2 ) &&
            CueLine( ch1 )   == CueLine( ch2 ) ) {
            return;
        }
    }
    WndNoSelect( wnd );
    row = AsmAddrRow( wnd, addr );
    if( row == WndRows( wnd ) ) {
        AsmSetFirst( wnd, addr, TRUE );
        row = AsmAddrRow( wnd, addr );
        WndDirtyCurr( wnd );
        WndNewCurrent( wnd, row, PIECE_CURRENT );
        WndRepaint( wnd );
        row = 0;
    } else {
        WndDirtyCurr( wnd );
        WndNewCurrent( wnd, row, PIECE_CURRENT );
    }

⌨️ 快捷键说明

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