drutils.c

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

C
1,082
字号
/****************************************************************************
*
*                            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 reader utility functions.
*
****************************************************************************/


#include <string.h>
#include <demangle.h>
#include "drpriv.h"
#include "drutils.h"

extern unsigned_16 const FunctionTags[] = {
    DW_TAG_subprogram, 0
};

extern unsigned_16 const ClassTags[] = {
    DW_TAG_class_type, DW_TAG_union_type, DW_TAG_structure_type, 0
};

extern unsigned_16 const TypedefTags[] = {
    DW_TAG_typedef, 0
};

extern unsigned_16 const EnumTags[] = {
    DW_TAG_enumeration_type, 0
};

extern unsigned_16 const LabelTags[] = {
    DW_TAG_label, 0
};

extern unsigned_16 const VariableTags[] = {
    DW_TAG_common_block, DW_TAG_variable,
    DW_TAG_formal_parameter, DW_TAG_member, 0
};

extern unsigned_16 const MacroTags[] = { 0 };

extern unsigned_16 const * const SearchTags[] = {
    FunctionTags, ClassTags, EnumTags,
    TypedefTags, VariableTags,
    MacroTags, LabelTags
};

extern unsigned_16 const SearchSymbolTags[] = {
    DW_TAG_class_type, DW_TAG_common_block, DW_TAG_enumeration_type,
    DW_TAG_subprogram, DW_TAG_variable, DW_TAG_member, DW_TAG_structure_type,
    DW_TAG_typedef, DW_TAG_union_type, DW_TAG_label, 0
};

extern unsigned_16 const SearchFunctionTags[] = {
    DW_TAG_subprogram, 0
};

extern unsigned_16 const SearchClassTags[] = {
    DW_TAG_class_type, DW_TAG_union_type, DW_TAG_structure_type, 0
};

extern unsigned_16 const SearchTypeTags[] = {
    DW_TAG_typedef, DW_TAG_enumeration_type, 0
};

extern unsigned_16 const SearchVariableTags[] = {
    DW_TAG_common_block, DW_TAG_variable, DW_TAG_member, 0
};

extern unsigned_16 const SearchFriendTags[] = {
    DW_TAG_friend, 0
};

extern unsigned_16 const SearchBaseTags[] = {
    DW_TAG_inheritance, 0
};

extern unsigned_16 const ScanKidsTags[] = {
    DW_TAG_compile_unit,  DW_TAG_lexical_block, 0
};

extern unsigned_16 const DeclarationTags[] = {
    DW_TAG_array_type, DW_TAG_class_type, DW_TAG_common_block, DW_TAG_constant,
    DW_TAG_enumeration_type, DW_TAG_member, DW_TAG_structure_type,
    DW_TAG_subprogram, DW_TAG_union_type, DW_TAG_variable, 0
};

extern unsigned_16 const * const SearchTypes[] = {
    SearchSymbolTags, SearchFunctionTags, SearchClassTags,
    SearchTypeTags, SearchVariableTags, SearchFriendTags, SearchBaseTags
};


extern long DWRInfoLength( dr_handle mod )
/****************************************/
// return length of dbg_info for mod
{
    dr_handle           finish;

    finish = mod + DWRVMReadDWord( mod );
    mod += COMPILE_UNIT_HDR_SIZE;
    return( finish - mod );
}


extern bool DWRScanCompileUnit( dr_search_context *ctxt,
                           DWRCUWLK fn,
                           unsigned_16 const *tagarray, dr_depth depth, void *data)
/*********************************************************************************/
/* note this modifies the start and stack fields of the context passed in */
{
    dr_handle           mod;
    unsigned            abbrevidx;
    mod_scan_info       info;
    unsigned_8          haschild;
    stack_op            op;
    dr_handle           abbrev;
    bool                skipped;

    mod = ctxt->start;
    info.context = ctxt;

    if( ctxt->stack.free == 0 ) { // start out in an unnamed chain
        DWRContextPush( &ctxt->stack, mod );
        DWRContextPush( &ctxt->stack, DO_NOTHING );
    }

    while( mod < ctxt->end ) {
        info.handle = mod;
        abbrevidx = DWRVMReadULEB128( &mod );
        if( abbrevidx == 0 ) {
            op = DWRContextPop( &ctxt->stack );
            switch( op ) {
            case SET_CLASS:
                ctxt->classhdl = DWRContextPop( &ctxt->stack );
                break;
            case SET_FUNCTION:
                ctxt->functionhdl = DWRContextPop( &ctxt->stack );
                break;
            case DO_NOTHING:
                DWRContextPop( &ctxt->stack );
                break;
            }
            if( ctxt->stack.free < 0 ) DWREXCEPT( DREXCEP_BAD_DBG_INFO );
            continue;   // <------------------  NOTE: weird control flow!
        }
        abbrev = ctxt->compunit->abbrevs[abbrevidx];
        info.tag = DWRVMReadULEB128( &abbrev );
        haschild = DWRVMReadByte( abbrev );
        abbrev++;
        if( DWRSearchArray( tagarray, info.tag ) ) {
            info.context->start = info.handle;
            if( !fn( abbrev, mod, &info, data ) )
                return( FALSE );    // FALSE == quit
        }
        skipped = FALSE;
        if( haschild == DW_CHILDREN_yes ) {
            if( DWRSearchArray( SearchClassTags, info.tag ) ) {
                if( !(depth & DR_DEPTH_CLASSES) ) {
                    DWRSkipChildren( &abbrev, &mod );
                    skipped = TRUE;
                } else {
                    DWRContextPush( &ctxt->stack, ctxt->classhdl );
                    DWRContextPush( &ctxt->stack, SET_CLASS );
                    ctxt->classhdl = info.handle;
                }
            } else {
                if( DWRSearchArray( SearchFunctionTags, info.tag ) ) {
                    if( !(depth & DR_DEPTH_FUNCTIONS) ) {
                        DWRSkipChildren( &abbrev, &mod );
                        skipped = TRUE;
                    } else {
                        DWRContextPush( &ctxt->stack, ctxt->functionhdl );
                        DWRContextPush( &ctxt->stack, SET_FUNCTION );
                        ctxt->functionhdl = info.handle;
                    }
                } else {
                    DWRContextPush( &ctxt->stack, info.handle );
                    DWRContextPush( &ctxt->stack, DO_NOTHING );
                }
            }
        }
        if( !skipped ) DWRSkipAttribs( abbrev, &mod );
    }

    return( TRUE );
}

extern void DWRSkipChildren( dr_handle *abbrev, dr_handle *mod )
/**************************************************************/
{
    unsigned_16 value;
    dr_handle   handle;

    value = DWRScanForAttrib( abbrev, mod, DW_AT_sibling );
    if( value == DW_AT_sibling ) {
        *mod = DWRReadReference( *abbrev, *mod );
    } else {    // we have to manually skip everything
        for( ;; ) {
            handle = DWRVMReadULEB128( mod );   // get attribute
            if( handle == 0 ) break;            // found end of chain!
            handle = DWRLookupAbbrev( *mod, handle );
            DWRVMSkipLEB128( &handle );         // skip tag
            handle++;                           // skip child;
            DWRSkipAttribs( handle, mod );
        }
    }
}

extern void DWRSkipAttribs( dr_handle abbrev, dr_handle *mod )
/************************************************************/
// skip the attributes.
{
    dw_formnum  form;
    dw_atnum    attrib;

    for( ;; ) {
        attrib = DWRVMReadULEB128( &abbrev );   // read attribute
        form = DWRVMReadULEB128( &abbrev );     // skip form
        if( attrib == 0 ) break;
        DWRSkipForm( mod, form );
    }
}

extern void DWRSkipRest( dr_handle abbrev, dr_handle *mod )
/*********************************************************/
// skip the rest of the attributes.  This is designed to come after a
// DWRScanForAttrib, which leaves abbrev pointing at the form.
{
    dw_formnum  form;
    dw_atnum    attrib;

    attrib = 1;         // arbitrary non-zero
    for( ;; ) {
        form = DWRVMReadULEB128( &abbrev );
        if( attrib == 0 ) break;
        DWRSkipForm( mod, form );
        attrib = DWRVMReadULEB128( &abbrev );
    }
}

extern void DWRAllChildren( dr_handle mod,
                            bool (*fn)(dr_handle, dr_handle, void *),
                            void *data )
/*******************************************************************/
{
    dr_handle   abbrev;

    for( ;; ) {
        abbrev = DWRVMReadULEB128( &mod );
        if( abbrev == 0 ) break;
        abbrev = DWRLookupAbbrev( mod, abbrev );
        DWRVMSkipLEB128( &abbrev );
        abbrev += sizeof( unsigned_8 );
        if( !fn( abbrev, mod, data ) ) break;
        DWRSkipAttribs( abbrev, &mod );
    }
}

extern bool DWRSearchArray( unsigned_16 const *array, unsigned_16 value )
/***********************************************************************/
{
    while( *array != 0 ) {
        if( *array == value ) return( TRUE );
        array++;
    }
    return( FALSE );
}

extern unsigned DWRGetAddrSize( dr_handle mod )
/**********************************************/
/* returns the size of the address for the compile unit */
{
    return( DWRVMReadByte( mod + 10 ) );
}


extern void DWRSkipForm( dr_handle *addr, unsigned_16 form )
/**********************************************************/
{
    unsigned_32 value;
    switch( form ) {
    case DW_FORM_addr:
        if( DWRCurrNode->addr_size == 0 ) {
            *addr += DWRGetAddrSize( DWRFindCompileUnit( *addr ) );
        } else {
            *addr += DWRCurrNode->addr_size;
        }
        break;
    case DW_FORM_block1:
        *addr += DWRVMReadByte( *addr ) + sizeof(unsigned_8);
        break;
    case DW_FORM_block2:
        *addr += DWRVMReadWord( *addr ) + sizeof(unsigned_16);
        break;
    case DW_FORM_block4:
        *addr += DWRVMReadDWord( *addr ) + sizeof(unsigned_32);
        break;
    case DW_FORM_block:
        value = DWRVMReadULEB128( addr );
        *addr += value;
        break;
    case DW_FORM_flag:
    case DW_FORM_data1:
    case DW_FORM_ref1:
        *addr += 1;
        break;
    case DW_FORM_data2:
    case DW_FORM_ref2:
        *addr += 2;
        break;
    case DW_FORM_ref_addr:      // NYI: non-standard behaviour for form_ref
    case DW_FORM_data4:
    case DW_FORM_ref4:
        *addr += 4;
        break;
    case DW_FORM_data8:
        *addr += 8;
        break;
    case DW_FORM_sdata:
    case DW_FORM_udata:
    case DW_FORM_ref_udata:
        DWRVMSkipLEB128( addr );
        break;
    case DW_FORM_string:
        *addr += DWRStrLen( *addr ) + 1;
        break;
    case DW_FORM_strp:
        *addr += 4;
        break;
    case DW_FORM_indirect:
        value = DWRVMReadULEB128( addr );
        DWRSkipForm( addr, value );
        break;
    default:
        DWREXCEPT( DREXCEP_BAD_DBG_INFO );
    }
}

⌨️ 快捷键说明

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