impexp.c

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

C
555
字号
        DbgAssert(name[0] == '.' && name[1] == '.');
        name += 2;  // skip '..' at the beginning of the name
    }
    prefixlen = sizeof(ImportSymPrefix) - 1;
    namelen = strlen( name );
    iatname = alloca( namelen + prefixlen + 1 );
    memcpy( iatname, ImportSymPrefix, prefixlen );
    memcpy( iatname + prefixlen, name, namelen );
    prefixlen += namelen;
    iatname[prefixlen] = '\0';
    return SymOp( ST_CREATE, iatname, prefixlen );
}

extern void MSImportKeyword( symbol *sym, length_name *modname,
                             length_name *extname, unsigned long ordinal )
/************************************************************************/
/* process the MS import keyword definition */
{
    dll_sym_info *      dll;

    if( !(sym->info & SYM_DEFINED) ) {
        sym->info |= SYM_DEFINED | SYM_DCE_REF;
        if( LinkFlags & STRIP_CODE ) {
            DefStripImpSym(sym);
        }
        SET_SYM_TYPE( sym, SYM_IMPORTED );
        dll = AllocDLLInfo();
        sym->p.import = dll;
        if( FmtData.type & MK_PE ) {
            dll->iatsym = GetIATSym( sym );
            dll->iatsym->info |= SYM_DEFINED | SYM_DCE_REF;
            SET_SYM_TYPE( dll->iatsym, SYM_IMPORTED );
            dll->iatsym->p.import = NULL;
        }
        dll->m.modnum = AddNameTable( modname->name, modname->len, TRUE,
                                    &FmtData.u.os2.mod_ref_list );
        dll->isordinal = ordinal != NOT_IMP_BY_ORDINAL;
        if( !dll->isordinal ) {
            dll->u.entry = AddNameTable( extname->name, extname->len, FALSE,
                                        &FmtData.u.os2.imp_tab_list );
        } else {
            dll->u.ordinal = ordinal;
        }
    }
}

extern void KillDependantSyms( symbol *sym )
/******************************************/
{
    if( !(FmtData.type & MK_PE) ) return;
    sym = GetIATSym( sym );
    sym->info |= SYM_KILL;
}

extern void AssignOrdinals( void )
/********************************/
/* assign ordinal values to entries in the export list */
{
    entry_export *      exp;
    entry_export *      place;
    entry_export *      prev;
    bool                isspace;

    if( FmtData.u.os2.exports != NULL ) {
        if( FmtData.u.os2.old_lib_name != NULL ) {
            ReadOldLib();
        }
        exp = prev = FmtData.u.os2.exports;
        place = prev->next;
        while( exp->ordinal == 0 ) {  // while still unassigned values
            for(;;) {                 // search for an unassigned value
                if( place != NULL ) {
                    isspace = (place->ordinal - prev->ordinal > 1);
                }
                if( place == NULL || isspace ) {
                    if( FmtData.u.os2.exports != prev ) {
                        FmtData.u.os2.exports = exp->next;
                        prev->next = exp;
                        exp->next = place;
                    }
                    exp->ordinal = prev->ordinal + 1;
                    prev = exp;      // now exp is 'previous' to place
                    break;
                } else {
                    prev = place;
                    place = place->next;
                }
            }
            exp = FmtData.u.os2.exports;
        }
    }
}

static void ReadOldLib( void )
/****************************/
// Read an old DLL & match ordinals of exports in it with exports in this.
{
    f_handle    the_file;
    long        filepos;
    union {
        dos_exe_header  dos;
        os2_exe_header  os2;
        os2_flat_header os2f;
        pe_header       pe;
    }           head;
    char *      fname;
    pe_object * objects;
    pe_object * currobj;

    fname = FmtData.u.os2.old_lib_name;
    the_file = QOpenR( fname );
    QRead( the_file, &head, sizeof(dos_exe_header), fname );
    if( head.dos.signature != 0x5A4D || head.dos.reloc_offset != 0x40 ) {
        LnkMsg( WRN + MSG_INV_OLD_DLL, NULL );
    } else {
        QSeek( the_file, 0x3c, fname );
        QRead( the_file, &filepos, sizeof( long ), fname );
        QSeek( the_file, filepos, fname );
        QRead( the_file, &head, sizeof(head), fname );
        if( head.os2.signature == OS2_SIGNATURE_WORD ) {
            QSeek( the_file, filepos + head.os2.resident_off, fname );
            ReadNameTable( the_file );
            QSeek( the_file, head.os2.nonres_off, fname );
            ReadNameTable( the_file );
        } else if( head.os2f.signature == OSF_FLAT_SIGNATURE
                || head.os2f.signature == OSF_FLAT_LX_SIGNATURE ) {
            if( head.os2f.resname_off != 0 ) {
                QSeek( the_file, filepos + head.os2f.resname_off, fname );
                ReadNameTable( the_file );
            }
            if( head.os2f.nonres_off != 0 ) {
                QSeek( the_file, head.os2f.nonres_off, fname );
                ReadNameTable( the_file );
            }
        } else if( head.pe.signature == PE_SIGNATURE ) {
            _ChkAlloc( objects, head.pe.num_objects * sizeof(pe_object) );
            QRead( the_file, objects, head.pe.num_objects * sizeof(pe_object),
                   fname );
            currobj = objects;
            while( head.pe.num_objects > 0 ) {
                if( currobj->rva == head.pe.table[PE_TBL_EXPORT].rva ) {
                    QSeek( the_file, currobj->physical_offset, fname );
                    head.pe.table[PE_TBL_EXPORT].rva -=currobj->physical_offset;
                    ReadPEExportTable( the_file, &head.pe.table[PE_TBL_EXPORT]);
                    break;
                }
                head.pe.num_objects--;
                currobj++;
            }
            _LnkFree( objects );
            if( head.pe.num_objects == 0 ) {
                LnkMsg( WRN + MSG_INV_OLD_DLL, NULL );
            }
        } else {
            LnkMsg( WRN+MSG_INV_OLD_DLL, NULL );
        }
    }
    QClose( the_file, fname );
    _LnkFree( fname );
    FmtData.u.os2.old_lib_name = NULL;
}

extern void CheckExport( char * name, unsigned_16 ordinal,
                         int (*compare_rtn)(const char *,const char *))
/*********************************************************************/
/* check if the name is exported and hasn't been assigned a value, and if so,
 * give it the specified value */
{
    entry_export *  place;
    entry_export *  prev;

    DEBUG(( DBG_OLD, "Oldlib export %s ordinal %l", name, ordinal ));
    prev = NULL;
    place = FmtData.u.os2.exports;
    while( compare_rtn( place->name, name ) != 0 ) {
        prev = place;
        place = place->next;
        if( place == NULL ) {
            break;
        }
    }
    if( place != NULL ) {
        if( place->ordinal == 0 ) {
            place->ordinal = ordinal;
            place = FindPlace( place );
            if( place != NULL ) {
                if( prev == NULL ) {
                    FmtData.u.os2.exports = place;
                } else {
                    prev->next = place;
                }
            }
        }
    }
}

static void ReadNameTable( f_handle the_file )
/********************************************/
// Read a name table & set export ordinal value accordingly.
{
    unsigned_8      length;
    unsigned_16     ordinal;
    int (*compare_rtn)(const char *,const char *);
    char *          fname;

    fname = FmtData.u.os2.old_lib_name;
    if( LinkFlags & CASE_FLAG ) {
        compare_rtn = &strcmp;
    } else {
        compare_rtn = &stricmp;
    }                             // skip the module name & ordinal.
    for( ;; ) {
        QRead( the_file, &length, sizeof( unsigned_8 ), fname );
        if( length == 0 ) break;
        QRead( the_file, TokBuff, length, fname );
        QRead( the_file, &ordinal, sizeof( unsigned_16 ), fname );
        if( ordinal == 0 ) continue;
        TokBuff[ length ] = '\0';
        CheckExport( TokBuff, ordinal, compare_rtn );
    }
}

extern unsigned_16 FindEntryOrdinal( targ_addr addr, group_entry *grp )
/*********************************************************************/
{
    unsigned_16     max_ord;
    entry_export ** owner;
    entry_export *  exp;

    max_ord = 0;
    owner = &FmtData.u.os2.exports;
    for( ;; ) {
        exp = *owner;
        if( exp == NULL ) break;
        if( addr.seg == exp->addr.seg && addr.off == exp->addr.off ) {
            return( exp->ordinal );
        }
        if( exp->ordinal >= max_ord ) max_ord = exp->ordinal;
        owner = &exp->next;
    }
    exp = AllocExport( NULL, 0 );
    exp->sym = NULL;
    exp->isexported = FALSE;
    exp->isanonymous = FALSE;
    exp->ordinal = max_ord + 1;
    exp->ismovable = (grp->segflags & SEG_MOVABLE) != 0;
    exp->next = NULL;
    exp->addr = addr;
    *owner = exp;
    return( exp->ordinal );
}

extern char * ImpModuleName( dll_sym_info *dll )
/**********************************************/
{
    return dll->m.modnum->name;
}

extern bool IsSymElfImported( symbol *s )
/***************************************/
{
    return IS_SYM_IMPORTED(s);
}

extern bool IsSymElfExported( symbol *s )
/***************************************/
{
    return FmtData.u.elf.exportallsyms || (s->info & SYM_EXPORTED);
}

extern bool IsSymElfImpExp( symbol *s )
/*************************************/
{
    return IsSymElfImported(s) || IsSymElfExported(s);
}

⌨️ 快捷键说明

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