search_result SearchFile( imp_image_handle *ii, address addr, imp_cue_handle *ic, virt_mem file_base, cv_directory_entry *cde, addr_off *best_offset) { cv_sst_src_module_file_table *fp; cv_sst_src_module_line_number *lp; virt_mem line_base; off_range *ranges; unsigned_32 *lines; unsigned num_segs; unsigned seg_idx; address curr_addr; unsigned pair; fp = VMBlock( ii, file_base, sizeof( *fp ) ); if( fp == NULL ) return( SR_NONE ); num_segs = fp->cSeg; fp = VMBlock( ii, file_base, sizeof( *fp ) + num_segs * (sizeof( unsigned_32 ) + sizeof( off_range ) ) ); if( fp == NULL ) return( SR_NONE ); ranges = __alloca( num_segs * sizeof( *ranges ) ); lines = __alloca( num_segs * sizeof( *lines ) ); memcpy( lines, &fp->baseSrcLn[0], num_segs * sizeof( *lines ) ); memcpy( ranges, &fp->baseSrcLn[num_segs], num_segs * sizeof( *ranges ) ); for( seg_idx = 0; seg_idx < num_segs; ++seg_idx ) { line_base = lines[seg_idx] + cde->lfo; lp = VMBlock( ii, line_base, sizeof( *lp ) ); if( lp == NULL ) return( SR_NONE ); curr_addr.mach.segment = lp->Seg; curr_addr.mach.offset = 0; MapLogical( ii, &curr_addr ); if( DCSameAddrSpace( curr_addr, addr ) != DS_OK ) continue; if( (ranges[seg_idx].start != 0 || ranges[seg_idx].end != 0) && (addr.mach.offset < ranges[seg_idx].start + curr_addr.mach.offset /* The next condition is commented out. Digital Mars tools are known to * emit buggy CV4 data where the upper range does not cover all code, * causing us to fail finding last addresses within a module. */ /*|| addr.mach.offset > ranges[seg_idx].end + curr_addr.mach.offset */ ) ) { continue; } pair = SearchOffsets( ii, line_base + offsetof( cv_sst_src_module_line_number, offset[0] ), lp->cPair, addr.mach.offset, best_offset, curr_addr.mach.offset ); if( pair != NO_IDX ) { ic->file = file_base; ic->line = line_base; ic->pair = pair; if( *best_offset == addr.mach.offset ) return( SR_EXACT ); } } /* We abuse the SR_FAIL return code to really mean SR_CONTINUE (ie. continue * searching other files). A SR_CONTINUE code is not defined because it does * not make sense as a return value for DIPImpAddrCue() */ return( SR_FAIL ); }
static walk_result FindAddr( imp_image_handle *ii, cv_directory_entry *cde, void *d ) { struct find_mod *md = d; address *a; address code; cv_sst_module *mp; cv_seginfo *sp; int left; if( cde->subsection != sstModule ) return( WR_CONTINUE ); a = md->d; mp = VMBlock( ii, cde->lfo, cde->cb ); if( mp == NULL ) return( WR_CONTINUE ); if( mp->ovlNumber != a->sect_id ) return( WR_CONTINUE ); sp = &mp->SegInfo[0]; left = mp->cSeg; for( ;; ) { if( left <= 0 ) return( WR_CONTINUE ); code.mach.segment = sp->Seg; code.mach.offset = sp->offset; MapLogical( ii, &code ); if( code.mach.segment == a->mach.segment && code.mach.offset <= a->mach.offset && (code.mach.offset+sp->cbSeg) > a->mach.offset ) { md->im = cde->iMod; return( WR_STOP ); } ++sp; --left; } }
address DIGENTRY DIPImpModAddr( imp_image_handle *ii, imp_mod_handle im ) { cv_sst_module *mp; cv_directory_entry *cde; address addr; cde = FindDirEntry( ii, im, sstModule ); if( cde == NULL ) return( NilAddr ); mp = VMBlock( ii, cde->lfo, cde->cb ); if( mp == NULL ) return( NilAddr ); if( mp->cSeg == 0 ) return( NilAddr ); addr.mach.segment = mp->SegInfo[0].Seg; addr.mach.offset = mp->SegInfo[0].offset; MapLogical( ii, &addr ); return( addr ); }
address DIPENTRY DIPImpCueAddr( imp_image_handle *ii, imp_cue_handle *ic ) { cv_sst_src_module_line_number *lp; address addr; unsigned long offset; unsigned_32 *off_p; lp = VMBlock( ii, ic->line, sizeof( *lp ) ); if( lp == NULL ) return( NilAddr ); if( lp->cPair == 0 ) return( NilAddr ); addr.mach.segment = lp->Seg; offset = offsetof( cv_sst_src_module_line_number, offset ) + (unsigned long)ic->pair * sizeof( unsigned_32 ); off_p = VMBlock( ii, ic->line + offset, sizeof( unsigned_16 ) ); if( off_p == NULL ) return( NilAddr ); addr.mach.offset = *off_p; MapLogical( ii, &addr ); return( addr ); }