watlcl.c

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

C
979
字号
/****************************************************************************
*
*                            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:  Locals processing for Watcom style debugging information.
*
****************************************************************************/


#include "dipwat.h"
#include "watlcl.h"
#include <string.h>

extern void             *InfoLoad(imp_image_handle *, imp_mod_handle, unsigned, unsigned, void (*)() );
extern void             InfoSpecUnlock( void * );
extern unsigned int     InfoSize(imp_image_handle *,imp_mod_handle,unsigned, unsigned );
extern address          FindModBase(imp_image_handle *, imp_mod_handle);
extern void             AddressMap( imp_image_handle *, addr_ptr * );
extern section_info     *FindInfo( imp_image_handle *, imp_mod_handle );
extern byte             *SkipLocation( loc_expr );
extern dip_status       EvalLocation( imp_image_handle *, location_context *, loc_expr, location_list * );
extern walk_result      WalkTypeSymList( imp_image_handle *, imp_type_handle *, IMP_SYM_WKR *, imp_sym_handle *, void * );
extern dip_status       FindTypeHandle( imp_image_handle *, imp_mod_handle, unsigned, imp_type_handle * );
extern search_result    LookupTypeName( imp_image_handle *, imp_mod_handle, lookup_item *, imp_type_handle * );
extern search_result    SearchMbr( imp_image_handle *, imp_type_handle *, lookup_item *, void * );
extern void             LocationCreate( location_list *, location_type, void * );
extern search_result    LookupGblAddr( imp_image_handle *, address, imp_sym_handle * );
extern dip_status       SymHdl2GblInfo( imp_image_handle *, imp_sym_handle *, sym_info * );
extern dip_status       Link2GblHdl( imp_image_handle *, void *, imp_sym_handle * );
extern unsigned         RegSize( unsigned );


extern address          NilAddr;

typedef struct lclinfo {
    section_info        *inf;
    byte                *start;
    byte                *end;
    unsigned            base_off;
    address             code_base;
    imp_mod_handle      im;
} lclinfo;

#define NO_BASE ((unsigned short)-1)

byte *GetIndex( byte *ptr, unsigned *value )
{
    unsigned tmp;

    tmp = *ptr++;
    if ( tmp & 0x80 ) {
        tmp = (tmp & 0x7f) << 8;
        tmp += *ptr++;
    }
    *value = tmp;
    return( ptr );
}

static byte *GetMachAddr( imp_image_handle *ii, byte *ptr, addr_ptr *addr,
                        int is32 )
{
    if( is32 ) {
        *addr = *(addr48_ptr *)ptr;
        ptr += sizeof( addr48_ptr );
    } else {
        ConvAddr32ToAddr48( *(addr32_ptr *)ptr, *addr );
        ptr += sizeof( addr32_ptr );
    }
    AddressMap( ii, addr );
    return( ptr );
}


byte *GetAddress( imp_image_handle *ii, byte *ptr, address *addr, int is32 )
{
    ptr = GetMachAddr( ii, ptr, &addr->mach, is32 );
    DCAddrSection( addr );
    return( ptr );
}

static void LclCreate( imp_sym_handle *is, byte *ptr, byte *name, lclinfo *local )
{
    is->type = SH_LCL;
    is->im = local->im;
    is->u.lcl.base = local->base_off;
    is->u.lcl.offset = ptr - local->start;
    is->u.lcl.gbl_link = NULL;
    is->name_off = name - ptr;
}

/*
 * LoadLocalSyms -- load the local symbol information for the module
 */

static dip_status LoadLocalSyms( imp_image_handle *ii, imp_mod_handle im,
                                        lclinfo *new )
{
    if( im == (imp_mod_handle)NO_MOD ) return( DS_FAIL );
    new->start = InfoLoad( ii, im, DMND_LOCALS, 0, NULL );
    if( new->start == NULL ) {
        return( DS_FAIL );
    }
    new->end = new->start + InfoSize( ii, im, DMND_LOCALS, 0 );
    new->im = im;
    new->inf = FindInfo( ii, im );
    new->base_off = NO_BASE;
    return( DS_OK );
}

static void PopLoad( lclinfo *local )
{
    if( local->start != NULL ) {
        InfoSpecUnlock( local->start );
    }
}

void KillLclLoadStack( void )
{
    // Nothing to do - not using globals anymore
}

/*
 * ProcBlock -- process a block definition
 */
static byte *ProcBlock( byte *ptr, lcl_defn *defn, lclinfo *local )
{
    if( local->base_off == NO_BASE ) {
        defn->b.start = FindModBase( local->inf->ctl, local->im );
    } else {
        defn->b.start = local->code_base;
    }
    if( defn->i.class >= (CODE_SYMBOL + CODE_BLOCK386) ) {
        defn->b.start.mach.offset += *((dword *) ptr);
        ptr += sizeof( dword );
        defn->b.size = *((dword *) ptr);
        ptr += sizeof( dword );
    } else {
        defn->b.start.mach.offset += *((word *) ptr);
        ptr += sizeof( word );
        defn->b.size = *((word *) ptr);
        ptr += sizeof( word );
    }
    defn->b.parent_block = *((word *) ptr);
    ptr += sizeof( word );
    return( ptr );
}


/*
 * ProcDefn -- process the next definition in the local symbol information
 */
static byte *ProcDefn( byte *ptr, lcl_defn *defn, lclinfo *local )
{
    byte        *end;
    int         parms;

    end = ptr + *ptr;
    ptr++;
    defn->i.class = *ptr++;
    defn->i.unparsed = ptr;
    switch( defn->i.class ) {
    case VAR_SYMBOL | VAR_MODULE386:
        ptr += sizeof( addr48_ptr );
        ptr = GetIndex( ptr, &defn->i.type_index );
        break;
    case VAR_SYMBOL | VAR_MODULE :
        ptr += sizeof( addr32_ptr );
        ptr = GetIndex( ptr, &defn->i.type_index );
        break;
    case VAR_SYMBOL | VAR_MODULE_LOC:
    case VAR_SYMBOL | VAR_LOCAL :
        ptr = SkipLocation( ptr );
        ptr = GetIndex( ptr, &defn->i.type_index );
        break;
    case CODE_SYMBOL | CODE_BLOCK386:
    case CODE_SYMBOL | CODE_BLOCK :
        ptr = ProcBlock( ptr, defn, local );
        break;
    case CODE_SYMBOL | CODE_NEAR_ROUT386:
    case CODE_SYMBOL | CODE_FAR_ROUT386:
    case CODE_SYMBOL | CODE_NEAR_ROUT :
    case CODE_SYMBOL | CODE_FAR_ROUT :
        ptr = ProcBlock( ptr, defn, local );
        defn->r.pro_size = *ptr++;
        defn->r.epi_size = *ptr++;
        if( defn->i.class >= (CODE_SYMBOL + CODE_BLOCK386) ) {
            defn->r.ret_addr_offset = *((dword *) ptr);
            ptr += sizeof( dword );
        } else {
            defn->r.ret_addr_offset = *((word *) ptr);
            ptr += sizeof( word );
        }
        ptr = GetIndex( ptr, &defn->i.type_index );
        defn->i.unparsed = ptr;
        ptr = SkipLocation( ptr );
        for( parms = *ptr++; parms != 0; --parms ) {
            ptr = SkipLocation( ptr );
        }
        break;
    case CODE_SYMBOL | CODE_MEMBER_SCOPE:
        defn->b.parent_block = *((word *) ptr);
        ptr += sizeof( word );
        ptr = GetIndex( ptr, &defn->i.type_index );
        if( ptr < end ) {
            defn->i.unparsed = ptr;
            /* skip the 'this' pointer type and the object loc expr */
            ptr = SkipLocation( ptr + 1 );
        } else {
            defn->i.unparsed = NULL;
        }
        break;
    }
    defn->i.name = ptr;
    defn->i.namelen = end - ptr;
    return( end );
}

static void NewBase( byte *ptr, lclinfo *local )
{
    ptr += 1;
    if( (ptr[0] & CLASS_MASK) == NEW_BASE ) {
        local->base_off = ptr - local->start - 1;
        local->code_base.sect_id = local->inf->sect_id;
        local->code_base.indirect = 1;
        switch( ptr[0] & SUBCLASS_MASK ) {
        case ADD_PREV_SEG:
            ptr += 1;
            local->code_base.mach.segment += *((word *) ptr);
            local->code_base.mach.offset = 0;
            break;
        case SET_BASE386:
            GetMachAddr( local->inf->ctl, ptr+1, &local->code_base.mach, 1 );
            break;
        case SET_BASE:
            GetMachAddr( local->inf->ctl, ptr+1, &local->code_base.mach, 0 );
            break;
        }
    }
}

static byte *FindBlockRout( byte *ptr, lclinfo *local )
{
    byte        cls;

    while( ptr < local->end ) {
        cls = ptr[1];
        if( (cls & CLASS_MASK) == CODE_SYMBOL &&
             cls != (CODE_SYMBOL | CODE_MEMBER_SCOPE) )  {
            return( ptr );
        }
        NewBase( ptr, local );
        ptr += *ptr;
    }
    return( NULL );
}

static byte *ModAddrLkupVar( byte *ptr, lclinfo *local )
{
    while( ptr < local->end ) {
        switch( ptr[1] ) {
        case VAR_SYMBOL | VAR_MODULE:
        case VAR_SYMBOL | VAR_MODULE386:
        case CODE_SYMBOL | CODE_NEAR_ROUT:
        case CODE_SYMBOL | CODE_FAR_ROUT:
        case CODE_SYMBOL | CODE_NEAR_ROUT386:
        case CODE_SYMBOL | CODE_FAR_ROUT386:
            return( ptr );
        }
        NewBase( ptr, local );
        ptr += *ptr;
    }
    return( NULL );
}

static byte *FindLclVar( byte *ptr, lclinfo *local )
{
    while( ptr < local->end ) {
        if( (*(ptr+1) & CLASS_MASK) == CODE_SYMBOL ) break;
        if( *(ptr+1) == (VAR_SYMBOL | VAR_LOCAL) ) return( ptr );
        NewBase( ptr, local );
        ptr += *ptr;
    }
    return( NULL );
}


static dip_status DefnLocation( lcl_defn *defn, location_context *lc,
                                location_list *ll, lclinfo *local )
{
    address     addr;

    switch( defn->i.class ) {
    case VAR_SYMBOL | VAR_MODULE386:
        GetAddress( local->inf->ctl, defn->i.unparsed, &addr, 1 );
        LocationCreate( ll, LT_ADDR, &addr );
        break;
    case VAR_SYMBOL | VAR_MODULE:
        GetAddress( local->inf->ctl, defn->i.unparsed, &addr, 0 );
        LocationCreate( ll, LT_ADDR, &addr );
        break;
    case VAR_SYMBOL | VAR_LOCAL:
    case VAR_SYMBOL | VAR_MODULE_LOC:
        return( EvalLocation( local->inf->ctl, lc, defn->i.unparsed, ll ) );
    default:
        LocationCreate( ll, LT_ADDR, &defn->b.start );

⌨️ 快捷键说明

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