hlltype.c

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

C
2,019
字号
/****************************************************************************
*
*                            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:  HLL/CV debugging type support.
*
****************************************************************************/


#include <stddef.h>
#include <string.h>
#include "walloca.h"
#include "hllinfo.h"


#define UNKNOWN_TYPE_IDX        ((unsigned short)-1)
#define PT_REALLY_CHAR          0x0070

static dip_status ImpTypeArrayInfo( imp_image_handle *ii,
                        imp_type_handle *array, location_context *lc,
                        array_info *ai, imp_type_handle *index );
extern dip_status ImpTypeInfo( imp_image_handle *ii, imp_type_handle *it,
                        location_context *lc, type_info *ti );


static dip_status TypeVMGetName( imp_image_handle *ii, virt_mem base,
                        char **namep, unsigned *lenp, lf_all **pp )
{
    lf_all              *p;
    unsigned            skip;
    char                *name;
    numeric_leaf        dummy;

    if( base == 0 ) {
        *namep = NULL;
        *lenp = 0;
        return( DS_OK );
    }
    /*
       The "+ sizeof( unsigned_32 )" is to make sure that the GetNumLeaf's
       have enough stuff mapped in to work.
    */
    p = VMBlock( ii, base, sizeof( *p ) + sizeof( unsigned_32 ) );
    if( p == NULL ) return( DS_ERR | DS_FAIL );
    switch( p->common.code ) {
    case LF_ARRAY:
        skip = sizeof( lf_array );
        break;
    case LF_CLASS:
    case LF_STRUCTURE:
        name = GetNumLeaf( &p->class_ + 1, &dummy );
        skip = name - (char *)p;
        break;
    case LF_UNION:
        name = GetNumLeaf( &p->union_ + 1, &dummy );
        skip = name - (char *)p;
        break;
    case LF_ENUM:
        skip = sizeof( lf_enum );
        break;
    case LF_ENUMERATE:
        name = GetNumLeaf( &p->enumerate + 1, &dummy );
        skip = name - (char *)p;
        break;
    case LF_FRIENDFCN:
        skip = sizeof( lf_friendfcn );
        break;
    case LF_MEMBER:
        name = GetNumLeaf( &p->member + 1, &dummy );
        skip = name - (char *)p;
        break;
    case LF_STMEMBER:
        skip = sizeof( lf_stmember );
        break;
    case LF_METHOD:
        skip = sizeof( lf_method );
        break;
    case LF_NESTEDTYPE:
        skip = sizeof( lf_nestedtype );
        break;
    case LF_ONEMETHOD:
        skip = sizeof( lf_onemethod );
        switch( p->onemethod.f.attr.f.mprop ) {
        case CV_VIRTUAL:
        case CV_INTROVIRT:
        case CV_PUREVIRT:
        case CV_PUREINTROVIRT:
            skip += sizeof( unsigned_32 );
            break;
        }
        break;
    default:
        *namep = NULL;
        *lenp = 0;
        return( DS_OK );
    }
    /* A name can't be longer than 255 bytes */
    p = VMBlock( ii, base, 256 + skip );
    if( p == NULL ) return( DS_ERR | DS_FAIL );
    name = (unsigned_8 *)p + skip;
    *lenp = name[0];
    *namep = &name[1];
    if( pp != NULL ) *pp = p;
    return( DS_OK );
}

static virt_mem TypeIndexVM( imp_image_handle *ii, unsigned idx )
{
    cv_directory_entry  *cde;
    unsigned_32         *p;

    if( idx < CV_FIRST_USER_TYPE ) return( 0 );
    cde = FindDirEntry( ii, MH_GBL, sstGlobalTypes );
    if( cde == NULL ) return( 0 );
    p = VMBlock( ii,
        cde->lfo
           + (unsigned long)(idx - CV_FIRST_USER_TYPE) * sizeof( *p )
           + offsetof( cv_sst_global_types_header, offType ),
        sizeof( *p ) );
    if( p == NULL ) return( 0 );
    return( *p + ii->types_base );
}

dip_status TypeIndexFillIn( imp_image_handle *ii, unsigned idx,
                        imp_type_handle *it )
{
    it->array_dim = 0;
    it->idx = idx;
    if( idx < CV_FIRST_USER_TYPE ) {
        it->handle = 0;
        return( DS_OK );
    }
    it->handle = TypeIndexVM( ii, idx );
    if( it->handle == 0 ) return( DS_ERR | DS_FAIL );
    it->handle += sizeof( unsigned_16 );
    return( DS_OK );
}

static dip_status TypeReal( imp_image_handle *ii,
                                imp_type_handle *in, imp_type_handle *out,
                                lf_all **pp )
{
    lf_all      *p;

    *out = *in;
    p = NULL;
    for( ;; ) {
        if( out->handle == 0 ) goto done;
        p = VMBlock( ii, out->handle, sizeof( *p ) );
        if( p == NULL ) return( DS_ERR | DS_FAIL );
        switch( p->common.code ) {
        case LF_MODIFIER:
            if( TypeIndexFillIn( ii, p->modifier.f.index, out ) != DS_OK ) {
                return( DS_ERR | DS_FAIL );
            }
            break;
        default:
            goto done;
        }
    }
done:
    if( pp != NULL ) *pp = p;
    return( DS_OK );
}

dip_status TypeCallInfo( imp_image_handle *ii, unsigned idx,
                        cv_calls *call_type, unsigned *parms )
{
    lf_all              *p;
    dip_status          ds;
    imp_type_handle     it;

    ds = TypeIndexFillIn( ii, idx, &it );
    if( ds != DS_OK ) return( ds );
    ds = TypeReal( ii, &it, &it, &p );
    if( ds != DS_OK ) return( ds );
    switch( p->common.code ) {
    case LF_PROCEDURE:
        *call_type = p->procedure.f.call;
        *parms = p->procedure.f.parms;
        break;
    case LF_MFUNCTION:
        *call_type = p->mfunction.f.call;
        *parms = p->mfunction.f.parms;
        break;
    default:
        return( DS_FAIL );
    }
    return( DS_OK );
}

dip_status TypeMemberFuncInfo( imp_image_handle *ii, imp_type_handle *func_it,
        imp_type_handle *class_it, imp_type_handle *this_it,
        unsigned long *adjustp )
{
    lf_all      *p;
    dip_status  ds;
    unsigned    class_idx;

    p = VMBlock( ii, func_it->handle, sizeof( *p ) );
    if( p == NULL ) return( DS_ERR | DS_FAIL );
    if( p->common.code != LF_MFUNCTION ) return( DS_FAIL );
    if( adjustp != NULL ) {
        *adjustp = p->mfunction.f.thisadjust;
    }
    class_idx = p->mfunction.f.class_idx;
    if( this_it != NULL ) {
        ds = TypeIndexFillIn( ii, p->mfunction.f.thisptr, this_it );
        if( ds != DS_OK ) return( ds );
    }
    if( class_it != NULL ) {
        ds = TypeIndexFillIn( ii, class_idx, class_it );
        p = VMBlock( ii, class_it->handle, sizeof( *p ) );
        if( p->common.code == LF_MODIFIER ){ //NON standard need it to handle forward refs
            ds = TypeIndexFillIn( ii, p->modifier.f.index, class_it );
        }
        if( ds != DS_OK ) return( ds );
    }
    return( DS_OK );
}

dip_status TypeSymGetName( imp_image_handle *ii, imp_sym_handle *is,
                        char **namep, unsigned *lenp )
{
    return( TypeVMGetName( ii, is->handle, namep, lenp, NULL ) );
}


typedef struct pending_type_list pending_type_list;
struct pending_type_list {
    pending_type_list   *prev;
    virt_mem            curr;
    virt_mem            end;
    virt_mem            containing_type;
    unsigned            len;
    unsigned            code;
};

typedef walk_result (LEAF_WALKER)( imp_image_handle *, sym_walk_info, pending_type_list *, lf_all *, void * );

static walk_result TypeListWalk( imp_image_handle *ii, virt_mem head,
                        virt_mem containing_type, LEAF_WALKER *wk, void *d )
{
    lf_all              *p;
    unsigned_16         *len_p;
    unsigned            len;
    walk_result         wr;
    numeric_leaf        val;
    void                *ptr;
    pending_type_list   *list;
    pending_type_list   *free_list;
    pending_type_list   *tmp;
    unsigned            base_idx;

    free_list = NULL;
    list = __alloca( sizeof( *list ) );
    list->prev = NULL;
    list->curr = head;
    list->containing_type = containing_type;
new_list:
    if( list->curr == 0 ) return( WR_FAIL );
    len_p = VMBlock( ii, list->curr, sizeof( *len_p ) );
    if( len_p == NULL ) return( WR_FAIL );
    list->curr += sizeof( *len_p );
    list->end = list->curr + *len_p;
    list->curr += sizeof( p->common.code ); /* skip the list introducer */
    for( ;; ) {
        while( list->curr >= list->end ) {
            tmp = list;
            list = list->prev;
            if( list == NULL ) return( WR_CONTINUE );
            wr = wk( ii, SWI_INHERIT_END, list, NULL, d );
            if( wr != WR_CONTINUE ) return( wr );
            tmp->prev = free_list;
            free_list = tmp;
            list->curr += list->len;
        }
        p = VMBlock( ii, list->curr, sizeof( *p ) + sizeof( unsigned_32 ) );
        if( p == NULL ) return( WR_FAIL );
        if( *(unsigned_8 *)p > LF_PAD0 ) {
            list->curr += *(unsigned_8 *)p & 0x0f;
        } else {
            list->code = p->common.code;
            switch( p->common.code ){
            case LF_INDEX:
                list->curr = TypeIndexVM( ii, p->index.f.index );
                goto new_list;
            case LF_BCLASS:
                len = (unsigned_8 *)GetNumLeaf( &p->bclass + 1, &val ) - (unsigned_8 *)p;
                base_idx = p->bclass.f.type;
                goto inherit_class;
            case LF_VBCLASS:
            case LF_IVBCLASS:
                len = (unsigned_8 *)GetNumLeaf( &p->vbclass + 1, &val ) - (unsigned_8 *)p;
                ptr = VMBlock( ii, list->curr + len, sizeof( unsigned_32 ) );
                len += (unsigned_8 *)GetNumLeaf( ptr, &val ) - (unsigned_8 *)ptr;
                if( list->prev != NULL ) {
                    /*
                       If we're processing an inherited class, we want to
                       ignore any virtual base classes. They'll get handled
                       by the most derived class.
                    */
                    list->curr += len;
                    continue;
                }
                base_idx = p->vbclass.f.btype;
inherit_class:
                list->len = len;
                wr = wk( ii, SWI_INHERIT_START, list, NULL, d );
                if( wr == WR_STOP ) {
                    list->curr += list->len;
                    continue;
                }
                if( free_list == NULL ) {
                    free_list = __alloca( sizeof( *list ) );
                    free_list->prev = NULL;
                }
                tmp = free_list;
                free_list = free_list->prev;
                tmp->prev = list;
                list = tmp;
                list->containing_type = TypeIndexVM( ii, base_idx );
                if( list->containing_type == 0 ) return( WR_FAIL );
                p = VMBlock( ii, list->containing_type+sizeof( unsigned_16 ),
                                        sizeof( *p ) );
                if( p == NULL ) return( WR_FAIL );
                switch( p->common.code ) {
                case LF_CLASS:
                case LF_STRUCTURE:
                    list->curr = TypeIndexVM( ii, p->class_.f.field );
                    break;
                default:
                    Confused();
                }
                goto new_list;
            case LF_ENUMERATE:
                len = (unsigned_8 *)GetNumLeaf( &p->enumerate + 1, &val ) - (unsigned_8 *)p;
                ptr = VMBlock( ii, list->curr + len, 1 );
                len += *(unsigned_8 *)ptr + 1;
                break;
            case LF_FRIENDFCN:
                len = *(unsigned_8 *)(&p->friendfcn + 1) + sizeof( p->friendfcn ) + 1;
                break;
            case LF_MEMBER:
                len = (unsigned_8 *)GetNumLeaf( &p->member + 1, &val ) - (unsigned_8 *)p;
                ptr = VMBlock( ii, list->curr + len, 1 );
                len += *(unsigned_8 *)ptr + 1;
                break;
            case LF_STMEMBER:
                len = *(unsigned_8 *)(&p->stmember + 1) + sizeof( p->stmember ) + 1;
                break;
            case LF_METHOD:
                len = *(unsigned_8 *)(&p->method + 1) + sizeof( p->method ) + 1;
                break;
            case LF_NESTEDTYPE:
                len = *(unsigned_8 *)(&p->nestedtype + 1) + sizeof( p->nestedtype ) + 1;
                break;
            case LF_VFUNCTAB:
                len = sizeof( p->vfunctab );
                break;
            case LF_FRIENDCLS:
                len = sizeof( p->friendcls );
                break;
            case LF_ONEMETHOD:
                len = *(unsigned_8 *)(&p->onemethod + 1) + sizeof( p->onemethod ) + 1;
                switch( p->onemethod.f.attr.f.mprop ) {
                case CV_VIRTUAL:
                case CV_INTROVIRT:
                case CV_PUREVIRT:
                case CV_PUREINTROVIRT:
                    len += sizeof( unsigned_32 );
                    break;
                }
                break;
            case LF_VFUNCOFF:
                len = sizeof( p->vfuncoff );
                break;
            default:
                Confused();
                return( WR_FAIL );
            }
            p = VMBlock( ii, list->curr, len );

⌨️ 快捷键说明

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