hllsym.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,855 行 · 第 1/5 页
C
1,855 行
case 12:
hash_base = cde->lfo + hdr->cbSymbol + hdr->cbSymHash + sizeof( *hdr );
p = VMBlock( ii, hash_base, sizeof( unsigned_16 ) );
if( p == NULL ) return( SR_FAIL );
num_segs = *(unsigned_16 *)p;
hash_base += 2 * sizeof( unsigned_16 );
best.base = 0;
best.off = *best_off;
i = 0;
for( ;; ) {
if( i >= num_segs ) break;
chk.mach.segment = i + 1;
chk.mach.offset = 0;
MapLogical( ii, &chk );
if( DCSameAddrSpace( chk, a ) != DS_OK ) goto next_seg;
p = VMBlock( ii, hash_base + i * sizeof( unsigned_32 ), sizeof( unsigned_32 ) );
if( p == NULL ) return( SR_FAIL );
curr.base = *(unsigned_32 *)p;
base = hash_base + num_segs * sizeof( unsigned_32 );
p = VMBlock( ii, base + i * sizeof( unsigned_32 ), sizeof( unsigned_32 ) );
if( p == NULL ) return( SR_FAIL );
offset_count = *(unsigned_32 *)p;
if( offset_count == 0 ) goto next_seg;
curr.base += base + num_segs * sizeof( unsigned_32 );
//NYI: offsets are sorted, so we can binary search this sucker
count = 0;
for( ;; ) {
if( count >= offset_count ) break;
p = VMBlock( ii, curr.base + sizeof( unsigned_32 ), sizeof( unsigned_32 ) );
if( p == NULL ) return( SR_FAIL );
new_off = *(unsigned_32 *)p + chk.mach.offset;
if( new_off >= a.mach.offset ) break;
curr.off = new_off;
curr.base += 2 * sizeof( unsigned_32 );
++count;
}
if( new_off == a.mach.offset ) {
best.base = curr.base;
best.off = new_off;
break;
}
if( count != 0
&& curr.off < a.mach.offset
&& (curr.off > best.off || best.base == 0 && best.off == 0) ) {
best.base = curr.base - 2 * sizeof( unsigned_32 );
best.off = curr.off;
}
next_seg:
++i;
}
if( best.base == 0 ) return( SR_NONE );
p = VMBlock( ii, best.base, sizeof( unsigned_32 ) );
if( p == NULL ) return( SR_FAIL );
if( SymFillIn( ii, is, *(unsigned_32 *)p + cde->lfo + sizeof( *hdr ) ) != DS_OK ) {
return( SR_FAIL );
}
*best_off = best.off;
return( (best.off == a.mach.offset) ? SR_EXACT : SR_CLOSEST );
default:
//NYI: what to do when don't have hash function? */
return( SR_NONE );
}
}
static unsigned long CalcHash( char *name, unsigned len )
{
unsigned_32 end;
unsigned_32 sum;
unsigned i;
#define B_toupper( b ) ((b) & 0xdf)
#define D_toupper( d ) ((d) & 0xdfdfdfdf)
end = 0;
for( i = len & 0x3; i != 0; --i ) {
end |= B_toupper( name[ len - 1 ] );
end <<= 8;
len -= 1;
}
len /= 4;
sum = 0;
for( i = 0; i < len; ++i ) {
sum ^= D_toupper( *(unsigned_32 *)name );
sum = _lrotl( sum, 4 );
name += 4;
}
return( sum ^ end );
}
typedef search_result SEARCH_CREATOR( imp_image_handle *, s_all *, imp_sym_handle *, void * );
static search_result TableSearchForName( imp_image_handle *ii,
int case_sense, char *li_name, unsigned li_len,
unsigned long hash, imp_sym_handle *is,
SEARCH_CREATOR *create, void *d, unsigned tbl_type )
{
cv_directory_entry *cde;
cv_sst_global_pub_header *hdr;
void *p;
unsigned i;
unsigned hash_buckets;
virt_mem hash_base;
virt_mem base;
virt_mem sym_base;
unsigned long count;
char *name;
unsigned name_len;
s_all *sp;
search_result sr;
cde = FindDirEntry( ii, MH_GBL, tbl_type );
if( cde == NULL ) return( SR_NONE );
hdr = VMBlock( ii, cde->lfo, sizeof( *hdr ) );
if( hdr == NULL ) return( SR_FAIL );
switch( hdr->symhash ) {
case 10:
hash_base = cde->lfo + hdr->cbSymbol + sizeof( *hdr );
p = VMBlock( ii, hash_base, sizeof( unsigned_16 ) );
if( p == NULL ) return( SR_FAIL );
hash_buckets = *(unsigned_16 *)p;
i = hash % hash_buckets;
hash_base += 2 * sizeof( unsigned_16 );
p = VMBlock( ii, hash_base + i * sizeof( unsigned_32 ), sizeof( unsigned_32 ) );
if( p == NULL ) return( SR_FAIL );
sym_base = *(unsigned_32 *)p;
base = hash_base + hash_buckets * sizeof( unsigned_32 );
p = VMBlock( ii, base + i * sizeof( unsigned_32 ), sizeof( unsigned_32 ) );
if( p == NULL ) return( SR_FAIL );
sym_base += base + hash_buckets * sizeof( unsigned_32 );
sr = SR_NONE;
for( count = *(unsigned_32 *)p; count != 0; sym_base += 2*sizeof(unsigned_32), --count ) {
p = VMBlock( ii, sym_base, 2 * sizeof( unsigned_32 ) );
if( p == NULL ) return( SR_FAIL );
if( ((unsigned_32 *)p)[1] != hash ) continue;
if( SymFillIn( ii, is, *(unsigned_32 *)p + cde->lfo + sizeof( *hdr ) ) != DS_OK ) {
return( SR_FAIL );
}
if( SymGetName( ii, is, &name, &name_len, &sp ) != DS_OK ) {
return( SR_FAIL );
}
if( name_len != li_len ) continue;
if( case_sense ) {
if( memcmp( li_name, name, name_len ) != 0 ) continue;
} else {
if( memicmp( li_name, name, name_len ) != 0 ) continue;
}
/* Got one! */
switch( create( ii, sp, is, d ) ) {
case SR_FAIL:
return( SR_FAIL );
case SR_CLOSEST:
/* means we found one, but keep on going */
sr = SR_EXACT;
break;
case SR_EXACT:
return( SR_EXACT );
}
}
return( sr );
default:
//NYI: What to do if don't have hash table
return( SR_NONE );
}
}
struct match_data {
unsigned idx;
};
static search_result MatchSym( imp_image_handle *ii, s_all *p,
imp_sym_handle *is, void *d )
{
struct match_data *md = d;
is = is;
if( md->idx != SymTypeIdx( ii, p ) ) return( SR_NONE );
return( SR_EXACT );
}
dip_status SymFindMatchingSym( imp_image_handle *ii,
char *name, unsigned len, unsigned idx, imp_sym_handle *is )
{
unsigned long hash;
search_result sr;
struct match_data data;
data.idx = idx;
hash = CalcHash( name, len );
sr = TableSearchForName( ii, 1, name, len, hash, is, MatchSym, &data,
sstStaticSym );
switch( sr ) {
case SR_FAIL: return( DS_ERR|DS_FAIL );
case SR_EXACT: return( DS_OK );
}
sr = TableSearchForName( ii, 1, name, len, hash, is, MatchSym, &data,
sstGlobalSym );
switch( sr ) {
case SR_FAIL: return( DS_ERR|DS_FAIL );
case SR_EXACT: return( DS_OK );
}
return( DS_FAIL );
}
static walk_result TableWalkSym( imp_image_handle *ii, imp_sym_handle *is,
IMP_SYM_WKR *wk, void *d, unsigned tbl_type )
{
cv_directory_entry *cde;
cv_sst_global_pub_header *hdr;
virt_mem base;
virt_mem end;
unsigned skip;
s_all *p;
walk_result wr;
search_result sr;
address addr;
imp_sym_handle dummy;
addr_off dummy_off;
is->im = MH_GBL;
cde = FindDirEntry( ii, MH_GBL, tbl_type );
if( cde == NULL ) return( WR_CONTINUE );
hdr = VMBlock( ii, cde->lfo, sizeof( *hdr ) );
if( hdr == NULL ) return( WR_FAIL );
base = cde->lfo + sizeof( *hdr );
end = base + hdr->cbSymbol;
while( base < end ) {
p = VMRecord( ii, base );
skip = p->common.length + sizeof( p->common.length );
switch( p->common.code ) {
case S_ALIGN:
case S_PROCREF:
case S_DATAREF:
/* not interested */
break;
case S_PUB16:
case S_PUB32:
if( p->common.code == S_PUB16 ) {
addr.mach.offset = p->pub16.f.offset;
addr.mach.segment = p->pub16.f.segment;
} else {
addr.mach.offset = p->pub32.f.offset;
addr.mach.segment = p->pub32.f.segment;
}
MapLogical( ii, &addr );
dummy_off = 0;
sr = TableSearchForAddr( ii, addr, &dummy, &dummy_off, sstGlobalSym );
if( sr == SR_FAIL ) return( WR_FAIL );
if( sr == SR_EXACT ) break;
/* fall through */
default:
if( SymFillIn( ii, is, base ) != DS_OK ) return( WR_FAIL );
wr = wk( ii, SWI_SYMBOL, is, d );
if( wr != WR_CONTINUE ) return( wr );
break;
}
base += skip;
}
return( WR_CONTINUE );
}
struct glue_info {
IMP_SYM_WKR *wk;
void *d;
imp_sym_handle *is;
};
static walk_result WalkGlue( imp_image_handle *ii, sym_walk_info swi,
imp_sym_handle *is, void *d )
{
struct glue_info *gd = d;
if( is == NULL ) return( gd->wk( ii, swi, NULL, gd->d ) );
*gd->is = *is;
return( gd->wk( ii, swi, gd->is, gd->d ) );
}
static walk_result WalkAModule( imp_image_handle *ii,
hll_debug_dir *hdd, void *d )
{
if( hdd->subsection != hll_sstModules ) return( WR_CONTINUE );
return( ScopeWalkFile( ii, hdd->iMod, WalkGlue, d ) );
}
walk_result DoWalkSymList( imp_image_handle *ii,
symbol_source ss, void *source, IMP_SYM_WKR *wk,
imp_sym_handle *is, void *d )
{
struct glue_info glue;
imp_mod_handle im;
scope_block *sc_block;
s_all *p;
scope_info sc_info;
dip_status ds;
walk_result wr;
imp_type_handle it;
glue.wk = wk;
glue.is = is;
glue.d = d;
switch( ss ) {
case SS_MODULE:
im = *(imp_mod_handle *)source;
if( im == (imp_mod_handle)NO_MOD ) {
wr = WalkDirList( ii, &WalkAModule, &glue );
if( wr != WR_CONTINUE ) return( wr );
im = MH_GBL;
}
if( im == MH_GBL ) {
wr = TableWalkSym( ii, is, wk, d, sstGlobalSym );
if( wr != WR_CONTINUE ) return( wr );
return( TableWalkSym( ii, is, wk, d, sstGlobalPub ) );
}
return( ScopeWalkFile( ii, im, WalkGlue, &glue ) );
case SS_SCOPED:
if( ImpAddrMod( ii, *(address *)source, &im ) == SR_NONE ) {
return( WR_CONTINUE );
}
return( ScopeWalkAll( ii, im, *(address *)source, &WalkGlue, &glue ) );
case SS_BLOCK:
sc_block = source;
if( ImpAddrMod( ii, sc_block->start, &im ) == SR_NONE ) {
return( WR_CONTINUE );
}
sc_info.cde = FindDirEntry( ii, im, sstAlignSym );
if( sc_info.cde == NULL ) return( WR_FAIL );
ds = ScopeFillIn( ii, sc_block->unique & SCOPE_UNIQUE_MASK,
&sc_info, &p );
if( ds & DS_ERR ) return( WR_FAIL );
if( ds != DS_OK ) return( WR_CONTINUE );
if( sc_block->unique & SCOPE_CLASS_FLAG ) {
/* Walk the member function class scope */
ds = TypeIndexFillIn( ii, SymTypeIdx( ii, p ), &it );
if( ds & DS_ERR ) return( WR_FAIL );
if( ds != DS_OK ) return( WR_CONTINUE );
ds = TypeMemberFuncInfo( ii, &it, &it, NULL, NULL );
if( ds & DS_ERR ) return( WR_FAIL );
if( ds != DS_OK ) return( WR_CONTINUE );
return( TypeSymWalkList( ii, &it, wk, is, d ) );
} else {
return( ScopeWalkOne( ii, &sc_info, WalkGlue, &glue ) );
}
case SS_TYPE:
return( TypeSymWalkList( ii, (imp_type_handle *)source, wk, is, d ) );
}
return( WR_FAIL );
}
walk_result DIPENTRY DIPImpWalkSymList( imp_image_handle *ii,
symbol_source ss, void *source, IMP_SYM_WKR *wk,
imp_sym_handle *is, void *d )
{
return( DoWalkSymList( ii, ss, source, wk, is, d ) );
}
walk_result DIPENTRY DIPImpWalkSymListEx( imp_image_handle *ii, symbol_source ss,
void *source, IMP_SYM_WKR *wk, imp_sym_handle *is,
location_context *lc, void *d )
{
lc=lc;
return( DoWalkSymList( ii, ss, source, wk, is, d ) );
}
imp_mod_handle DIPENTRY DIPImpSymMod( imp_image_handle *ii,
imp_sym_handle *is )
{
ii = ii;
return( is->im );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?