ovldbg.c

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

C
395
字号
/****************************************************************************
*
*                            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:  Overlay debugger support.
*
****************************************************************************/


#include <stddef.h>
#include <dos.h>
#if defined( OVL_MULTITHREAD )
#include "novlldr.h"
#elif defined( OVL_WHOOSH )
#include "novlldr.h"
#else
#include "ovlstd.h"
#endif

#include "ovldbg.h"

#ifndef FALSE
#define FALSE       0
#define TRUE        (!FALSE)
#endif

typedef struct {
    void    far *addr;
    short   sect;
} ovl_addr;

typedef unsigned char byte;

#if defined( OVL_WHOOSH )
extern int  near __LoadNewOverlay__( int );
extern int  near __LoadSectionCode__( ovltab_entry far * );
#else
extern int  near NAME( LoadOverlay )( int );
#endif

#ifndef OVL_WHOOSH
extern unsigned  far    __BankStack__;
#else
typedef struct {
    unsigned    location;
    unsigned    section;
    unsigned    bitsize;
} ovl_dbg_info;

extern ovl_dbg_info far __OVLDBGINFO__;
#endif


static int GetSizeOverlays( void )
/********************************/
// This returns the size of the overlay state table.
{
    unsigned    number;

    number = (ovltab_entry far *)&__OVLTABEND__ - __OVLTAB__.entries;
#ifdef OVL_WHOOSH
    __OVLDBGINFO__.bitsize = ( number + 7 ) / 8;
#endif
    return( ( ( number + 7 ) / 8 ) + sizeof( unsigned ) + 1 );
}

static int GetSectionData( ovl_addr far * data )
/**********************************************/
{
    unsigned            number;
    unsigned            seg;
    ovltab_entry far *  ovl;

    number = (ovltab_entry far *)&__OVLTABEND__ - __OVLTAB__.entries;
    if( ( data->sect > number ) || ( data->sect <= 0 ) )
        return( 0 );
    ovl = &__OVLTAB__.entries[data->sect - 1];
    data->sect = ovl->num_paras;
#ifdef OVL_WHOOSH
    seg = __OVLTAB__.prolog.delta + __OVLSTARTPARA__;
#else
    seg = ovl->code_handle;
#endif
    data->addr = MK_FP( seg, 0 );
    return( 1 );
}

static int SaveOvlState( char far * data )
/****************************************/
// this fills a bit array with the status of the overlays
// 1 means overlay in memory, 0 means overlay on disk
{
    ovltab_entry far *  ovl;
    unsigned char       mask;
    unsigned char       loaded;
    char far *          savedata;

    savedata = data;
    mask = 1;
    loaded = 0;
    ovl = &__OVLTAB__.entries;
    while( FP_OFF( ovl ) != FP_OFF( &__OVLTABEND__ ) ) {
        if( ovl->flags_anc & FLAG_INMEM ) {
            loaded |= mask;
        }
        *data = loaded;
        if( mask == 0x80 ) {
            mask = 1;
            loaded = 0;
            ++data;
        } else {
            mask <<= 1;
        }
        ovl++;
    }
    if( mask != 1 )
        ++data;
#ifndef OVL_WHOOSH
    *(unsigned *)data = __BankStack__;
#else
    *data = 1;
    if( __OVLFLAGS__ & DBGAREA_VALID ) {
        savedata += ( __OVLDBGINFO__.section - 1 ) / 8;
        *savedata |= 1 << ( __OVLDBGINFO__.section - 1 ) % 8;
    }
#endif
    return( TRUE );
}

static int RestoreOvlState( char far * data )
/*******************************************/
// set the overlay state to match the given vector.
{
    ovltab_entry far *  ovl;
    unsigned char       mask;
    int                 ovlnum;
#ifdef OVL_WHOOSH
    unsigned            flags_save;
    unsigned            code_save;
    unsigned_16         start_save;

/* If we want to load a section for the debugger to look at, do it in a special
 * area so it doesn't cause the overlay loader to go tracing through the
 * debugger stack. (or run out of memory) */
    if( *( data + __OVLDBGINFO__.bitsize ) == 0 ) {
        ovlnum = 1;
        while( *data == 0 ) {
            ovlnum += 8;
            data++;
        }
        mask = *data >> 1;
        while( mask != 0 ) {
            mask >>= 1;
            ovlnum++;
        }
        ovl = &__OVLTAB__.entries[ ovlnum - 1 ];
        if( !( ovl->flags_anc & FLAG_INMEM ) ) {
            if( ( __OVLFLAGS__ & DBGAREA_VALID )
                && ( __OVLDBGINFO__.section != ovlnum ) ) {
                __OVLTAB__.entries[__OVLDBGINFO__.section - 1].flags_anc
                                                             |= FLAG_CHANGED;
            }
            __OVLDBGINFO__.section = ovlnum;
            code_save = ovl->code_handle;
            flags_save = ovl->flags_anc;
            start_save = ovl->start_para;
            ovl->code_handle = __OVLDBGINFO__.location;
            ovl->start_para = __OVLSTARTPARA__;
            __LoadSectionCode__( ovl );
            ovl->code_handle = code_save;
            ovl->flags_anc = flags_save | FLAG_CHANGED;
            ovl->start_para = start_save;
            __OVLFLAGS__ |= DBGAREA_LOADED | DBGAREA_VALID;
        }
        return( TRUE );
    }
#endif
    ovlnum = 1;
    mask = 1;
    ovl = &__OVLTAB__.entries;
    while( FP_OFF( ovl ) != FP_OFF( &__OVLTABEND__ ) ) {
#ifndef OVL_WHOOSH
        if( !( ovl->flags_anc & FLAG_INMEM ) && ( *data & mask ) ) {
            NAME( LoadOverlay )( ovlnum );
        }
#else
        if( ( ( ovl->flags_anc & FLAG_INMEM ) == 0 ) !=
                                                ( ( *data & mask ) == 0 ) ) {
            /* our overlay state doesn't match the one given to us... so
               we tell the debugger to forget it. */
            return( FALSE );
        }
#endif
        if( mask == 0x80 ) {
            mask = 1;
            ++data;
        } else {
            mask <<= 1;
        }
        ++ovlnum;
        ++ovl;
    }
#ifndef OVL_WHOOSH
    if( mask != 1 )
        ++data;
    if( *(unsigned *)data != 0 )
        __BankStack__ = *(unsigned *)data;
#else
    __OVLFLAGS__ &= ~DBGAREA_VALID;
#endif
    return( TRUE );
}

static int CheckVecAddr( ovl_addr far * data )
/**********************************************/
// check if the address stored in data is a vector, returning TRUE if it is.
{
    char far *      address;
    vector far *    vect;
    unsigned        addr;
#ifdef OVL_WHOOSH
    ovltab_entry *  ovl;
#endif

    address = data->addr;
    if( FP_SEG( address ) != FP_SEG( &__OVLSTARTVEC__ ) )
        return( FALSE );
    addr = FP_OFF( address );
    if( addr < FP_OFF( &__OVLSTARTVEC__ ) )
        return( FALSE );
    if( addr >= FP_OFF( &__OVLENDVEC__ ) )
        return( FALSE );
    addr -= FP_OFF( &__OVLSTARTVEC__ );
    if( addr % sizeof( vector ) != 0 )
        return( FALSE );
    vect = (vector *)address;
#ifdef OVL_SMALL
    data->addr = MK_FP( FP_SEG( address ), vect->target + (unsigned)&vect->target + 2 );
    data->sect = vect->sec_num;
#elif defined( OVL_WHOOSH )
    if( vect->u.i.cs_over == OVV_CS_OVERRIDE ) {
        data->sect = ( vect->u.i.tab_addr - FP_OFF( __OVLTAB__.entries ) )
                                                    / sizeof( ovltab_entry ) + 1;
        data->addr = MK_FP( vect->target.seg, vect->target.off );
    } else {
        data->sect = vect->u.v.sec_num;
        ovl = &__OVLTAB__.entries[ vect->u.v.sec_num - 1 ];
        if( ( __OVLFLAGS__ & DBGAREA_VALID )
                         && ( data->sect == __OVLDBGINFO__.section ) ) {
            addr = __OVLDBGINFO__.location;
        } else if( ovl->flags_anc & FLAG_DBG_SECT_LOAD ) {
            addr = __OVLDBGINFO__.location;
        } else if( ovl->flags_anc & FLAG_RET_TRAP ) {
            ret_trap_ptr        rt;

            rt = MK_FP( ovl->code_handle, 0 );
            addr = rt->old_code_handle;
        } else if( ovl->code_handle != 0 ) {
            addr = ovl->code_handle;
        } else {
            addr = __OVLSTARTPARA__ + __OVLTAB__.prolog.delta;
        }
        data->addr = MK_FP( addr, vect->target.off );
    }
#else
    data->addr = MK_FP( vect->target.seg, vect->target.off );
    data->sect = vect->u.v.sec_num;
#endif
    return( TRUE );
}

#ifdef OVL_WHOOSH

static int GetChangedSections( ovl_addr far *data )
/*************************************************/
/* return TRUE if a section changed. return the section number and the new
 * segment in that memory pointed to by data */
{
    ovltab_entry *  ovl;
    unsigned        ovl_num;

     if( ( __OVLFLAGS__ & DBGAREA_LOADED )
         && ( __OVLFLAGS__ & DBGAREA_VALID ) ) {
        ovl_num = __OVLDBGINFO__.section;
        if( ovl_num == data->sect ) {
            __OVLFLAGS__ &= ~DBGAREA_LOADED;
            data->sect = 0;
        } else {
            data->sect = ovl_num;
            data->addr = MK_FP( __OVLDBGINFO__.location, 0 );
            __OVLTAB__.entries[ovl_num - 1].flags_anc &= ~FLAG_CHANGED;
            __OVLTAB__.entries[ovl_num - 1].flags_anc |= FLAG_DBG_SECT_LOAD;
            return( TRUE );
        }
    }
    ovl_num = data->sect + 1;
    ovl = &__OVLTAB__.entries[ ovl_num - 1 ];
    while( FP_OFF( ovl ) != FP_OFF( &__OVLTABEND__ ) ) {
        if( ovl->flags_anc & FLAG_CHANGED ) {
            ovl->flags_anc &= ~( FLAG_CHANGED | FLAG_DBG_SECT_LOAD );
            data->sect = ovl_num;
            if( ovl->flags_anc & FLAG_RET_TRAP ) {
                ret_trap_ptr    rt;

                rt = MK_FP( ovl->code_handle, 0 );
                data->addr = MK_FP( rt->old_code_handle, 0 );
                return( TRUE );
            }
            data->addr = MK_FP( ovl->code_handle, 0 );
            return( TRUE );
        }
        ++ovl;
        ++ovl_num;
    }
    return( FALSE );
}

unsigned near __OVLMAXSECT__( void )
/***********************************/
// This returns the size of the largest overlay section.
{
    ovltab_entry far *  ovl;
    unsigned            max;

    max = 0;
    ovl = &__OVLTAB__.entries;
    while( FP_OFF( ovl ) != FP_OFF( &__OVLTABEND__ ) ) {
        if( ovl->num_paras > max ) {
            max = ovl->num_paras;
        }
        ++ovl;
    }
    return( max );
}
#endif

int far GNAME( DBG_HANDLER )( int service, void far *data )
/*********************************************************/
{
    int ret;

    ret = FALSE;
    switch( service ) {
    case OVLDBG_GET_OVERLAY_STATE:
        ret = SaveOvlState( data );
        break;
    case OVLDBG_SET_OVERLAY_STATE:
        ret = RestoreOvlState( data );
        break;
    case OVLDBG_TRANSLATE_VECTOR_ADDR:
        ret = CheckVecAddr( data );
        break;
    case OVLDBG_GET_STATE_SIZE:
        ret = GetSizeOverlays();
        break;
    case OVLDBG_TRANSLATE_RETURN_ADDR:
        ret = GNAME( CheckRetAddr )( data );
        break;
    case OVLDBG_GET_OVL_TBL_ADDR:
        *(void far *far *)data = &__OVLTAB__;
        break;
#ifdef OVL_WHOOSH
    case OVLDBG_GET_MOVED_SECTION:
        ret = GetChangedSections( data );
        break;
#endif
    case OVLDBG_GET_SECTION_DATA:
        ret = GetSectionData( data );
        break;
    }
    return( ret );
}

⌨️ 快捷键说明

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