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 + -
显示快捷键?