hllsym.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,855 行 · 第 1/5 页

C
1,855
字号
        break;
    case S_REGREL32:
        disp = p->regrel32.f.offset;
        ds = LocationOneReg( ii, p->regrel32.f.reg, lc, ll );
        if( ds != DS_OK ) return( ds );
        LocationCreate( &tmp_ll, LT_INTERNAL, &tmp.off48 );
        ds = DCAssignLocation( ll, &tmp_ll, sizeof( addr48_off ) );
        if( ds != DS_OK ) return( ds );
        ds = DCItemLocation( lc, CI_DEF_ADDR_SPACE, ll );
        if( ds != DS_OK ) return( ds );
        ll->e[0].u.addr.mach.offset = tmp.off48 + disp;
        break;
    case S_LTHREAD32:
    case S_GTHREAD32:
        addr.mach.offset = p->lthread32.f.offset;
        addr.mach.segment = p->lthread32.f.segment;
        MapLogical( ii, &addr );
        LocationCreate( ll, LT_ADDR, &addr );
        break;
    default:
        Confused();
        return( DS_FAIL );
    }
    return( DS_OK );
}

typedef struct {
    cv_directory_entry  *cde;
    address             start;
    unsigned_32         len;
    virt_mem            scope;
    virt_mem            parent;
    virt_mem            end;
    virt_mem            next;
    unsigned            code;
} scope_info;

static dip_status ScopeFillIn( imp_image_handle *ii, virt_mem chk,
                                scope_info *scope, s_all **pp )
{
    s_all       *p;

    p = VMBlock( ii, chk, sizeof( s_gproc32 ) );
    if( pp != NULL ) *pp = p;
    if( p == NULL ) return( DS_ERR|DS_FAIL );
    scope->code = p->common.code;
    scope->scope = chk;
    scope->next = 0;
    switch( p->common.code ) {
    case S_LPROC16:
    case S_GPROC16:
        scope->start.mach.segment = p->lproc16.f.segment;
        scope->start.mach.offset  = p->lproc16.f.offset;
        scope->len = p->lproc16.f.proc_length;
        scope->parent = p->lproc16.f.pParent;
        scope->end = p->lproc16.f.pEnd;
        scope->next = p->lproc16.f.pNext;
        break;
    case S_THUNK16:
        scope->start.mach.segment = p->thunk16.f.segment;
        scope->start.mach.offset  = p->thunk16.f.offset;
        scope->len = p->thunk16.f.length;
        scope->parent = p->thunk16.f.pParent;
        scope->end = p->thunk16.f.pEnd;
        scope->next = p->lproc16.f.pNext;
        break;
    case S_BLOCK16:
        scope->start.mach.segment = p->block16.f.segment;
        scope->start.mach.offset  = p->block16.f.offset;
        scope->len = p->block16.f.length;
        scope->parent = p->block16.f.pParent;
        scope->end = p->block16.f.pEnd;
        break;
    case S_WITH16:
        scope->start.mach.segment = p->with16.f.segment;
        scope->start.mach.offset  = p->with16.f.offset;
        scope->len = p->with16.f.length;
        scope->parent = p->with16.f.pParent;
        scope->end = p->with16.f.pEnd;
        break;
    case S_LPROC32:
    case S_GPROC32:
        scope->start.mach.segment = p->lproc32.f.segment;
        scope->start.mach.offset  = p->lproc32.f.offset;
        scope->len = p->lproc32.f.proc_length;
        scope->parent = p->lproc32.f.pParent;
        scope->end = p->lproc32.f.pEnd;
        scope->next = p->lproc16.f.pNext;
        break;
    case S_THUNK32:
        scope->start.mach.segment = p->thunk32.f.segment;
        scope->start.mach.offset  = p->thunk32.f.offset;
        scope->len = p->thunk32.f.length;
        scope->parent = p->thunk32.f.pParent;
        scope->end = p->thunk32.f.pEnd;
        scope->next = p->lproc16.f.pNext;
        break;
    case S_BLOCK32:
        scope->start.mach.segment = p->block32.f.segment;
        scope->start.mach.offset  = p->block32.f.offset;
        scope->len = p->block32.f.length;
        scope->parent = p->block32.f.pParent;
        scope->end = p->block32.f.pEnd;
        break;
    case S_WITH32:
        scope->start.mach.segment = p->with32.f.segment;
        scope->start.mach.offset  = p->with32.f.offset;
        scope->len = p->with32.f.length;
        scope->parent = p->with32.f.pParent;
        scope->end = p->with32.f.pEnd;
        break;
    default:
        return( DS_FAIL );
    }
    if( scope->parent != 0 ) scope->parent += scope->cde->lfo;
    if( scope->next != 0 ) scope->next += scope->cde->lfo;
    scope->end += scope->cde->lfo;
    MapLogical( ii, &scope->start );
    return( DS_OK );
}

static dip_status ScopeFindFirst( imp_image_handle *ii, imp_mod_handle im,
                                address addr, scope_info *scope )
{
    virt_mem            chk;
    unsigned long       len;
    s_all               *p;
    scope_info          new;
    dip_status          ds;

    scope->cde = FindDirEntry( ii, im, sstAlignSym );
    if( scope->cde == NULL ) return( DS_FAIL );
    chk = scope->cde->lfo + sizeof( unsigned_32 );
    len = scope->cde->cb - sizeof( unsigned_32 );
    for( ;; ) {
        if( len == 0 ) return( DS_FAIL );
        p = VMBlock( ii, chk, sizeof( s_ssearch ) );
        if( p == NULL ) return( DS_ERR|DS_FAIL );
        if( p->common.code == S_SSEARCH ) {
            scope->start.mach.segment = p->ssearch.f.segment;
            scope->start.mach.offset  = 0;
            MapLogical( ii, &scope->start );
            if( DCSameAddrSpace( scope->start, addr ) == DS_OK ) {
                chk = p->ssearch.f.sym_off + scope->cde->lfo;
                break;
            }
        }
        chk += p->common.length + sizeof( p->common.length );
        len -= p->common.length + sizeof( p->common.length );
    }
    /* found first scope block, now find correct offset */
    for( ;; ) {
        ds = ScopeFillIn( ii, chk, scope, NULL );
        if( ds != DS_OK ) return( DS_ERR|ds );
        if( addr.mach.offset >= scope->start.mach.offset
         && addr.mach.offset < (scope->start.mach.offset + scope->len) ) {
            break;
        }
        if( scope->next == 0 ) return( DS_FAIL );
        chk = scope->next;
    }
    /* found enclosing scope block, now find smallest one */
    chk = scope->scope;
    new.cde = scope->cde;
    for( ;; ) {
        ds = ScopeFillIn( ii, chk, &new, NULL );
        if( ds & DS_ERR ) return( ds );
        if( ds == DS_OK ) {
            /* new scope */
            if( !(addr.mach.offset >= new.start.mach.offset
             && addr.mach.offset <  (new.start.mach.offset + new.len)) ) {
                /* out of range */
                chk = new.end;
            } else if( !(new.start.mach.offset >= scope->start.mach.offset
                   && (new.start.mach.offset+new.len) <= (scope->start.mach.offset+scope->len)) ) {
                /* not smaller */
                chk = new.end;
            } else {
                /* inner scope */
                *scope = new;
            }
        } else if( p->common.code == S_END ) {
            /* all done */
            return( DS_OK );
        }
        p = VMBlock( ii, chk, sizeof( p->common ) );
        if( p == NULL ) return( DS_ERR|DS_FAIL );
        chk += p->common.length + sizeof( p->common.length );
    }
}

static dip_status ScopeFindNext( imp_image_handle *ii, scope_info *scope )
{
    if( scope->parent == 0 ) return( DS_FAIL );
    return( ScopeFillIn( ii, scope->parent, scope, NULL ) );
}


static walk_result ScopeOneSymbol( imp_image_handle *ii, cv_directory_entry *cde,
                    scope_info *scope, IMP_SYM_WKR *wk, void *d,
                    virt_mem *currp )
{
    scope_info          new;
    dip_status          ds;
    walk_result         wr;
    imp_sym_handle      is;
    s_all               *p;
    virt_mem            curr;

    curr = *currp;
    new.cde = cde;
    ds = ScopeFillIn( ii, curr, &new, &p );
    if( ds & DS_ERR ) return( WR_FAIL );
    if( ds == DS_OK ) {
        *currp = new.end;
        p = VMBlock( ii, *currp, sizeof( p->common ) );
        if( p == NULL ) return( WR_FAIL );
    }
    *currp += p->common.length + sizeof( p->common.length );
    switch( new.code ) {
    case S_COMPILE:
    case S_SSEARCH:
    case S_END:
    case S_SKIP:
    case S_OBJNAME:
    case S_ENDARG:
    case S_RETURN:
    case S_CEXMODEL16:
    case S_VFTPATH16:
    case S_THUNK16:
    case S_BLOCK16:
    case S_WITH16:
    case S_CEXMODEL32:
    case S_VFTPATH32:
    case S_THUNK32:
    case S_BLOCK32:
    case S_WITH32:
        /* not interested in these */
        break;
    case S_ENTRYTHIS:
        curr += sizeof( s_common );
        /* fall through */
    default:
        if( ds == DS_OK && scope != NULL ) {
            /*
                starting a new scope and not doing file scope
                symbols -- skip scope start symbol
            */
            break;
        }
        is.im = cde->iMod;
        if( SymFillIn( ii, &is, curr ) != DS_OK ) return( WR_FAIL );
        wr = wk( ii, SWI_SYMBOL, &is, d );
        if( wr != WR_CONTINUE ) return( wr );
        break;
    }
    return( WR_CONTINUE );
}

static walk_result ScopeWalkOne( imp_image_handle *ii, scope_info *scope,
                                IMP_SYM_WKR *wk, void *d )
{
    walk_result         wr;
    s_all               *p;
    virt_mem            curr;

    curr = scope->scope;
    p = VMBlock( ii, curr, sizeof( p->common ) );
    if( p == NULL ) return( WR_FAIL );
    /* skip over first scope start symbol */
    curr += p->common.length + sizeof( p->common.length );
    for( ;; ) {
        p = VMBlock( ii, curr, sizeof( p->common ) );
        if( p == NULL ) return( WR_FAIL );
        if( p->common.code == S_END ) return( WR_CONTINUE );
        wr = ScopeOneSymbol( ii, scope->cde, scope, wk, d, &curr );
        if( wr != WR_CONTINUE ) return( wr );
    }
}

static walk_result ScopeWalkClass( imp_image_handle *ii, scope_info *scope,
                                IMP_SYM_WKR *wk, void *d )
{
    dip_status          ds;
    imp_type_handle     it;
    s_all               *p;
    imp_sym_handle      is;

    p = VMBlock( ii, scope->scope, sizeof( *p ) );
    if( p == NULL ) return( WR_FAIL );
    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 ) );
}

static walk_result ScopeWalkAll( imp_image_handle *ii, imp_mod_handle im,
                        address addr, IMP_SYM_WKR *wk, void *d )
{
    dip_status          ds;
    walk_result         wr;
    scope_info          scope;

    ds = ScopeFindFirst( ii, im, addr, &scope );
    if( ds & DS_ERR ) return( WR_FAIL );
    if( ds != DS_OK ) return( WR_CONTINUE );
    for( ;; ) {
        wr = ScopeWalkOne( ii, &scope, wk, d );
        if( wr != WR_CONTINUE ) return( wr );
        switch( scope.code ) {
        case S_LPROC16:
        case S_GPROC16:
        case S_LPROC32:
        case S_GPROC32:
            wr = ScopeWalkClass( ii, &scope, wk, d );
            if( wr != WR_CONTINUE ) return( wr );
            break;
        }
        ds = ScopeFindNext( ii, &scope );
        if( ds & DS_ERR ) return( WR_FAIL );
        if( ds != DS_OK ) return( WR_CONTINUE );
    }
}

static walk_result ScopeWalkFile( imp_image_handle *ii, imp_mod_handle im,
                        IMP_SYM_WKR *wk, void *d )
{
    cv_directory_entry  *cde;
    virt_mem            curr;
    virt_mem            end;
    walk_result         wr;

    cde = FindDirEntry( ii, im, sstAlignSym );
    if( cde == NULL ) return( WR_CONTINUE );
    curr = cde->lfo;
    end = curr + cde->cb;
    curr += sizeof( unsigned_32 );
    for( ;; ) {
        if( curr >= end ) return( WR_CONTINUE );
        wr = ScopeOneSymbol( ii, cde, NULL, wk, d, &curr );
        if( wr != WR_CONTINUE ) return( wr );
    }
}

static search_result TableSearchForAddr( imp_image_handle *ii,
                        address a, imp_sym_handle *is, addr_off *best_off, unsigned tbl_type )
{
    cv_directory_entry          *cde;
    cv_sst_global_pub_header    *hdr;
    unsigned                    num_segs;
    void                        *p;
    unsigned                    i;
    address                     chk;
    virt_mem                    hash_base;
    virt_mem                    base;
    unsigned long               offset_count;
    unsigned long               count;
    addr_off                    new_off;
    struct {
        virt_mem                base;
        addr_off                off;
    }                           curr, best;

    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->addrhash ) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?