bool DRConstValAT( dr_handle var, uint_32 *ret ) /**********************************************/ { dr_handle abbrev; unsigned form; uint_32 val; dwr_formcl formcl; abbrev = DWRGetAbbrev( &var ); if( DWRScanForAttrib( &abbrev, &var, DW_AT_const_value ) ) { form = DWRVMReadULEB128( &abbrev ); for( ;; ) { formcl = DWRFormClass( form ); switch( formcl ) { case DWR_FORMCL_indirect: form = DWRVMReadULEB128( &var ); break; case DWR_FORMCL_data: val = ReadConst( form, var ); *ret = val; goto found; default: goto not_found; } } } not_found: return( FALSE ); found: return( TRUE ); }
static bool DWRGetConstAT( dr_handle abbrev, dr_handle info, unsigned at, unsigned_32 *where ) /******************************************************************/ /* look for a specific attribute in the list of attributes */ /* if found read in */ { unsigned attrib; unsigned form; bool ret; ret = FALSE; for( ;; ) { attrib = DWRVMReadULEB128( &abbrev ); if( attrib == at ) break; form = DWRVMReadULEB128( &abbrev ); if( attrib == 0 ) break; DWRSkipForm( &info, form ); } if( attrib != 0 ) { *where = DWRReadConstant( abbrev, info ); ret = TRUE; } return( ret ); }
extern dr_handle DRSkipTypeChain( dr_handle tref ) /************************************************/ // skip modifiers and typedefs { dr_handle abbrev; dr_handle entry; uint_32 tag; for( ;; ) { entry = tref; abbrev = DWRVMReadULEB128( &entry ); abbrev = DWRLookupAbbrev( entry, abbrev ); tag = DWRVMReadULEB128( &abbrev ); ++abbrev; /* skip child flag */ switch( tag ) { case DW_TAG_const_type: case DW_TAG_volatile_type: case DW_TAG_packed_type: case DW_TAG_typedef: break; default: goto end_loop; } if( DWRScanForAttrib( &abbrev, &entry, DW_AT_type ) ) { entry = DWRReadReference( abbrev, entry ); tref = entry; } else { tref = 0; goto end_loop; } } end_loop:; return( tref ); }
extern void DRGetSubrangeInfo( dr_handle sub, dr_subinfo *info ) /**************************************************************/ { dr_handle abbrev; dr_val32 vals[3]; abbrev = DWRVMReadULEB128( &sub ); abbrev = DWRLookupAbbrev( sub, abbrev ); DWRVMReadULEB128( &abbrev ); /* skip tag */ ++abbrev; /* skip child flag */ DWRGetAT( abbrev, sub, vals, SubATList ); info->low = vals[0]; info->high = vals[1]; info->count = vals[2]; }
static size_t GetNameBuffAttr( drmem_hdl entry, char *buff, size_t length, dw_atnum attrib ) /******************************************************************************************/ { drmem_hdl abbrev; dw_formnum form; abbrev = DWRSkipTag( &entry ) + 1; if( DWRScanForAttrib( &abbrev, &entry, attrib ) ) { form = DWRVMReadULEB128( &abbrev ); switch( form ) { case DW_FORM_string: length = DWRVMGetStrBuff( entry, buff, length ); break; case DW_FORM_strp: { unsigned_32 offset; drmem_hdl dbgsec_str; offset = ReadConst( DW_FORM_data4, entry ); dbgsec_str = DWRCurrNode->sections[DR_DEBUG_STR].base + offset; length = DWRVMGetStrBuff( dbgsec_str, buff, length ); } break; default: DWREXCEPT( DREXCEP_BAD_DBG_INFO ); length = 0; } } else { length = 0; } return( length ); }
extern int DRGetBitFieldInfo( dr_handle mem, dr_bitfield *info ) /**************************************************************/ { dr_handle abbrev; dr_val32 vals[3]; int count; abbrev = DWRVMReadULEB128( &mem ); abbrev = DWRLookupAbbrev( mem, abbrev ); DWRVMReadULEB128( &abbrev ); /* skip tag */ ++abbrev; /* skip child flag */ count = DWRGetAT( abbrev, mem, vals, BitATList ); info->byte_size = vals[0]; info->bit_offset = vals[1]; info->bit_size = vals[2]; return( count ); }
static int DWRGetAT( dr_handle abbrev, dr_handle info, dr_val32 *vals, uint_16 const *at ) /********************************************************/ /* look for a specific attribute in the list of attributes */ /* if found read in */ { unsigned attrib; unsigned form; uint_16 index; dwr_formcl formcl; uint_32 value; int count; int max; count = 0; for( index = 0; at[index] != 0; ++index ) { vals[index].val_class = DR_VAL_NOT; } max = index; for( ;; ) { attrib = DWRVMReadULEB128( &abbrev ); if( attrib == 0 ) break; form = DWRVMReadULEB128( &abbrev ); for( index = 0; index < max; ++index ) { if( attrib == at[index] ) { ++count; if( form == DW_FORM_indirect ) { form = DWRVMReadULEB128( &info ); } formcl = DWRFormClass( form ); value = ReadConst( form, info ); if( formcl == DWR_FORMCL_data ) { vals[index].val_class = DR_VAL_INT; vals[index].val.s = value; } else { value += DWRFindCompileUnit( info ); vals[index].val_class = DR_VAL_REF; vals[index].val.ref = value; } } } DWRSkipForm( &info, form ); } return( count ); }
extern dr_array_stat DRGetArrayInfo( dr_handle entry, dr_array_info *info ) /*************************************************************************/ { dr_handle abbrev; dr_array_stat stat; uint_32 value; unsigned_8 haschild; stat = DR_ARRAY_NONE; abbrev = DWRVMReadULEB128( &entry ); abbrev = DWRLookupAbbrev( entry, abbrev ); DWRVMReadULEB128( &abbrev ); /* skip tag */ haschild = DWRVMReadByte( abbrev ); ++abbrev; /* skip child flag */ if( DWRGetConstAT( abbrev, entry, DW_AT_ordering, &value ) ) { info->ordering = value; stat |= DR_ARRAY_ORDERING; } if( DWRGetConstAT( abbrev, entry, DW_AT_byte_size, &value ) ) { info->byte_size = value; stat |= DR_ARRAY_BYTE_SIZE; } if( DWRGetConstAT( abbrev, entry, DW_AT_stride_size, &value ) ) { info->stride_size = value; stat |= DR_ARRAY_STRIDE_SIZE; } if( DWRGetConstAT( abbrev, entry, DW_AT_count, &value ) ) { info->count = value; stat |= DR_ARRAY_COUNT; } if( haschild ) { DWRSkipAttribs( abbrev, &entry ); info->child = entry; } else { info->child = 0; } return( stat ); }
static void ReadNameEntry( drmem_hdl *start, file_info *nametab, file_table *idxtab, file_table *maptab ) /*****************************************************************/ { char *name; filetab_idx ftidx; dr_fileidx pathidx; name = DWRVMCopyString( start ); ftidx = DWRAddFileName( name, &nametab->fnametab ); DWRAddIndex( ftidx, idxtab, TAB_IDX_FNAME ); pathidx = DWRVMReadULEB128( start ); ftidx = DWRIndexPath( pathidx, maptab ); DWRInsertIndex( ftidx, idxtab, TAB_IDX_PATH ); DWRVMSkipLEB128( start ); // skip time DWRVMSkipLEB128( start ); // skip length }
extern void DWRScanFileTable( drmem_hdl start, file_info *nametab, file_table *idxtab ) /****************************************************************/ // find the filenames in the line information, and return them in a table { drmem_hdl finish; file_table curridxmap; char *name; int index; filetab_idx ftidx; unsigned length; unsigned_8 *oparray; int op_base; int value; unsigned_32 stmt_offset; dw_lns value_lns; dw_lne value_lne; stmt_offset = (unsigned_32)-1; DWRGetCompileUnitHdr( start, GrabLineAddr, &stmt_offset ); if( stmt_offset == (unsigned_32)-1 ) { return; } start = DWRCurrNode->sections[DR_DEBUG_LINE].base + stmt_offset; finish = start + DWRVMReadDWord( start ); op_base = DWRVMReadByte( start + offsetof( stmt_prologue, opcode_base ) ); start += offsetof( stmt_prologue, standard_opcode_lengths ); oparray = __alloca( op_base - 1 ); for( index = 0; index < op_base - 1; index++ ) { oparray[index] = DWRVMReadByte( start ); start++; } DWRInitFileTable( &curridxmap ); while( start < finish ) { // get directory table value = DWRVMReadByte( start ); if( value == 0 ) { start++; break; } name = DWRVMCopyString( &start ); ftidx = DWRAddFileName( name, &nametab->pathtab ); DWRAddIndex( ftidx, &curridxmap, TAB_IDX_PATH ); } while( start < finish ) { // get filename table value = DWRVMReadByte( start ); if( value == 0 ) { start++; break; } ReadNameEntry( &start, nametab, idxtab, &curridxmap ); } while( start < finish ) { // now go through the statement program value_lns = DWRVMReadByte( start ); start++; if( value_lns == 0 ) { // it's an extended opcode length = DWRVMReadULEB128( &start ); value_lne = DWRVMReadByte( start ); if( value_lne == DW_LNE_define_file ) { start++; ReadNameEntry( &start, nametab, idxtab, &curridxmap ); } else { start += length; } } else if( value_lns < op_base ) { // it is a standard opcode if( value_lns == DW_LNS_fixed_advance_pc ) { start += sizeof( unsigned_16 ); // it is a fixed size } else { // it is a variable # of blocks for( value = oparray[value_lns - 1]; value > 0; --value ) { DWRVMSkipLEB128( &start ); } } } // else it was a special op, and thus only 1 byte long } DWRTrimTableSize( idxtab ); DWRFiniFileTable( &curridxmap, false ); }
extern bool DRGetTypeInfo( dr_handle entry, dr_typeinfo *info ) /**************************************************************/ // Assume entry is pointing at start of a type { dr_handle curr_ab; dr_handle abbrev; dr_handle curr_ent; dw_tagnum tag; uint_32 value; dr_typek kind; info->acc = DR_STORE_NONE; info->mclass = DR_MOD_NONE; kind = 0; for( ;; ) { if( entry == DR_HANDLE_VOID ) { info->kind = DR_TYPEK_VOID; info->mclass = DR_MOD_BASE; info->size = 0; info->modifier.sign = FALSE; return( TRUE ); } abbrev = DWRVMReadULEB128( &entry ); abbrev = DWRLookupAbbrev( entry, abbrev ); tag = DWRVMReadULEB128( &abbrev ); ++abbrev; /* skip child flag */ switch( tag ) { case DW_TAG_array_type: kind = DR_TYPEK_ARRAY; goto end_loop; case DW_TAG_enumeration_type: kind = DR_TYPEK_ENUM; info->mclass = DR_MOD_BASE; goto end_loop; case DW_TAG_pointer_type: kind = DR_TYPEK_POINTER; info->mclass = DR_MOD_ADDR; goto end_loop; case DW_TAG_string_type: kind = DR_TYPEK_STRING; goto end_loop; case DW_TAG_structure_type: kind = DR_TYPEK_STRUCT; goto end_loop; case DW_TAG_union_type: kind = DR_TYPEK_UNION; goto end_loop; case DW_TAG_class_type: kind = DR_TYPEK_CLASS; goto end_loop; case DW_TAG_subprogram: case DW_TAG_subroutine_type: kind = DR_TYPEK_FUNCTION; goto end_loop; case DW_TAG_reference_type: kind = DR_TYPEK_REF; info->mclass = DR_MOD_ADDR; goto end_loop; case DW_TAG_ptr_to_member_type: kind = DR_TYPEK_ADDRESS; goto end_loop; case DW_TAG_set_type: kind = DR_TYPEK_DATA; goto end_loop; case DW_TAG_subrange_type: kind = DR_TYPEK_DATA; info->mclass = DR_MOD_BASE; goto end_loop; break; case DW_TAG_base_type: info->mclass = DR_MOD_BASE; goto end_loop; case DW_TAG_file_type: kind = DR_TYPEK_DATA; goto end_loop; case DW_TAG_thrown_type: kind = DR_TYPEK_CODE; goto end_loop; /*** goes for loop ***/ case DW_TAG_const_type: info->acc |= DR_STORE_CONST; break; case DW_TAG_volatile_type: info->acc |= DR_STORE_VOLATILE; break; case DW_TAG_packed_type: info->acc |= DR_STORE_PACKED; break; case DW_TAG_typedef: break; default: goto error; } curr_ab = abbrev; curr_ent = entry; if( DWRScanForAttrib( &curr_ab, &curr_ent, DW_AT_type ) ) { entry = DWRReadReference( curr_ab, curr_ent ); } else { goto error; } }end_loop:; info->kind = kind; if( info->mclass != DR_MOD_ADDR ) { if( DWRGetConstAT( abbrev, entry, DW_AT_byte_size, &value ) ) { info->size = value; } else { info->size = 0; } } switch( info->mclass ) { case DR_MOD_BASE: if( DWRGetConstAT( abbrev, entry, DW_AT_encoding, &value ) ) { switch( value ) { case DW_ATE_address: info->kind = DR_TYPEK_ADDRESS; info->modifier.sign = FALSE; break; case DW_ATE_boolean: info->kind = DR_TYPEK_BOOL; info->modifier.sign = FALSE; break; case DW_ATE_complex_float: info->kind = DR_TYPEK_COMPLEX; break; case DW_ATE_float: info->kind = DR_TYPEK_REAL; break; case DW_ATE_signed: info->kind = DR_TYPEK_INTEGER; info->modifier.sign = TRUE; break; case DW_ATE_signed_char: info->kind = DR_TYPEK_CHAR; info->modifier.sign = TRUE; break; case DW_ATE_unsigned: info->kind = DR_TYPEK_INTEGER; info->modifier.sign = FALSE; break; case DW_ATE_unsigned_char: info->kind = DR_TYPEK_CHAR; info->modifier.sign = FALSE; break; default: goto error; } } else { info->modifier.sign = FALSE; } break; case DR_MOD_ADDR: if( !DWRGetConstAT( abbrev, entry, DW_AT_address_class, &value ) ) { value = DW_ADDR_none; } switch( value ) { case DW_ADDR_none: info->size = DWRGetAddrSize( DWRFindCompileUnit( entry ) ); info->modifier.ptr = DR_PTR_none; break; case DW_ADDR_near16: info->size = 2; info->modifier.ptr = DR_PTR_near16; break; case DW_ADDR_far16: info->size = 4; info->modifier.ptr = DR_PTR_far16; break; case DW_ADDR_huge16: info->size = 4; info->modifier.ptr = DR_PTR_huge16; break; case DW_ADDR_near32: info->size = 4; info->modifier.ptr = DR_PTR_near32; break; case DW_ADDR_far32: info->size = 6; info->modifier.ptr = DR_PTR_far32; break; default: goto error; } break; } return( TRUE ); error: return( FALSE ); }
static void References( ReferWhich which, dr_handle entry, void *data1, hook_func do_callback, void *data2, DRSYMREF callback ) /*********************************************************************/ { dr_handle loc; dr_handle end; dr_handle owning_node; dr_handle infoOffset; unsigned_8 opcode; dr_ref_info registers = { { 0, 0, NULL }, 0L, NULL, 1L, 1 }; bool quit = FALSE; bool inScope = FALSE; loc = DWRCurrNode->sections[ DR_DEBUG_REF ].base; end = loc + DWRCurrNode->sections[ DR_DEBUG_REF ].size; infoOffset = DWRCurrNode->sections[ DR_DEBUG_INFO ].base; loc += sizeof( unsigned_32 ); /* skip size */ while( loc < end && !quit ) { opcode = DWRVMReadByte( loc ); loc += sizeof( unsigned_8 ); switch( opcode ) { case REF_BEGIN_SCOPE: owning_node = DWRVMReadDWord( loc ) + infoOffset; loc += sizeof( unsigned_32 ); ScopePush( ®isters.scope, owning_node ); if( (which & REFERSTO) != 0 && owning_node == entry ) { inScope = TRUE; } break; case REF_END_SCOPE: ScopePop( ®isters.scope ); inScope = FALSE; break; case REF_SET_FILE: registers.file = DWRFindFileName( DWRVMReadULEB128( &loc ), infoOffset ); break; case REF_SET_LINE: registers.line = DWRVMReadULEB128( &loc ); break; case REF_SET_COLUMN: registers.column = (unsigned_8)DWRVMReadULEB128( &loc ); break; case REF_ADD_LINE: registers.line += DWRVMReadSLEB128( &loc ); registers.column = 0; break; case REF_ADD_COLUMN: registers.column += (signed_8)DWRVMReadSLEB128( &loc ); break; case REF_COPY: default: if( opcode >= REF_CODE_BASE ) { unsigned_32 ld; opcode -= REF_CODE_BASE; ld = opcode / REF_COLUMN_RANGE; if( ld != 0 ) { registers.column = 0; registers.line += ld; } registers.column += opcode % REF_COLUMN_RANGE; registers.dependent = DWRVMReadDWord( loc ) + infoOffset; loc += sizeof( unsigned_32 ); } quit = FALSE; /* don't terminate */ if( do_callback( ®isters, data1 ) || inScope ) { char *name = NULL; owning_node = ScopeLastNameable( ®isters.scope, &name ); /* make sure that there is something nameable on the stack */ if( owning_node != DR_HANDLE_NUL ) { quit = !callback( owning_node, ®isters, name, data2 ); } } break; } } DWRFREE( registers.scope.stack ); }