dfsym.c

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

C
1,799
字号
/****************************************************************************
*
*                            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:  DWARF implementation of the DIP symbol handling interface.
*
****************************************************************************/


#include <string.h>
#include "dfdip.h"
#include "dfld.h"
#include "dfmod.h"
#include "dfmodinf.h"
#include "dfaddr.h"
#include "dfaddsym.h"
#include "dftype.h"
#include "dfloc.h"
#include "dfscope.h"
#include "dfhash.h"
#include "demangle.h"
#include "dfsym.h"


imp_mod_handle  DIPENTRY DIPImpSymMod( imp_image_handle *ii, imp_sym_handle *is )
/*******************************************************************************/
{
    /* Return the module that the implementation symbol handle comes from. */
    imp_mod_handle im;

    ii = ii;
    im = IMX2IM( is->imx );
    return( im );
}


unsigned        DIPENTRY DIPImpSymName( imp_image_handle *ii,
                        imp_sym_handle *is, location_context *lc,
                        symbol_name sn, char *buff, unsigned max )
/****************************************************************/
{
    /*
        SN_SOURCE:
                The name of the symbol as it appears in the source code.

        SN_OBJECT:
                The name of the symbol as it appeared to the linker.

        SN_DEMANGLED:
                C++ names, with full typing (essentially it looks like
                a function prototype). If the symbol is not a C++ symbol
                (not mangled), return zero for the length.

        SN_EXPRESSION:
                Return whatever character string is necessary such that
                when scanned in an expression, the symbol handle can
                be reconstructed.

        SS_BLOCK:
                Not possible. Will never happen.
    */
    char        *name;
    unsigned    len, demangled_len;

    lc = lc;
//TODO: what's lc for?
    DRSetDebug( ii->dwarf->handle ); /* must do at each call into dwarf */
    switch( sn ) {
    case SN_SOURCE:
    case SN_OBJECT:
        len = DRGetNameBuff( is->sym, buff, max );
        if( len == 0 ) {
            DCStatus( DS_FAIL );
            return( 0 );
        }
        --len;
        if( max != 0 && len > max ) {
           buff[max-1] = '\0';
        }
        break;
    case SN_SCOPED:
        len =  DRGetScopedNameBuff( is->sym, buff, max );
        if( len == 0 ) {
            DCStatus( DS_FAIL );
            return( 0 );
        }
        --len;
        if( max != 0 && len > max ) {
           buff[max-1] = '\0';
        }
        break;
    case SN_DEMANGLED:
        if( ii->mod_map[is->imx].lang == DR_LANG_CPLUSPLUS ) {
            name = DRDecoratedName( is->sym, NULL );
            if( name == NULL ) {
                DCStatus( DS_FAIL );
                return( 0 );
            }
            len = NameCopy(buff, name, max );
            DCFree( name );
        } else if( buff == NULL ) {
            return( 0 );
        } else {
            len = DRGetNameBuff( is->sym, buff, max );
            if( __is_mangled( buff, len ) ) {
                demangled_len = __demangle_l( buff, len, NULL, 0 );
                if( demangled_len > max ) {
                    demangled_len = max;
                }
                name = DCAlloc( demangled_len );
                __demangle_l( buff, len, name, demangled_len );
                strncpy( buff, name, max );
                DCFree( name );
                return( demangled_len );
            } else {
                return( 0 );
            }
        }
        break;
    case SN_EXPRESSION:
        return( 0 );
    }
    return( len );
}


dip_status      DIPENTRY DIPImpSymType( imp_image_handle *ii,
                    imp_sym_handle *is, imp_type_handle *it )
/***********************************************************/
{
    /* Get the implementation type handle for the type of the given symbol. */
    dip_status  ret;
    ret = DS_FAIL;
    DRSetDebug( ii->dwarf->handle );    /* must do at each call into DWARF */
    if( is->state == DF_NOT ) {
        is->stype = DRGetTagType( is->sym );
    }
    switch( is->stype ) {
    case DR_TAG_FUNCTION:
    case DR_TAG_CLASS:
    case DR_TAG_ENUM:
        it->type = is->sym;
        break;
    default:
        it->type = DRGetTypeAT( is->sym );
        break;
    }
    ret = DS_OK;
    it->imx = is->imx;
    if( it->type != NULL ) {
        it->state = DF_NOT;
    } else {
        it->state = DF_SET;         // default the type
        it->sub_array = FALSE;
        it->typeinfo.kind = DR_TYPEK_DATA;
        it->typeinfo.size = 0;
        it->typeinfo.mclass = DR_MOD_NONE;
        if( is->stype == DR_TAG_LABEL ) {
            it->typeinfo.kind = DR_TYPEK_CODE;
        }
    }
    return( ret );
}


struct mod_wlk {
    imp_image_handle    *ii;
    seg_list            *addr_sym;
    im_idx              imx;
    address             a;
    dr_handle           sym;
    search_result       ret;
};

static int AMod( dr_handle sym, void *_d, dr_search_context *cont )
/*****************************************************************/
{
//TODO: no segments, better TAG_label
    struct mod_wlk  *d = _d;
    uint_32         offset;
    uint_32         seg;
    int             ret;
    addrsym_info    info;

    cont = cont;
    ret = TRUE;
    if( DRGetLowPc( sym, &offset) ) {
        if( d->ii->mod_map[d->imx].is_segment == FALSE ) {
            seg = SEG_FLAT; // if flat hoke segment
        } else {
            EvalSeg( d->ii, sym, &seg );
        }
    } else {
        if( d->ii->mod_map[d->imx].is_segment == FALSE ) {
            seg = SEG_FLAT; // if flat hoke segment
        } else {
            EvalSeg( d->ii, sym, &seg );
        }
        ret = EvalSymOffset( d->ii, sym, &offset );
    }
    info.map_offset = offset;
    info.sym = sym;
    info.map_seg = seg;
    AddAddrSym( d->addr_sym, &info );
    return( TRUE );
}


extern seg_list *DFLoadAddrSym( imp_image_handle *ii, im_idx imx )
/****************************************************************/
{
    dr_handle       cu_tag;
    struct mod_wlk  d;
    seg_list        *addr_sym;

    addr_sym = ii->mod_map[imx].addr_sym;
    if( addr_sym->head == NULL ) {  /* no cache */
        FiniAddrSym( addr_sym );    /* kill cache */
        DRSetDebug( ii->dwarf->handle ); /* must do at each interface */
        cu_tag = ii->mod_map[imx].cu_tag;
        d.addr_sym = addr_sym;
        d.ii = ii;
        d.imx = imx;
        d.ret = SR_NONE;
        DRWalkModFunc( cu_tag, FALSE, AMod, &d );   /* load cache */
        SortAddrSym( addr_sym );
    }
    return( addr_sym );
}


typedef struct {
    dr_handle   inh;    /* member class handle */
    char        *name;  /* member name         */
    dr_handle   match;  /* handle that matches */
} mem_func_wlk;

static int AMemFuncSym( void *_df, addrsym_info *info )
/*****************************************************/
{
    mem_func_wlk    *df = _df;
    int             cont;
    char            buff[256];
    int             len;
    dr_handle       contain;

    cont = TRUE;
    contain  = DRGetContaining( info->sym );
    if( contain != NULL ) {
        contain = DRSkipTypeChain( contain );   /* PCH typedef link */
        if( contain == df->inh ) {
            len =  DRGetNameBuff( info->sym, buff, sizeof( buff ) );
            if( strcmp( buff, df->name ) == 0 ) {
                cont = FALSE;
                df->match = info->sym;
            }
        }
    }
    return( cont );
}


static dr_handle MemFuncLookUp( imp_image_handle *ii,
                                dr_handle sym,
                                dr_handle inh,
                                im_idx   imx )
/***************************************************/
{
    mem_func_wlk    df;
    char            buff[256];
    seg_list        *addr_sym;

    DRSetDebug( ii->dwarf->handle );    /* must do at each call into DWARF */
    addr_sym = DFLoadAddrSym( ii, imx );
    DRGetNameBuff( sym, buff, sizeof( buff ) );
    df.name = buff;
    df.inh =  inh;
    df.match =  NULL;
    WlkAddrSyms( addr_sym, &AMemFuncSym, &df );
    return( df.match );
}


static  addr_seg GetCodeSeg( imp_image_handle *ii )
/*************************************************/
{
    addr_ptr mach;
    mach.segment = SEG_CODE;
    mach.offset = 0;
    DCMapAddr( &mach, ii->dcmap );
    return( mach.segment );
}


dip_status      DIPENTRY DIPImpSymLocation( imp_image_handle *ii,
                imp_sym_handle *is, location_context *lc, location_list *ll )
/***************************************************************************/
{
    /* Get the location of the given symbol. */
    dip_status       ret;
    address          base; /* base segment & offset */
    uint_32          seg;
    dr_handle        sym;

    base = NilAddr;
    DRSetDebug( ii->dwarf->handle ); /* must do at each call into dwarf */
    if( DRGetLowPc( is->sym, &base.mach.offset) ) {
        if( ii->mod_map[is->imx].is_segment == FALSE ) {
            seg = SEG_CODE; // if flat hoke segment
        } else {
            EvalSeg( ii, is->sym, &seg );
        }
        base.mach.segment = seg;
        DCMapAddr( &base.mach, ii->dcmap );
        LocationCreate( ll, LT_ADDR, &base );
        ret = DS_OK;
    } else {
        switch( is->sclass ) {
        case SYM_MEM:
        case SYM_VIRTF:
        {
            dr_bitfield info;
            int         b_strt;

            ret = SafeDCItemLocation( lc, CI_OBJECT, ll );
            if( ret != DS_OK ) {
                DCStatus( ret );
                return( ret );
            }
            if( is->f.minfo.inh != NULL ) {
                DFBaseAdjust( ii, is->f.minfo.root,
                      DRGetTypeAT( is->f.minfo.inh ),lc, &ll->e[0].u.addr );
            }
            ret = EvalLocAdj( ii, lc, is->sym, &ll->e[0].u.addr  );
            if( is->sclass == SYM_VIRTF ) {
                ll->e[0].u.addr.mach.segment = GetCodeSeg( ii );
            } else if( DRGetBitFieldInfo( is->sym, &info ) ) {
                b_strt = 8 * info.byte_size.val.s -
                    (info.bit_offset.val.s + info.bit_size.val.s);
                LocationAdd( ll, b_strt );
                LocationTrunc( ll, info.bit_size.val.s );
            }
            break;
        }
        case SYM_MEMF:
            if( is->f.minfo.inh == NULL ) {
                sym = is->f.minfo.root;
            } else {
                sym = DRGetTypeAT( is->f.minfo.inh );   /* get inherited type */
            }
            sym = DRSkipTypeChain( sym );   /* PCH typedef link */
            sym =  MemFuncLookUp( ii, is->sym, sym, is->imx );
            if( sym == NULL ) {
                base = NilAddr; /* for now say it's NULL */
                LocationCreate( ll, LT_ADDR, &base );
                ret = DS_OK;
                break;
            } else {
                is->sym = sym;
            }
            DRSetDebug( ii->dwarf->handle );    /* must do at each call into DWARF */
            if( DRGetLowPc( is->sym, &base.mach.offset) ) {
                if( ii->mod_map[is->imx].is_segment == FALSE ) {
                    seg = SEG_CODE; // if flat hoke segment
                } else {
                    EvalSeg( ii, is->sym, &seg );
                }
                base.mach.segment = seg;
                DCMapAddr( &base.mach, ii->dcmap );
                LocationCreate( ll, LT_ADDR, &base );
                ret = DS_OK;
            }
            break;
        case SYM_MEMVAR:
        case SYM_VAR:
            if( ii->mod_map[is->imx].is_segment == FALSE ) {
                if( DRIsFunc( is->sym ) ) {
                    seg = SEG_CODE; // if flat hoke segment
                } else {
                    seg = SEG_DATA; // if flat hoke segment
                }
            } else {
                EvalSeg( ii, is->sym, &seg );
            }
            ret = EvalLocation( ii, lc, is->sym, seg, ll );
            break;
        }
    }
    return( ret );
}


dip_status      DIPENTRY DIPImpSymValue( imp_image_handle *ii,
                imp_sym_handle *is, location_context *ic, void *buff )
/********************************************************************/
{
    uint_32     value;
    /* Copy the value of a constant symbol into 'buff'. You can get the
     * size required by doing a SymType followed by a TypeInfo.
     */
    ii = ii;
    ic = ic;
    if( is->sclass != SYM_ENUM ) {
        return( DS_FAIL );
    }
    DRSetDebug( ii->dwarf->handle );    /* must do at each call into DWARF */
    if( !DRConstValAT( is->sym, &value ) ) {
        return( DS_FAIL );
    }
    switch( is->f.einfo.size ) {
    case 1:
        *(uint_8 *)buff = value;
        break;
    case 2:
        *(uint_16 *)buff = value;
        break;
    case 4:
        *(uint_32 *)buff = value;
        break;
    default:
        return( DS_FAIL );
    }
    return( DS_OK );
}


dip_status      DIPENTRY DIPImpSymInfo( imp_image_handle *ii,
                imp_sym_handle *is, location_context *lc, sym_info *si )

⌨️ 快捷键说明

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