dip_status InitDemand( imp_image_handle *ii ) { struct walk_demand d; d.max_size = 0; MyWalkModList( ii, WlkDmnd, &d ); if( d.max_size >= (0x10000UL - sizeof( demand_ctrl )) ) { DCStatus( DS_ERR|DS_INFO_INVALID ); return( DS_ERR|DS_INFO_INVALID ); } if( d.max_size <= LastDmndSize ) return( DS_OK ); if( LastDemand != NULL ) { Unload( LastDemand ); DCFree( LastDemand ); } LastDmndSize = d.max_size; LastDemand = DCAlloc( _demand_size( d.max_size ) ); if( LastDemand == NULL ) { DCStatus( DS_ERR|DS_NO_MEM ); return( DS_ERR|DS_NO_MEM ); } LastDemand->link = NULL; LastDemand->owner = NULL; LastDemand->clear = NULL; LastDemand->locks = 0; return( DS_OK ); }
/* Adjust the 'src' cue by 'adj' amount and return the result in 'dst'. That is, If you get called with "DIPImpCueAdjust( ii, src, 1, dst )", the 'dst' handle should be filled in with implementation cue handle representing the source cue immediately following the 'src' cue. Passing in an 'adj' of -1 will get the immediately preceeding source cue. The list of source cues for each file are considered a ring, so if 'src' is the first cue in a file, an 'adj' of -1 will return the last source cue FOR THAT FILE. The cue adjust never crosses a file boundry. Also, if 'src' is the last cue in a file, and 'adj' of 1 will get the first source cue FOR THAT FILE. If an adjustment causes a wrap from begining to end or vice versa, you should return DS_WRAPPED status (NOTE: DS_ERR should *not* be or'd in, nor should DCStatus be called in this case). Otherwise DS_OK should be returned unless an error occurred. */ dip_status DIPENTRY DIPImpCueAdjust( imp_image_handle *ii, imp_cue_handle *src, int adj, imp_cue_handle *dst ) /*****************************************************************/ { dr_handle stmts; dfline_search start_state; dfline_find find; dip_status ret; imp_mod_handle imx; cue_item cue; cue_list *cue_map; address map_addr; imx = src->imx; DRSetDebug( ii->dwarf->handle ); /* must do at each call into DWARF */ stmts = ii->mod_map[imx].stmts; if( stmts == 0 ) { DCStatus( DS_FAIL ); return( DS_ERR|DS_FAIL ); } cue_map= ii->cue_map; if( cue_map->imx != imx ) { ResetCueInfo( cue_map ); cue_map->imx = imx; map_addr = NilAddr; LoadCueMap( stmts, &map_addr, cue_map ); } if( adj < 0 ) { start_state = LOOK_LOW; adj = -adj; } else { start_state = LOOK_HIGH; } cue.fno = src->fno; cue.line = src->line; cue.col = src->col; while( 0 != adj ) { find = FindCue( cue_map, &cue, start_state ); if( find == LINE_NOT ) break; --adj; } dst->imx = imx; dst->fno = cue.fno; dst->line = cue.line; dst->col = cue.col; dst->a.mach = cue.mach; switch( find ) { case LINE_NOT: DCStatus( DS_FAIL ); ret = DS_ERR | DS_FAIL; break; case LINE_WRAPPED: ret = DS_WRAPPED; break; case LINE_FOUND: ret = DS_OK; break; } return( ret ); }
dip_status hllLocationManyReg( imp_image_handle *iih, unsigned count, const unsigned_8 *reg_list, location_context *lc, location_list *ll ) { unsigned i; byte j; unsigned idx; const reg_entry *reg; location_list reg_ll; dip_status ds; j = 0; for( i = count; i-- > 0; ) { idx = reg_list[i]; switch( iih->mad ) { case MAD_X86: if( idx >= CV_X86_AL && idx <= CV_X86_EFLAGS ) { reg = &X86_CPURegTable[idx-CV_X86_AL]; } else if( idx >= CV_X86_ST0 && idx <= CV_X86_STATUS ) { reg = &X86_FPURegTable[idx-CV_X86_ST0]; } else { DCStatus( DS_ERR | DS_FAIL ); return( DS_ERR | DS_FAIL ); } break; case MAD_AXP: if( !(idx >= CV_AXP_f0 && idx <= CV_AXP_fltfsr) ) { DCStatus( DS_ERR | DS_FAIL ); return( DS_ERR | DS_FAIL ); } reg = &AXP_RegTable[idx-CV_AXP_f0]; if( reg->ci == CI_LAST ) { DCStatus( DS_ERR | DS_FAIL ); return( DS_ERR | DS_FAIL ); } break; default: DCStatus( DS_ERR | DS_FAIL ); return( DS_ERR | DS_FAIL ); } ds = DCItemLocation( lc, reg->ci, ®_ll ); if( ds != DS_OK ) { DCStatus( ds ); return( ds ); } memcpy( &ll->e[j], ®_ll.e[0], reg_ll.num * sizeof( reg_ll.e[0] ) ); ll->e[j].bit_start += BYTES2BITS( reg->start ); ll->e[j].bit_length = BYTES2BITS( reg->len ); j += reg_ll.num; ll->flags |= reg_ll.flags; } ll->num = j; return( DS_OK ); }
dip_status DIPIMPENTRY( LoadInfo )( dig_fhandle fid, imp_image_handle *ii ) { dip_status ds; unsigned long off; unsigned long size; cv_directory_entry *cde; cv_sst_global_types_header *hdr; memset( ii, 0, sizeof( *ii ) ); ds = FindCV( fid, &off, &size ); if( ds != DS_OK ) return( ds ); ii->sym_fid = fid; ii->bias = off; ds = VMInit( ii, size ); if( ds != DS_OK ) return( ds ); ii->next_image = ImageList; ImageList = ii; ds = LoadDirectory( ii, off + CV_SIG_SIZE ); if( ds != DS_OK ) { DCStatus( ds ); Cleanup( ii ); return( ds ); } ds = LoadMapping( ii ); if( ds != DS_OK ) { DCStatus( ds ); Cleanup( ii ); return( ds ); } cde = FindDirEntry( ii, IMH_GBL, sstGlobalTypes ); if( cde != NULL ) { hdr = VMBlock( ii, cde->lfo, sizeof( *hdr ) ); if( hdr == NULL ) { Cleanup( ii ); return( DS_ERR|DS_FAIL ); } ii->types_base = cde->lfo + offsetof(cv_sst_global_types_header, offType ) + hdr->cType * sizeof( hdr->offType[0] ); } ds = SetMADType( ii ); if( ds != DS_OK ) { DCStatus( ds ); Cleanup( ii ); return( ds ); } return( DS_OK ); }
size_t DIPIMPENTRY( CueFile )( imp_image_handle *ii, imp_cue_handle *ic, char *buff, size_t buff_size ) /************************************************************************/ { char *name; file_walk_name wlk; size_t len; drmem_hdl stmts; drmem_hdl cu_tag; int i; mod_info *modinfo; DRSetDebug( ii->dwarf->handle ); /* must do at each call into dwarf */ modinfo = IMH2MODI( ii, ic->im ); stmts = modinfo->stmts; cu_tag = modinfo->cu_tag; if( stmts == DRMEM_HDL_NULL || cu_tag == DRMEM_HDL_NULL ) { DCStatus( DS_FAIL ); return( 0 ); } wlk.index = ic->fno; wlk.ret = NULL; wlk.num_dirs = 0; wlk.dirs = NULL; DRWalkLFiles( stmts, ACueFile, &wlk, ACueDir, &wlk ); name = wlk.ret; // Free directory and file table information for( i = 0; i < wlk.num_dirs; i++ ) { DCFree( wlk.dirs[i].name ); } DCFree( wlk.dirs ); if( name == NULL ) { DCStatus( DS_FAIL ); return( 0 ); } // If compilation unit has a DW_AT_comp_dir attribute, we need to // stuff that in front of the file pathname, unless that is absolute len = DRGetCompDirBuff( cu_tag, buff, buff_size ); if( ( len > 1 ) && IsRelPathname( name ) ) { // Ignore empty comp dirs len = NameCopy( buff, "/", buff_size, len ); } else { len = 0; } len = NameCopy( buff, name, buff_size, len ); DCFree( name ); return( len ); }
dip_status InitModMap( imp_image_handle *ii ) /***********************************************/ // Make the imp_mod_handle to dr_handle map { mod_list list; dip_status ret; ret = DS_OK; ii->mod_count = 0; InitModList( &list ); InitAddrSym( ii->addr_sym ); DRSetDebug( ii->dwarf->handle ); /* set dwarf to image */ DRIterateCompileUnits( &list, ModFill ); DRDbgClear( ii->dwarf->handle ); /* clear some mem */ ii->mod_count = list.count; ii->mod_map = FiniModInfo( &list ); if( list.version == VER_V1 ) { DRDbgOldVersion( ii->dwarf->handle, 1 ); } else if( list.version == VER_V2 ) { DRDbgOldVersion( ii->dwarf->handle, 2 ); } else if( list.version == VER_ERROR ) { DCStatus( DS_INFO_BAD_VERSION ); ret = DS_FAIL | DS_INFO_BAD_VERSION; } return( ret ); }
walk_result DIPENTRY DIPImpWalkFileList( imp_image_handle *ii, imp_mod_handle im, IMP_CUE_WKR *wk, imp_cue_handle *ic, void *d ) /*************************************************************************/ { file_walk_cue wlk; im_idx imx; dr_handle stmts; imx = IM2IMX( im ); DRSetDebug( ii->dwarf->handle ); /* must do at each call into DWARF */ stmts = ii->mod_map[imx].stmts; if( stmts == 0 ) { DCStatus( DS_FAIL ); return( WR_CONTINUE ); } wlk.stmts = stmts; wlk.ii = ii; wlk.imx = imx; wlk.wk = wk; wlk.ic = ic; wlk.d = d; wlk.wr = WR_CONTINUE; DRWalkLFiles( stmts, ACueFileNum, &wlk, ACueDir, NULL ); return( wlk.wr ); }
char *DIGENTRY DIPImpModSrcLang( imp_image_handle *ii, imp_mod_handle im ) { char *ret = NULL; if( im == IMH_NOMOD ) { DCStatus( DS_FAIL ); return( NULL ); } switch( IM2MODI( ii, im )->lang ) { case DR_LANG_UNKNOWN: // ret = "unknown"; ret = "c"; break; case DR_LANG_CPLUSPLUS: ret = "cpp"; break; case DR_LANG_FORTRAN: ret = "fortran"; break; case DR_LANG_C: ret = "c"; break; } return( ret ); }
dip_status DIPENTRY DIPImpCueAdjust( imp_image_handle *ii, imp_cue_handle *ic, int adj, imp_cue_handle *aic ) { cv_directory_entry *cde; dip_status status; dip_status ok; cde = FindDirEntry( ii, ic->im, sstSrcModule ); if( cde == NULL ) { DCStatus( DS_ERR|DS_INFO_INVALID ); return( DS_ERR|DS_INFO_INVALID ); } *aic = *ic; ok = DS_OK; while( adj > 0 ) { status = AdjForward( ii, cde->lfo, aic ); if( status & DS_ERR ) return( status ); if( status != DS_OK ) ok = status; --adj; } while( adj < 0 ) { status = AdjBackward( ii, cde->lfo, aic ); if( status & DS_ERR ) return( status ); if( status != DS_OK ) ok = status; ++adj; } return( ok ); }
static bool InitPageDir( imp_image_handle *ii, unsigned dir_idx ) { ii->virt[dir_idx] = DCAllocZ( sizeof( virt_page * ) * DIR_SIZE ); if( ii->virt[dir_idx] == NULL ) { DCStatus( DS_ERR | DS_NO_MEM ); return( FALSE ); } return( TRUE ); }
dip_status DIGENTRY DIPImpTypeArrayInfo( imp_image_handle *ii, imp_type_handle *array, location_context *lc, array_info *ai, imp_type_handle *index ) { /* Given an implemenation type handle that represents an array type, get information about the array shape and index type. The location context is for variable dimensioned arrays again. The 'index' parameter is filled in with the type of variable used to subscript the array. It may be NULL, in which case no information is returned. */ DRSetDebug( ii->dwarf->handle ); /* must do at each call into dwarf */ if( array->state == DF_NOT ) { InitTypeHandle( ii, array, lc ); } if( array->state == DF_NOT ) { DCStatus( DS_ERR | DS_BAD_PARM ); return( DS_ERR | DS_BAD_PARM ); } if( array->typeinfo.kind != DR_TYPEK_ARRAY ) { DCStatus( DS_ERR | DS_BAD_PARM ); return( DS_ERR | DS_BAD_PARM ); } ai->low_bound = array->array.low; ai->num_elts = array->array.num_elts; ai->num_dims = array->array.dims; ai->column_major = array->array.column_major; ai->stride = array->array.base_stride; if( index != NULL ) { index->im = array->im; if( array->array.index == DR_HANDLE_NUL ) { //Fake a type up index->state = DF_SET; index->type = DR_HANDLE_NUL; index->typeinfo.size = 0; index->typeinfo.kind = DR_TYPEK_NONE; index->typeinfo.mclass = DR_MOD_NONE; } else { index->state = DF_NOT; index->type = array->array.index; } } return( DS_OK ); }
dip_status VMInit( imp_image_handle *ii, unsigned long size ) { ii->vm_dir_num = BLOCK_FACTOR( size, DIR_SIZE * VM_PAGE_SIZE ); ii->virt = DCAllocZ( ii->vm_dir_num * sizeof( ii->virt ) ); if( ii->virt == NULL ) { DCStatus( DS_ERR|DS_NO_MEM ); return( DS_ERR|DS_NO_MEM ); } return( DS_OK ); }
static int InitPageDir( imp_image_handle *iih, unsigned dir_idx ) { iih->virt[dir_idx] = DCAlloc( sizeof( virt_page * ) * DIR_SIZE ); if( iih->virt[dir_idx] == NULL ) { DCStatus( DS_ERR | DS_NO_MEM ); return( 0 ); } memset( iih->virt[dir_idx], 0, sizeof( virt_page * ) * DIR_SIZE ); return( 1 ); }
search_result SearchMbr( imp_image_handle *ii, imp_type_handle *it, lookup_item *li, void *d ) //Search for matching lookup item { dr_handle btype; type_wlk_lookup df; df_cleaner cleanup; DRSetDebug( ii->dwarf->handle ); /* must do at each call into dwarf */ if( it->state == DF_NOT ) { if( DRGetTypeInfo( it->type, &it->typeinfo ) ) { it->state = DF_SET; } } if( it->state == DF_NOT ) { return( SR_NONE ); } df.com.im = it->im; df.com.ii = ii; df.com.d = d; df.com.root = it->type; df.com.inh = DR_HANDLE_NUL; df.com.vbase = NULL; cleanup.rtn = FreeBases; //push cleanup cleanup.d = &df.com.vbase; cleanup.prev = Cleaners; Cleaners = &cleanup; btype = DRSkipTypeChain( it->type ); if( li->case_sensitive ) { df.comp = memcmp; } else { df.comp = memicmp; } df.li = li; df.sr = SR_NONE; switch( it->typeinfo.kind ) { case DR_TYPEK_ENUM: df.com.sclass = SYM_ENUM; df.com.einfo.size = it->typeinfo.size; df.com.einfo.sign = it->typeinfo.modifier.sign; DRWalkEnum( btype, AEnumMemLookup, &df ); break; case DR_TYPEK_STRUCT: case DR_TYPEK_UNION: case DR_TYPEK_CLASS: df.com.sclass = SYM_MEM; DRWalkStruct( btype, StrucWlkLookup, &df ); break; default: DCStatus( DS_ERR | DS_BAD_PARM ); df.sr = SR_FAIL; } FreeBases( &df.com.vbase ); // free virtual base list Cleaners = cleanup.prev; // pop cleanup return( df.sr ); }
size_t DIGENTRY DIPImpModName( imp_image_handle *ii, imp_mod_handle im, char *buff, size_t buff_size ) { char *name; size_t len; if( im == IMH_NOMOD || (name = IMH2MODI( ii, im )->name) == NULL ) { DCStatus( DS_FAIL ); return( 0 ); } len = NameCopy( buff, name, buff_size, 0 ); return( len ); }
unsigned DIGENTRY DIPImpModName( imp_image_handle *ii, imp_mod_handle im, char *buff, unsigned max ) { char *name; unsigned len; if( im == IMH_NOMOD || (name = IM2MODI( ii, im )->name) == NULL ) { DCStatus( DS_FAIL ); return( 0 ); } len = NameCopy( buff, name, max ); return( len ); }
extern walk_result WalkTypeSymList( imp_image_handle *ii, imp_type_handle *it, IMP_SYM_WKR *wk, imp_sym_handle *is, void *d ) { dr_handle btype; type_wlk_wlk df; df_cleaner cleanup; DRSetDebug( ii->dwarf->handle ); /* must do at each call into dwarf */ if( it->state == DF_NOT ) { if( DRGetTypeInfo( it->type, &it->typeinfo ) ) { it->state = DF_SET; } } if( it->state == DF_NOT ) { return( WR_STOP ); } df.com.im = it->im; df.com.ii = ii; df.com.d = d; df.com.root = it->type; df.com.inh = DR_HANDLE_NUL; df.com.vbase = NULL; cleanup.rtn = FreeBases; //push cleanup cleanup.d = &df.com.vbase; cleanup.prev = Cleaners; Cleaners = &cleanup; btype = DRSkipTypeChain( it->type ); df.is = is; df.wk = wk; df.wr = WR_CONTINUE; switch( it->typeinfo.kind ) { case DR_TYPEK_ENUM: df.com.sclass = SYM_ENUM; df.com.einfo.size = it->typeinfo.size; df.com.einfo.sign = it->typeinfo.modifier.sign; DRWalkEnum( btype, AEnumMem, &df ); break; case DR_TYPEK_STRUCT: case DR_TYPEK_UNION: case DR_TYPEK_CLASS: df.com.sclass = SYM_MEM; DRWalkStruct( btype, StrucWlk, &df ); break; default: DCStatus( DS_ERR | DS_BAD_PARM ); df.wr = WR_STOP; } FreeBases( &df.com.vbase ); // free virtual base list Cleaners = cleanup.prev; // pop cleanup return( df.wr ); }
dip_status DIGENTRY DIPImpModInfo( imp_image_handle *ii, imp_mod_handle im, handle_kind hk ) { /* Return DS_OK if the module has the kind of information indicated by 'hk', DS_FAIL if it does not. */ dip_status ret; dr_handle stmts; mod_info *modinfo; ret = DS_FAIL; if( im == IMH_NOMOD ) { DCStatus( ret ); return( ret ); } modinfo = IM2MODI( ii, im ); switch( hk ) { case HK_IMAGE: break; case HK_TYPE: if( modinfo->stmts != 0 ) { ret = DS_OK; } break; case HK_CUE: stmts = modinfo->stmts; if( stmts != 0 ) { // need to get rid of stmts for file with no cues l_walk_info walk; address a; walk.ii = ii; walk.im = im; walk.ret = &a; DRSetDebug( ii->dwarf->handle ); /* set dwarf to image */ if( !DRWalkLines( stmts, SEG_CODE, ALineCue, &walk ) ) { ret = DS_OK; } } break; case HK_SYM: /* if no lang assumed linker generated */ if( modinfo->lang != DR_LANG_UNKNOWN ) { ret = DS_OK; } break; default: break; } return( ret ); }
address DIGENTRY DIPImpModAddr( imp_image_handle *ii, imp_mod_handle im ) { l_walk_info walk; address a; dr_handle stmts; if( im != IMH_NOMOD && (stmts = IM2MODI( ii, im )->stmts) != 0 ) { DRSetDebug( ii->dwarf->handle ); /* must do at each call into dwarf */ walk.ii = ii; walk.im = im; walk.ret = &a; if( !DRWalkLines( stmts, SEG_CODE, AModAddr, &walk ) ) { // found return( a ); } } DCStatus( DS_FAIL ); return( NilAddr ); }
static bool AMemLookup( dr_handle var, int index, void *_d ) /**********************************************************/ { type_wlk_lookup *d = _d; imp_sym_handle *is; char *name; unsigned len; name = DRGetName( var ); if( name == NULL ) { DCStatus( DS_FAIL ); return( FALSE ); } len = strlen( name ); if( len == d->li->name.len && d->comp( name, d->li->name.start, len ) == 0 ) { is = DCSymCreate( d->com.ii, d->com.d ); SetSymHandle( (type_wlk *)d, is ); is->sym = var; switch( index ) { case 0: is->sclass = SYM_MEM; break; case 2: is->sclass = SYM_MEMVAR; // static member break; case 3: if( DRGetVirtuality( var ) == DR_VIRTUALITY_VIRTUAL ) { is->sclass = SYM_VIRTF; // virtual func } else if( !DRIsSymDefined( var ) ) { is->sclass = SYM_MEMF; // memfunc decl } else { is->sclass = SYM_MEMVAR; // inlined defn treat like a var } break; } d->sr = SR_EXACT; } DCFree( name ); return( TRUE ); }
walk_result DIPIMPENTRY( WalkFileList )( imp_image_handle *ii, imp_mod_handle im, DIP_IMP_CUE_WALKER *wk, imp_cue_handle *ic, void *d ) /*************************************************************************/ { file_walk_cue wlk; drmem_hdl stmts; DRSetDebug( ii->dwarf->handle ); /* must do at each call into DWARF */ stmts = IMH2MODI( ii, im )->stmts; if( stmts == DRMEM_HDL_NULL ) { DCStatus( DS_FAIL ); return( WR_CONTINUE ); } wlk.stmts = stmts; wlk.ii = ii; wlk.im = im; wlk.wk = wk; wlk.ic = ic; wlk.d = d; wlk.wr = WR_CONTINUE; DRWalkLFiles( stmts, ACueFileNum, &wlk, ACueDir, NULL ); return( wlk.wr ); }
static bool AEnumMemLookup( dr_handle var, int index, void *_d ) /**************************************************************/ { type_wlk_lookup *d = _d; imp_sym_handle *is; char *name; unsigned len; index = index; name = DRGetName( var ); if( name == NULL ) { DCStatus( DS_FAIL ); return( FALSE ); } len = strlen( name ); if( len == d->li->name.len && d->comp( name, d->li->name.start, len ) == 0 ) { is = DCSymCreate( d->com.ii, d->com.d ); SetSymHandle( (type_wlk *)d, is ); is->sym = var; d->sr = SR_EXACT; } DCFree( name ); return( TRUE ); }
search_result DoLookupSym( imp_image_handle *ii, symbol_source ss, void *source, lookup_item *li, location_context *lc, void *d ) { imp_mod_handle im; search_result sr; lookup_item item; char *buff; char *src; char *dst; unsigned len; unsigned op_len; imp_sym_handle *scope_is; if( *li->name.start == SH_ESCAPE ) { CollectSymHdl( (byte *)li->name.start, DCSymCreate( ii, d ) ); return( SR_EXACT ); } if( li->type == ST_NAMESPACE ) return( SR_NONE ); item = *li; if( ss == SS_SCOPESYM ) { scope_is = source; len = ImpInterface.sym_name( ii, scope_is, NULL, SN_SOURCE, NULL, 0 ); item.scope.start = __alloca( len + 1 ); ImpInterface.sym_name( ii, scope_is, NULL, SN_SOURCE, item.scope.start, len + 1 ); item.scope.len = len; ss = SS_MODULE; item.mod = scope_is->im; source = &item.mod; } if( item.type == ST_OPERATOR ) { src = item.name.start; len = item.name.len; buff = __alloca( len + 20 ); dst = buff; for( ;; ) { if( len == 0 ) break; if( src == item.source.start ) { op_len = __mangle_operator( src, item.source.len, buff ); if( op_len == 0 ) { DCStatus( DS_ERR|DS_INVALID_OPERATOR ); return( SR_NONE ); } dst += op_len; src += item.source.len; len -= item.source.len; } else { *dst++ = *src++; --len; } } item.name.len = dst - buff; item.name.start = buff; } sr = SR_NONE; switch( ss ) { case SS_SCOPED: if( ImpInterface.addr_mod( ii, *(address *)source, &im ) == SR_NONE ) { im = item.mod; } else if( item.mod == NO_MOD || item.mod == im ) { if( !item.file_scope && item.type == ST_NONE ) { sr = SearchLclScope( ii, im, (address *)source, &item, d ); } } else { im = item.mod; } if( im != NO_MOD && sr == SR_NONE ) { sr = SearchFileScope( ii, im, &item, d ); } break; case SS_MODULE: im = *(imp_mod_handle *)source; if( item.mod == NO_MOD || item.mod == im ) { sr = SearchFileScope( ii, im, &item, d ); } break; case SS_TYPE: if( item.mod != NO_MOD ) return( SR_NONE ); switch( item.type ) { case ST_TYPE: case ST_STRUCT_TAG: case ST_CLASS_TAG: case ST_UNION_TAG: case ST_ENUM_TAG: return( SR_NONE ); } return( SearchMbr( ii, (imp_type_handle *)source, &item, d ) ); } if( sr == SR_NONE ) { switch( item.type ) { case ST_NONE: case ST_DESTRUCTOR: case ST_OPERATOR: sr = SearchGbl( ii, im, (imp_mod_handle)item.mod, &item, d ); break; } } return( sr ); }
/* Adjust the 'src' cue by 'adj' amount and return the result in 'dst'. That is, If you get called with "DIPImpCueAdjust( ii, src, 1, dst )", the 'dst' handle should be filled in with implementation cue handle representing the source cue immediately following the 'src' cue. Passing in an 'adj' of -1 will get the immediately preceeding source cue. The list of source cues for each file are considered a ring, so if 'src' is the first cue in a file, an 'adj' of -1 will return the last source cue FOR THAT FILE. The cue adjust never crosses a file boundry. Also, if 'src' is the last cue in a file, and 'adj' of 1 will get the first source cue FOR THAT FILE. If an adjustment causes a wrap from begining to end or vice versa, you should return DS_WRAPPED status (NOTE: DS_ERR should *not* be or'd in, nor should DCStatus be called in this case). Otherwise DS_OK should be returned unless an error occurred. */ dip_status DIPIMPENTRY( CueAdjust )( imp_image_handle *ii, imp_cue_handle *src, int adj, imp_cue_handle *dst ) /*****************************************************************/ { drmem_hdl stmts; dfline_search start_state; dfline_find find; dip_status ret; cue_item cue; cue_list *cue_map; address map_addr; DRSetDebug( ii->dwarf->handle ); /* must do at each call into DWARF */ stmts = IMH2MODI( ii, src->im )->stmts; if( stmts == DRMEM_HDL_NULL ) { DCStatus( DS_FAIL ); return( DS_ERR|DS_FAIL ); } cue_map = ii->cue_map; if( cue_map->im != src->im ) { ResetCueInfo( cue_map ); cue_map->im = src->im; map_addr = NilAddr; LoadCueMap( stmts, &map_addr, cue_map ); } if( adj < 0 ) { start_state = LOOK_LOW; adj = -adj; } else { start_state = LOOK_HIGH; } cue.fno = src->fno; cue.line = src->line; cue.col = src->col; cue.mach = src->a.mach; find = LINE_NOT; while( 0 != adj ) { find = FindCue( cue_map, &cue, start_state ); if( find == LINE_NOT ) break; --adj; } dst->im = src->im; dst->fno = cue.fno; dst->line = cue.line; dst->col = cue.col; dst->a.mach = cue.mach; ret = DS_FAIL; switch( find ) { case LINE_NOT: DCStatus( DS_FAIL ); ret = DS_ERR | DS_FAIL; break; case LINE_WRAPPED: ret = DS_WRAPPED; break; case LINE_FOUND: ret = DS_OK; break; } return( ret ); }
/* * AllocLinkTable - allocate the demand load link table * */ static dip_status AllocLinkTable( section_info *inf, unsigned long num_links, unsigned long first_link ) { dword **lnk_tbl; dword *lnk; mod_table *tbl; unsigned num; unsigned long count; unsigned i; unsigned d; mod_info *mod; unsigned tbl_entries; dword end; info_block *blk; tbl_entries = ((num_links+(MAX_LINK_ENTRIES-1)) / MAX_LINK_ENTRIES) + 1; lnk_tbl = DCAlloc( tbl_entries * sizeof( dword * ) ); if( lnk_tbl == NULL ) { DCStatus( DS_ERR|DS_NO_MEM ); return( DS_ERR|DS_NO_MEM ); } for( i = 0; i < tbl_entries; ++i ) lnk_tbl[i] = NULL; inf->dmnd_link = lnk_tbl; i = 0; count = num_links; while( count != 0 ) { num = (count>MAX_LINK_ENTRIES) ? MAX_LINK_ENTRIES : count; lnk = DCAlloc( num*sizeof(dword)); if( lnk == NULL ) { DCStatus( DS_ERR|DS_NO_MEM ); return( DS_ERR|DS_NO_MEM ); } lnk_tbl[i++] = lnk; if( !inf->ctl->v2 ) { if( DCRead(inf->ctl->sym_file,lnk,num*sizeof(dword))!=num*sizeof(dword)) { DCStatus( DS_ERR|DS_FREAD_FAILED ); return( DS_ERR|DS_FREAD_FAILED ); } } count -= num; } lnk = *lnk_tbl; num = 0; count = 0; for( d = DMND_FIRST; d < DMND_NUM; ++d ) { for( blk = inf->mod_info; blk != NULL; blk = blk->next ) { tbl = blk->link; for( i = 0; i < tbl->count; ++i ) { mod = (mod_info *)((byte *)blk->info + tbl->mod_off[i]); if( inf->ctl->v2 ) { if( mod->di[d].u.size != 0 ) { if( num >= MAX_LINK_ENTRIES ) { lnk = *++lnk_tbl; num = 0; } lnk[num] = mod->di[d].info_off; end = lnk[num] + mod->di[d].u.size; mod->di[d].u.entries = 1; mod->di[d].info_off = count; ++num; ++count; } } else { if( mod->di[d].u.entries != 0 ) { mod->di[d].info_off = (mod->di[d].info_off-first_link)/sizeof(dword); } } } } } if( inf->ctl->v2 ) { if( num >= MAX_LINK_ENTRIES ) { lnk = *++lnk_tbl; num = 0; } lnk[num] = end; } return( DS_OK ); }
/* * AdjustMods - adjust the demand info offsets in all the modules * - allocate module index table * - allocate demand load link table */ dip_status AdjustMods( section_info *inf, unsigned long adjust ) { info_block *blk; unsigned count; unsigned mod_off; mod_table *tbl; mod_info *mod; unsigned long num_links; unsigned long first_link; unsigned long last_link; unsigned d; unsigned num; dword *lnk; dword **lnk_tbl; unsigned long off; dip_status ok; last_link = 0; first_link = ~0; num_links = 1; for( blk = inf->mod_info; blk != NULL; blk = blk->next ) { count = 0; for( mod_off = 0; mod_off < blk->size; mod_off += sizeof( mod_info ) + mod->name[0] ) { ++count; mod = (mod_info *)((byte *)blk->info + mod_off); } tbl = DCAlloc( sizeof(mod_table) + (count-1)*sizeof(mod_info *) ); if( tbl == NULL ) { DCStatus( DS_ERR|DS_NO_MEM ); return( DS_ERR|DS_NO_MEM ); } tbl->count = count; blk->link = tbl; count = 0; for( mod_off = 0; mod_off < blk->size; mod_off += sizeof( mod_info ) + mod->name[0] ) { tbl->mod_off[count++] = mod_off; mod = (mod_info *)((byte *)blk->info + mod_off); for( d = DMND_FIRST; d < DMND_NUM; ++d ) { if( inf->ctl->v2 ) { if( mod->di[d].u.size != 0 ) ++num_links; } else { if( mod->di[d].u.entries != 0 ) { num_links = mod->di[d].info_off; if( num_links < first_link ) { first_link = num_links; } num_links += mod->di[d].u.entries * sizeof(dword); if( num_links > last_link ) { last_link = num_links; } } } } } } if( !inf->ctl->v2 ) { off = first_link + adjust; if( DCSeek( inf->ctl->sym_file, off, DIG_ORG) != off ) { DCStatus( DS_ERR|DS_FSEEK_FAILED ); return( DS_ERR|DS_FSEEK_FAILED ); } num_links = (last_link - first_link) / sizeof( dword ) + 2; } ok = AllocLinkTable( inf, num_links, first_link ); if( ok != DS_OK ) return( ok ); num = 0; lnk_tbl = inf->dmnd_link; lnk = *lnk_tbl; for( ;; ) { if( num_links == 0 ) break; if( num >= MAX_LINK_ENTRIES ) { lnk = *++lnk_tbl; num = 0; } /* * shift over one bit so as to leave the lower bit * clear for testing if it is allocated or not */ lnk[num] = (lnk[num] + adjust) << 1; ++num; --num_links; } return( DS_OK ); }
search_result DIPIMPENTRY( LineCue )( imp_image_handle *ii, imp_mod_handle im, cue_fileid file, unsigned long line, unsigned column, imp_cue_handle *ic ) /**********************************************************************/ { search_result ret; dfline_find find; dfline_search what; drmem_hdl stmts; cue_list *cue_map; address map_addr; cue_item cue; if( im == IMH_NOMOD ) { DCStatus( DS_FAIL ); return( SR_NONE ); } DRSetDebug( ii->dwarf->handle ); /* must do at each call into DWARF */ stmts = IMH2MODI( ii, im )->stmts; if( stmts == DRMEM_HDL_NULL ) { return( SR_NONE ); } cue_map= ii->cue_map; if( cue_map->im != im ) { ResetCueInfo( cue_map ); cue_map->im = im; map_addr = NilAddr; LoadCueMap( stmts, &map_addr, cue_map ); } if( file == 0 ) { // primary file cue.fno = 1; } else { cue.fno = (uint_16)file; } cue.line = line; cue.col = (uint_16)column; cue.mach.offset = 0; cue.mach.segment = 0; ic->a = NilAddr; if( line == 0 ) { what = LOOK_FILE; } else { what = LOOK_CLOSEST; } find = FindCue( cue_map, &cue, what ); ic->im = im; ic->fno = cue.fno; ic->line = cue.line; ic->col = cue.col; ic->a.mach = cue.mach; ret = SR_NONE; switch( find ) { case LINE_CLOSEST: ret = SR_CLOSEST; break; case LINE_FOUND: ret = SR_EXACT; break; case LINE_NOT: ret = SR_NONE; break; } return( ret ); }
static search_result DoLookupSym( imp_image_handle *ii, symbol_source ss, void *source, lookup_item *li, location_context *lc, void *d ) { imp_mod_handle im; search_result sr; lookup_item sym_li; char *buff; const char *src; char *dst; size_t len; unsigned op_len; imp_sym_handle *scope_is; lc = lc; if( GETU8( li->name.start ) == SH_ESCAPE ) { CollectSymHdl( li->name.start, DCSymCreate( ii, d ) ); return( SR_EXACT ); } if( li->type == ST_NAMESPACE ) return( SR_NONE ); sym_li = *li; if( ss == SS_SCOPESYM ) { char *scope_name; scope_is = source; len = ImpInterface.SymName( ii, scope_is, NULL, SN_SOURCE, NULL, 0 ); scope_name = __alloca( len + 1 ); ImpInterface.SymName( ii, scope_is, NULL, SN_SOURCE, scope_name, len + 1 ); sym_li.scope.start = scope_name; sym_li.scope.len = len; ss = SS_MODULE; sym_li.mod = IMH2MH( scope_is->im ); source = &sym_li.mod; } if( sym_li.type == ST_OPERATOR ) { src = sym_li.name.start; len = sym_li.name.len; buff = __alloca( len + 20 ); dst = buff; for( ;; ) { if( len == 0 ) break; if( src == sym_li.source.start ) { op_len = __mangle_operator( src, sym_li.source.len, buff ); if( op_len == 0 ) { DCStatus( DS_ERR|DS_INVALID_OPERATOR ); return( SR_NONE ); } dst += op_len; src += sym_li.source.len; len -= sym_li.source.len; } else { *dst++ = *src++; --len; } } sym_li.name.len = dst - buff; sym_li.name.start = buff; } sr = SR_NONE; im = IMH_NOMOD; switch( ss ) { case SS_SCOPED: if( ImpInterface.AddrMod( ii, *(address *)source, &im ) == SR_NONE ) { im = MH2IMH( sym_li.mod ); } else if( MH2IMH( sym_li.mod ) == IMH_NOMOD || MH2IMH( sym_li.mod ) == im ) { if( !sym_li.file_scope && sym_li.type == ST_NONE ) { sr = SearchLclScope( ii, im, (address *)source, &sym_li, d ); } } else { im = MH2IMH( sym_li.mod ); } if( im != IMH_NOMOD && sr == SR_NONE ) { sr = SearchFileScope( ii, im, &sym_li, d ); } break; case SS_MODULE: im = *(imp_mod_handle *)source; if( MH2IMH( sym_li.mod ) == IMH_NOMOD || MH2IMH( sym_li.mod ) == im ) { sr = SearchFileScope( ii, im, &sym_li, d ); } break; case SS_TYPE: if( MH2IMH( sym_li.mod ) != IMH_NOMOD ) return( SR_NONE ); switch( sym_li.type ) { case ST_TYPE: case ST_STRUCT_TAG: case ST_CLASS_TAG: case ST_UNION_TAG: case ST_ENUM_TAG: return( SR_NONE ); } return( SearchMbr( ii, (imp_type_handle *)source, &sym_li, d ) ); } if( sr == SR_NONE ) { switch( sym_li.type ) { case ST_NONE: case ST_DESTRUCTOR: case ST_OPERATOR: sr = SearchGbl( ii, im, MH2IMH( sym_li.mod ), &sym_li, d ); break; } } return( sr ); }
search_result DIPIMPENTRY( AddrCue )( imp_image_handle *ii, imp_mod_handle im, address addr, imp_cue_handle *ic ) /*******************************************************************/ { /* Search for the closest cue in the given module that has an address * less then or equal to the given address. If there is no such cue * return SR_NONE. If there is one exactly at the address return * SR_EXACT. Otherwise, return SR_CLOSEST. */ address map_addr; search_result ret; cue_list *cue_map; cue_item cue; drmem_hdl stmts; if( im == IMH_NOMOD ) { DCStatus( DS_FAIL ); return( SR_NONE ); } DRSetDebug( ii->dwarf->handle ); /* must do at each call into dwarf */ stmts = IMH2MODI( ii, im )->stmts; if( stmts == DRMEM_HDL_NULL ) { return( SR_NONE ); } map_addr = addr; cue_map = ii->cue_map; Real2Map( ii->addr_map, &map_addr ); if( cue_map->im != im ) { ResetCueInfo( cue_map ); cue_map->im = im; LoadCueMap( stmts, &map_addr, cue_map ); } ic->im = im; ic->fno = 0; ic->line = 0; ic->col = 0; ic->a = NilAddr; ret = SR_NONE; if( map_addr.mach.segment == cue_map->last.mach.segment && map_addr.mach.offset >= cue_map->last.mach.offset && map_addr.mach.offset < cue_map->last.next_offset ) { ic->fno = cue_map->last.fno; ic->line = cue_map->last.line; ic->col = cue_map->last.col; ic->a.mach = cue_map->last.mach; if( cue_map->last.mach.offset == map_addr.mach.offset ) { ret = SR_EXACT; } else { ret = SR_CLOSEST; } return( ret ); } if( FindCueOffset( cue_map, &map_addr.mach, &cue ) ) { ic->fno = cue.fno; ic->line = cue.line; ic->col = cue.col; ic->a.mach = cue.mach; if( cue.mach.offset == map_addr.mach.offset ) { ret = SR_EXACT; } else { ret = SR_CLOSEST; } cue_map->last = cue; } return( ret ); }
/* * Load debug info if it's in the HLL/CV format. */ dip_status DIGENTRY DIPImpLoadInfo( dig_fhandle h, imp_image_handle *ii ) { dip_status rc; /* Init the module handle. */ memset( ii, 0, sizeof( *ii ) ); ii->mad = MAD_X86; /* No known non-x86 support */ ii->sym_file = h; ii->is_32bit = 1; ii->format_lvl = HLL_LVL_NB04; ii->next_image = ImageList; ImageList = ii; /* Read basic HLL and executable image bits. */ rc = FindHLL( ii ); if( rc == DS_OK ) { rc = VMInit( ii, ii->size ); } /* Make sure we've got segment mappings. (FIXME: scan module headers) */ if( rc == DS_OK && !ii->segments ) { ii->seg_count = 2; ii->segments = DCAlloc( sizeof( hllinfo_seg ) * ii->seg_count ); if( ii->segments != NULL ) { memset( ii->segments, 0, sizeof( hllinfo_seg ) * ii->seg_count ); ii->segments[0].is_executable = 1; ii->segments[0].map.segment = 1; ii->segments[1].map.segment = 2; ii->segments[0].size = ii->segments[1].size = 0x00400000; /* 4MB */ ii->segments[0].address = ii->segments[1].address = 0; } else{ rc = DS_ERR | DS_NO_MEM; } } /* Locate global types. If none, we've types per module. */ if( rc == DS_OK ) { /* FIXME hll_debug_dir *cde; cde = FindDirEntry( ii, IMH_GBL, sstGlobalTypes ); if( cde != NULL ) { hdr = VMBlock( ii, cde->lfo, sizeof( *hdr ) ); if( hdr == NULL ) { Cleanup( ii ); return( DS_ERR | DS_FAIL ); } ii->types_base = cde->lfo + offsetof( cv_sst_global_types_header, offType ) + hdr->cType * sizeof( hdr->offType[0] ); } */ } /* We're done - clean up on failure. */ if( rc != DS_OK ) { DCStatus( rc ); Cleanup( ii ); } return( rc ); }