dfsym.c

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

C
1,799
字号
/**********************************************************************/
{
    /* Get some generic information about a symbol. */
    uint_32         num1;
    uint_32         num2;
    dr_ptr          addr_class;

    lc = lc;
    DRSetDebug( ii->dwarf->handle );    /* must do at each call into DWARF */
    if( is->state == DF_NOT ) {
        DRSetDebug( ii->dwarf->handle ); /* must do at each interface */
        is->stype = DRGetTagType( is->sym );
        is->acc   = DRGetAccess( is->sym );
        is->isstatic = DRIsStatic( is->sym );
        is->isartificial = DRIsArtificial( is->sym );
        is->state = DF_SET;
    }
    switch( is->stype ) {
    case DR_TAG_FUNCTION:
        if( is->sclass == SYM_MEMF || is->sclass == SYM_VIRTF ) {
            si->kind = SK_CODE;     /* member functions */
        } else {
            si->kind = SK_PROCEDURE;
            if( DRStartScopeAT( is->sym, &num1 ) ) {
                si->prolog_size  = num1;
            } else {
                si->prolog_size  = 0;
            }
            if( !DRGetLowPc( is->sym, &num1 ) ) {
                num1 = 0;
            }
            if( !DRGetHighPc( is->sym, &num2 ) ) {
                num2 = num1;
            }
            si->rtn_size = num2 - num1;
            si->num_parms = GetParmCount( ii, is->sym );
            si->ret_size = 0;
            si->ret_modifier = TM_NONE;
            si->epilog_size = 0;
            si->rtn_calloc  = 0;
            if( EvalOffset( ii, is->sym, &num1 ) )
                si->ret_addr_offset = num1;
            else
                si->ret_addr_offset = ~0;
            addr_class =  DRGetAddrClass( is->sym );
            switch( addr_class ) {
            case DR_PTR_far32:
            case DR_PTR_far16:
                si->rtn_far = 1;
                break;
            default:
                si->rtn_far = 0;
            }
        }
        break;
    case DR_TAG_CLASS:
    case DR_TAG_ENUM:
    case DR_TAG_TYPEDEF:
        si->kind = SK_TYPE;
        break;
    case DR_TAG_VARIABLE:
        si->kind = SK_DATA;
        break;
    case DR_TAG_LABEL:
        si->kind = SK_CODE;
        break;
    case DR_TAG_NAMESPACE:
        si->kind = SK_NAMESPACE;
        break;
    default:
        si->kind = SK_NONE;
        break;
    }
    si->is_private = 0;
    si->is_protected = 0;
    si->is_public = 0;
    switch( is->acc ) {
    case DR_ACCESS_PUBLIC:
        si->is_public = 1;
        break;
    case DR_ACCESS_PROTECTED:
        si->is_protected = 1;
        break;
    case DR_ACCESS_PRIVATE:
        si->is_private = 1;
        break;
    }
    si->compiler = is->isartificial;
    if( is->isstatic ) {
        si->global = 0;
    } else {
        si->global = 1;
    }
    switch( is->sclass ) {
    case SYM_MEMVAR:
        si->member = 1;
        si->is_static = 1;
        break;
    case SYM_MEM:
    case SYM_MEMF:
    case SYM_VIRTF:
        si->member = 1;
        si->is_static = 0;
        break;
    default:
        si->member = 0;
        si->is_static = 0;
    }
    return( DS_OK );
}


static int ARet( dr_handle var, int index, void *_var_ptr )
/*********************************************************/
{
    dr_handle   *var_ptr = _var_ptr;
    char        name[sizeof( ".return" )];
    int         cont;
    int         len;

    index = index;
    cont = TRUE;
    if( DRIsArtificial( var ) ) {
        len = DRGetNameBuff( var, name, sizeof( ".return" ) );
        if( len == sizeof( ".return" ) ) {
            if( strcmp( name, ".return" ) == 0 ) {
                *var_ptr = var;
                cont = FALSE;
            }
        }
    }
    return( cont );
}


extern dr_handle GetRet(  imp_image_handle *ii, dr_handle proc )
/**************************************************************/
{
    /* Find handle of Watcom return symbol. */
    dr_handle ret;

    DRSetDebug( ii->dwarf->handle );    /* must do at each call into DWARF */
    if( DRWalkBlock( proc, DR_SRCH_var, ARet, &ret ) ) {
        ret = NULL;
    }
    return( ret );
}


dip_status      DIPENTRY DIPImpSymParmLocation( imp_image_handle *ii,
                    imp_sym_handle *is, location_context *lc,
                    location_list *ll, unsigned n )
/*******************************************************************/
{
    /* Get information about where a routine's parameters/return value
     * are located.
     * If the 'n' parameter is zero, fill in the location list structure
     * pointed at by 'll' with the information on the location of the
     * function's return value. Otherwise fill it in with the location
     * of the n'th parameter.
     */
//TODO: brian only wants regs for now
    dr_handle       parm;
    dip_status      ret;

    DRSetDebug( ii->dwarf->handle );    /* must do at each call into DWARF */
    ret = DS_FAIL;
    if( n > 0 ) {
        parm = GetParmN( ii, is->sym, n );
        if( parm != NULL ) {
            ret = EvalParmLocation( ii, lc, parm, ll );
        }
    } else if( n == 0 ) {
        //TODO: get ret location
        parm = GetRet( ii, is->sym );
        if( parm != NULL ) {
            ret = EvalRetLocation( ii, lc, parm, ll );
        }
    }
    return( ret );
}



static int AThis( dr_handle var, int index, void *_var_ptr )
/**********************************************************/
{
    dr_handle   *var_ptr = _var_ptr;
    char        name[sizeof( "this" )];
    int         ret;
    int         len;

    index = index;
    ret = TRUE;
    len =  DRGetNameBuff( var, name, sizeof( "this" ) );
    if( len == sizeof( "this" ) ) {
        if( strcmp( name, "this" ) == 0 ) {
            *var_ptr = var;
            ret = FALSE;
        }
    }
    return( ret );
}


static dr_handle GetThis(  imp_image_handle *ii, dr_handle proc )
/***************************************************************/
{
    /* Return handle of the this parmeter. */
    dr_handle   ret;

    DRSetDebug( ii->dwarf->handle );    /* must do at each call into DWARF */
    if( DRWalkBlock( proc,  DR_SRCH_parm, AThis, &ret ) ) {
        ret = NULL;
    }
    return( ret );
}


dip_status      DIPENTRY DIPImpSymObjType( imp_image_handle *ii,
                    imp_sym_handle *is, imp_type_handle *it, type_info *ti )
/**************************************************************************/
{
    /* Fill in the imp_type_handle with the type of the 'this' object
     * for a C++ member function.
     * If 'ti' is not NULL, fill in the type_info with the kind of 'this'
     * pointer that the routine is expecting (near/far, 16/32). If the
     * routine is a static member, set ti->kind to TK_NONE.
     */
    dr_handle   dr_this;
    dr_handle   dr_type;
    dr_typeinfo typeinfo;
    dip_status  ret;

    dr_this = GetThis( ii, is->sym );
    if( dr_this != NULL ) {
        DRSetDebug( ii->dwarf->handle );    /* must do at each call into DWARF */
        dr_type =  DRGetTypeAT( dr_this );
        if( dr_type != NULL ) {
            DRGetTypeInfo( dr_type, &typeinfo );
            MapImpTypeInfo( &typeinfo, ti );
            dr_type =  DRSkipTypeChain( dr_type );
            it->type = DRGetTypeAT( dr_type );
            it->state = DF_NOT;
            it->imx = is->imx;
            ret = DS_OK;
        } else {
            ret = DS_FAIL;
        }
    } else {
        ti->kind = TK_NONE;
        ret = DS_FAIL;
    }
    return( ret );
}


dip_status      DIPENTRY DIPImpSymObjLocation( imp_image_handle *ii,
                                imp_sym_handle *is, location_context *lc,
                                location_list *ll )
/***********************************************************************/
{
    /* Fill in the location list with the location of the '*this' object
     * for a C++ member function. Return DS_FAIL if it's a static member
     * function.
     */
    dr_handle       dr_this;
    dr_handle       dr_type;
    dr_typeinfo     typeinfo;
    uint_32         seg;
    address         base;   /* base segment & offset */
    location_list   tmp;
    dip_status      ret;
    union{
        addr32_off  n16;
        addr48_off  n32;
        addr32_ptr  f16;
        addr48_ptr  f32;
    } obj_ptr;

    dr_this = GetThis( ii, is->sym );
    if( dr_this != NULL ) {
        if( ii->mod_map[is->imx].is_segment == FALSE ) {
            seg = SEG_DATA; // if flat hoke segment
        } else {
            EvalSeg( ii, is->sym, &seg );
        }
        ret = EvalLocation( ii, lc, dr_this, seg, &tmp );
        if( ret == DS_OK ) {
            dr_type =  DRGetTypeAT( dr_this );
            if( dr_type != NULL ) {
                DRGetTypeInfo( dr_type, &typeinfo );
                LocationCreate( ll, LT_INTERNAL, &obj_ptr );
                ret = DCAssignLocation( ll, &tmp, typeinfo.size );
                if( ret == DS_OK ) {
                    base = NilAddr;
                    switch( typeinfo.modifier.ptr ) {   /* set segment */
                    case DR_PTR_none:
                    case DR_PTR_near16:
                    case DR_PTR_near32:
                        ret = SafeDCItemLocation( lc, CI_DEF_ADDR_SPACE, ll );
                        base = ll->e[0].u.addr; /* set base */
                        break;
                    }
                    switch( typeinfo.modifier.ptr ) {
                    case DR_PTR_none:
                        if( typeinfo.size == 4 ) {
                            base.mach.offset  = obj_ptr.n32;
                        } else {
                            base.mach.offset  = obj_ptr.n16;
                        }
                        break;
                    case DR_PTR_near16:
                        base.mach.offset  = obj_ptr.n16;
                        break;
                    case DR_PTR_near32:
                        base.mach.offset  = obj_ptr.n32;
                        break;
                    case DR_PTR_far16:
                        base.mach.segment = obj_ptr.f16.segment;
                        base.mach.offset  = obj_ptr.f16.offset;
                        break;
                    case DR_PTR_far32:
                        base.mach.segment = obj_ptr.f32.segment;
                        base.mach.offset  = obj_ptr.f32.offset;
                        break;
                    case DR_PTR_huge16:
                        base.mach.segment = obj_ptr.f16.segment;
                        base.mach.offset  = obj_ptr.f16.offset;
                        break;
                    }
                }
                LocationCreate( ll, LT_ADDR, &base );
            }
        }
    } else {
        ret = DS_FAIL;
    }
    return( ret );
}


search_result   DIPENTRY DIPImpAddrSym( imp_image_handle *ii,
                        imp_mod_handle im, address a, imp_sym_handle *is )
/************************************************************************/
{
    /* Search the given module for a symbol who's address is greater than
     * or equal to 'addr'. If none is found return SR_NONE. If you find
     * a symbol at that address exactly, fill in '*is' and return SR_EXACT.
     * Otherwise, fill in '*is' and return SR_CLOSEST.
     */
    im_idx          imx;
    addrsym_info    info;
    search_result   ret;
    seg_list        *addr_sym;

    if( im == 0 ) {
        DCStatus( DS_FAIL );
        return( SR_NONE );
    }
    imx = IM2IMX( im );
    addr_sym = DFLoadAddrSym( ii, imx );
    Real2Map( ii->addr_map, &a );
    if( FindAddrSym( addr_sym, &a.mach, &info ) >= 0 ) {
           is->sclass = SYM_VAR;
           is->imx = imx;
           is->sym = info.sym;
           is->state = DF_NOT;
           if( info.map_offset == a.mach.offset ) {
               ret = SR_EXACT;
           } else {
               ret = SR_CLOSEST;
           }
    } else {
        ret = SR_NONE;
    }
    return( ret );
}

/**********************************/
/* Walk inner and outer blocks   */
/*********************************/

static int InBlk( dr_handle blk, int depth, void *_ctl )
/******************************************************/
{
    scope_ctl       *ctl = _ctl;
    uint_32         lo;
    uint_32         hi;
    scope_node      *new;

    depth = depth;
    lo = 0; //quick fix for labels
    hi = 0;
    DRGetLowPc( blk, &lo );
    DRGetHighPc( blk, &hi );
    new = AddScope( ctl->edge, lo, hi, blk );
    if( ctl->root == NULL ) {
        ctl->root = new;
    }
    ctl->edge = new;
    return( TRUE );
}


static bool IsInScope( scope_ctl  *ctl, address addr )
/****************************************************/
{
    bool            ret;
    scope_node      *root;

    ret = FALSE;
    root = ctl->root;
    if( root != NULL ) {
        if( ctl->base.mach.segment == addr.mach.segment ) {
            if( root->start <= addr.mach.offset
              && addr.mach.offset <  root->end ) {
                ret = TRUE;
           }
        }
    }
    return( ret );
}


static search_result  DFAddrScope( imp_image_handle *ii,
                im_idx imx, address addr, scope_block *scope )
/************************************************************/
{
    scope_ctl       *ctl;
    scope_node      *node;
    search_result   ret;

    ret = SR_NONE;
    Real2Map( ii->addr_map, &addr );
    ctl =  &ii->scope;
    if( !IsInScope( ctl, addr ) ) {
        addrsym_info        info;
        seg_list            *addr_sym;

        addr_sym = DFLoadAddrSym( ii, imx );
        if( FindAddrSym( addr_sym, &addr.mach, &info ) >= 0 ) {
            DRSetDebug( ii->dwarf->handle );    /* must do at each interface */
            if( DRIsFunc( info.sym ) ) {
                FiniScope( ctl );
                ctl->base = addr;
                ctl->base.mach.offset  = info.map_offset;
                ctl->base.mach.segment = info.map_seg;
                DRWalkScope( info.sym, InBlk, ctl );
            }

⌨️ 快捷键说明

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