loados2.c

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

C
1,176
字号
    for( node = val; node != NULL; node = node->next ) {
        ++i;
        WriteLoad( &(node->len), sizeof(unsigned char) );  // NOTE:little endian
        if( upper ) {
            for( j = node->len-1; j >= 0; --j ) {
                node->name[j] = toupper( node->name[j] );
            }
        }
        WriteLoad( node->name, node->len );
        off += node->len + 1;
    }
    *count = i;
    return( off );
}

extern unsigned long ImportProcTable( unsigned long *count )
/**********************************************************/
{
    return( WriteTabList( FmtData.u.os2.imp_tab_list, count,
                          !(LinkFlags & CASE_FLAG) ) );
}

extern unsigned long ImportModTable( unsigned long *count )
/*********************************************************/
{
    return( WriteTabList( FmtData.u.os2.mod_ref_list, count, FALSE ) );
}

static unsigned long ImportNameTable( void )
/******************************************/
{
    unsigned long count;
    unsigned long size;

    PadLoad( 1 );
    size = 1;
    size += ImportProcTable( &count );
    size += ImportModTable( &count );
    return( size );
}

static unsigned long ModRefTable( void )
/**************************************/
/* count total number of groups */
{
    name_list *         node;
    name_list *         inode;
    unsigned long       nodenum;
    unsigned long       off;

    if( FmtData.type & MK_OS2_16BIT ) {
        off = 1;
        for( inode = FmtData.u.os2.imp_tab_list; inode != NULL;
                                                 inode = inode->next ) {
            off += inode->len + 1;
        }
    } else {
        off = 0;
    }
    nodenum = 0;
    for( node = FmtData.u.os2.mod_ref_list; node != NULL; node = node->next ) {
        WriteLoad( &off, sizeof(unsigned_16) );
        off += node->len + 1;
        nodenum++;
    }
    return nodenum;
}

extern unsigned long ResNonResNameTable( bool dores )
/***************************************************/
/* NOTE: this routine assumes INTEL byte ordering (in the use of namelen) */
{
    entry_export *  exp;
    int             namelen;
    unsigned long   size;
    char *          name;

    size = 0;
    if( dores ) {
        if( FmtData.u.os2.res_module_name != NULL ) {
            name = FmtData.u.os2.res_module_name;
            namelen = strlen( name );
        } else {
            name = RemovePath( Root->outfile->fname, &namelen );
        }
    } else {     /* in non-resident names table */
        if( FmtData.u.os2.description != NULL ) {
            name = FmtData.u.os2.description;
        } else if( FmtData.type & MK_OS2_16BIT ) {
            name = Root->outfile->fname;
        } else {
            name = "";
        }
        namelen = strlen( name );
    }
    if( dores || namelen > 0 ) {
        WriteLoad( &namelen, 1 );
        WriteLoad( name, namelen );
        PadLoad( 2 );
        size += namelen + 3;
    }
    if( dores && FmtData.u.os2.res_module_name != NULL ) {
        _LnkFree( name );
        FmtData.u.os2.res_module_name = NULL;
    }
    if( !dores && FmtData.u.os2.description != NULL ) {
        _LnkFree( name );
        FmtData.u.os2.description = NULL;
    }
    for( exp = FmtData.u.os2.exports; exp != NULL; exp = exp->next ) {
        if( !exp->isexported ) continue;
        if( exp->isanonymous ) continue;
        if( (dores && exp->isresident) || (!dores && !exp->isresident) ) {
            if( !(LinkFlags & CASE_FLAG) ) {
                strupr( exp->name );
            }
            namelen = strlen( exp->name );
            WriteLoad( &namelen, 1 );
            WriteLoad( exp->name, namelen );
            WriteLoad( &(exp->ordinal), 2 );
            size += namelen + 3;
            if( !exp->isprivate ) {
                if( exp->impname != NULL ) {
                    AddImpLibEntry(exp->impname, exp->name, NOT_IMP_BY_ORDINAL);
                } else {
                    AddImpLibEntry( exp->sym->name, NULL, exp->ordinal );
                }
            }
        }
    }
    if( size > 0 ) {
        PadLoad( 1 );
        ++size;
    }
    return( size );
}


/*
 * NOTE: The routine DumpFlatEntryTable in LOADFLAT.C is very similar to this
 *       one, however there are a enough differences to preclude the use
 *       of one routine to dump both tables. Therefore any logic bugs that
 *       occur in this routine will likely have to be fixed in the other
 *       one as well.
 */
static unsigned long DumpEntryTable( void )
/*****************************************/
/* Dump the entry table to the file */
{
    entry_export *  start;
    entry_export *  place;
    entry_export *  prev;
    unsigned_16     prevord;
    unsigned long   size;
    unsigned        gap;
    unsigned        entries;
    bundle_prefix   prefix;
    union {
        fixed_record    f;
        movable_record  m;
    }               bundle_item;

    size = 0;
    start = FmtData.u.os2.exports;
    if( start != NULL ) {
        prevord = 0;
        place = start;
        while( place != NULL ) {
            gap = place->ordinal - prevord;
            if( gap > 1 ) {  // fill in gaps in ordinals.
                gap--;       // fix 'off by 1' problem.
                prefix.number = 0xFF;
                prefix.type = 0x00;   // Null bundles.
                while( gap > 0xff ) {
                    WriteLoad( &prefix, sizeof( bundle_prefix ) );
                    gap -= 0xFF;
                    size += 2;
                }
                prefix.number = (unsigned_8) gap;
                WriteLoad( &prefix, sizeof( bundle_prefix ) );
                size += 2;
            }
            // now get a bundle of ordinals.
            entries = 1;
            prev = start = place;
            place = place->next;
            while( place != NULL ) {
                if( entries >= 0xff ) break;
                if( start->ismovable ) {
                    if( !place->ismovable )break;
                } else {
                    if( place->addr.seg != start->addr.seg ) break;
                }
                if( place->ordinal - prev->ordinal > 1 ) {
                    break;    // ordinal can't be put in this bundle.
                }
                entries++;
                prev = place;
                place = place->next;
            }
            if( start->ismovable ) {
                prefix.type = MOVABLE_ENTRY_PNT;
                bundle_item.m.reserved = 0x3fcd; /* int 0x3f */
                size += entries * sizeof( movable_record );
            } else {
                prefix.type = start->addr.seg;     // fixed segment records.
                size += entries * sizeof( fixed_record );
            }
            prevord = prev->ordinal;
            prefix.number = (unsigned_8) entries;
            WriteLoad( &prefix, sizeof( bundle_prefix ) );
            size += 2;
            for( ; entries > 0; --entries ) {
                bundle_item.f.info = (start->iopl_words << IOPL_WORD_SHIFT);
                if( start->isexported ) {
                    bundle_item.f.info |= ENTRY_EXPORTED;
                    if( FmtData.u.os2.flags & SHARABLE_DGROUP ) {
                        bundle_item.f.info |= ENTRY_SHARED;
                    }
                }
                if( start->ismovable ) {
                    if( start->addr.seg > 0xFF ) {
                        LnkMsg( WRN+MSG_BAD_MOVABLE_SEG_NUM, NULL );
                    }
                    bundle_item.m.entrynum = start->addr.seg;
                    bundle_item.m.entry = start->addr.off;
                    WriteLoad( &bundle_item, sizeof( movable_record ) );
                } else {
                    bundle_item.f.entry = start->addr.off;
                    WriteLoad( &bundle_item, sizeof( fixed_record ) );
                }
                start = start->next;
            }
        }
    }
    PadLoad( 2 );
    return( size + 2 );
}

extern void ChkOS2Data()
/**********************/
{
    SetSegFlags( (seg_flags *) FmtData.u.os2.os2_seg_flags );
    FmtData.u.os2.os2_seg_flags = NULL;
}

extern void ChkOS2Exports( void )
/*******************************/
// NOTE: there is a continue in this loop!
{
    symbol *        symptr;
    entry_export *  exp;
    group_entry *   group;
    unsigned        num_entries;

    SetGroupFlags();            // NOTE: there is a continue in this loop!
    num_entries = 0;
    for( exp = FmtData.u.os2.exports; exp != NULL; exp = exp->next ) {
        num_entries++;
        symptr = exp->sym;
        if( IS_SYM_ALIAS( symptr ) ) {
            symptr = UnaliasSym( ST_FIND, symptr );
            if( symptr == NULL || !(symptr->info & SYM_DEFINED) ) {
                LnkMsg( ERR+MSG_EXP_SYM_NOT_FOUND, "s", exp->sym->name );
                continue;               // <----- DANGER weird control flow!
            } else if( exp->sym->info & SYM_WAS_LAZY ) {
                LnkMsg( WRN+MSG_EXP_SYM_NOT_FOUND, "s", exp->sym->name );
            }
            exp->sym = symptr;
        }
        if( !(symptr->info & SYM_DEFINED) ) {
            LnkMsg( ERR+MSG_EXP_SYM_NOT_FOUND, "s", symptr->name );
        } else {
            exp->addr = symptr->addr;
            if( symptr->p.seg == NULL || IS_SYM_IMPORTED(symptr) ) {
                if( FmtData.type & MK_OS2_FLAT ) {
                    // MN: Create a forwarder - add a special flag?
                    // Currently DumpFlatEntryTable() in loadflat.c will
                    // recognize a forwarder by segment == 0xFFFF
                } else {
                    LnkMsg( ERR+MSG_CANT_EXPORT_ABSOLUTE, "S", symptr );
                }
            } else {
                group = symptr->p.seg->u.leader->group;
                if( FmtData.type & MK_OS2_FLAT ) {
                    exp->addr.off -= group->grp_addr.off;
                } else if( FmtData.type & MK_PE ) {
                    exp->addr.off += (group->linear - group->grp_addr.off);
                }
                if( group->segflags & SEG_MOVABLE ) {
                    exp->ismovable = TRUE;
                }
            }
        }
    }   // NOTE: there is a continue in this loop!
    AssignOrdinals();    /* make sure all exports have ordinals */
    if(( FmtData.type & MK_WIN_VXD ) && ( num_entries != 1 )) {
        LnkMsg( FTL+MSG_VXD_INCORRECT_EXPORT, NULL );
    }
}

extern void PhoneyStack( void )
/*****************************/
// signal that we will be making a fake stack later on.
{
    FmtData.u.os2.flags |= PHONEY_STACK_FLAG;
}

static WResDir InitNEResources(int *resHandle, ResTable *outRes)
/**************************************************************/
{
    WResDir     inRes;
    int         dup_discarded;
    int         error;

    if( FmtData.resource ) {
        *resHandle = QOpenR( FmtData.resource );
        inRes = WResInitDir();
        error = WResReadDir( *resHandle, inRes, &dup_discarded );
        if( error ) {
            LnkMsg( WRN+MSG_PROBLEM_IN_RESOURCE, NULL );
            inRes = NULL;
        }

        outRes->Dir.NumTypes = WResGetNumTypes( inRes );
        outRes->Dir.NumResources = WResGetNumResources( inRes );
        outRes->Dir.TableSize = outRes->Dir.NumTypes * sizeof(resource_type_record) +
                            outRes->Dir.NumResources * sizeof(resource_record) +
                            2 * sizeof(uint_16);
        /* the 2 uint_16 are the resource shift count and the type 0 record */
        outRes->Dir.Head = NULL;
        outRes->Dir.Tail = NULL;
        StringBlockBuild( &outRes->Str, inRes, FALSE );
    } else {
        inRes = NULL;
    }
    return inRes;
}

static void FiniNEResources( int resHandle, WResDir inRes, ResTable *outRes )
/***************************************************************************/
{
    if( inRes != NULL ) {
        if( outRes->Str.StringBlock != NULL ) {
            _LnkFree( outRes->Str.StringBlock );
            outRes->Str.StringBlock = NULL;
        }
        if( outRes->Str.StringList != NULL ) {
            _LnkFree( outRes->Str.StringList );
            outRes->Str.StringList = NULL;
        }
        WResFreeDir( inRes );
        QClose( resHandle, FmtData.resource );
    }
}


static uint_32 ComputeResourceSize( WResDir dir )
/***********************************************/
{
    uint_32         length;
    WResDirWindow   wind;
    WResLangInfo *  res;

    if( dir == NULL ) {
        return 0;
    }
    length = 0;
    wind = WResFirstResource( dir );
    while( !WResIsEmptyWindow( wind ) ) {
        res = WResGetLangInfo( wind );
        length += res->Length;
        wind = WResNextResource( wind, dir );
    }
    return( length );
}

#define MAX_DGROUP_SIZE (64*1024UL)

extern void FiniOS2LoadFile()
/***************************/
/* terminate writing of load file */
{
    os2_exe_header      exe_head;
    unsigned long       temp;
    unsigned_16         adseg;
    group_entry *       group;
    unsigned_32         stub_len;
    unsigned_32         dgroup_size;
    unsigned long       size;
    entry_export *      exp;
    unsigned long       imageguess;     // estimated length of the image

⌨️ 快捷键说明

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