loadflat.c

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

C
564
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Utilities for creation of OS/2 flat (LX) executable files.
*
****************************************************************************/


#include <string.h>
#include "linkstd.h"
#include "reloc.h"
#include "exeos2.h"
#include "exeflat.h"
#include "loados2.h"
#include "loadfile.h"
#include "specials.h"
#include "alloc.h"
#include "virtmem.h"
#include "fileio.h"
#include "impexp.h"
#include "ring.h"
#include "dbgall.h"
#include "vxd_ddb.h"

#define PAGE_COUNT( size )  (((size)+(OSF_DEF_PAGE_SIZE-1))>>OSF_PAGE_SHIFT)
#define PAGEMAP_BUF_SIZE (MAX_HEADROOM / sizeof(map_entry) * (unsigned long)OSF_DEF_PAGE_SIZE)


static unsigned NumberBuf( unsigned_32 *start, unsigned_32 limit,
                           map_entry *buf )
/**************************************************************/
/* fill a buffer with consecutive numbers */
{
    unsigned    size;
    unsigned_32 num;
    unsigned    shift;

    num = PAGE_COUNT(limit);
    if( FmtData.type & (MK_OS2_LE|MK_WIN_VXD) ) {
        size = num * sizeof( le_map_entry );
        while( num > 0 ) {
            *start += 1;
            buf->le.page_num[2] = *start;
            buf->le.page_num[1] = *start >> 8;
            buf->le.page_num[0] = *start >> 16;
            buf->le.flags = PAGE_VALID; //NYI: have to figure out how to fill in
            buf = (map_entry *)((char *)buf + sizeof(le_map_entry));
            num--;
        }
    } else {
        shift = FmtData.u.os2.segment_shift;
        size = num * sizeof( lx_map_entry );
        while( limit > 0 ) {
            buf->lx.page_offset = *start >> shift;
            if( limit > OSF_DEF_PAGE_SIZE ) {
                buf->lx.data_size = OSF_DEF_PAGE_SIZE;
                limit -= OSF_DEF_PAGE_SIZE;
            } else {
                buf->lx.data_size = ROUND_SHIFT( limit, shift );
                limit = 0;
            }
            *start += buf->lx.data_size;
            buf->lx.flags = PAGE_VALID; //NYI: have to figure out how to fill in
            buf = (map_entry *)((char *)buf + sizeof(lx_map_entry));
        }
    }
    return( size );
}

static unsigned_32 WriteObjectTables( os2_flat_header *header,unsigned long loc)
/******************************************************************************/
/* write the object table and the object page map */
{
    unsigned_32     numpages;
    unsigned_32     numobjects;
    unsigned_32     size;
    unsigned_32     start;
    unsigned_32     sizeleft;
    group_entry *   group;
    object_record   objrec;
    unsigned        map_size;
    seg_leader *    leader;

    header->objtab_off = loc;
    numpages = 0;
    numobjects = 0;
    objrec.reserved = 0;
    if( DataGroup != NULL ) {
        header->autodata_obj = DataGroup->grp_addr.seg;
    } else {
        header->autodata_obj = 0;
    }
    for( group = Groups; group != NULL; group = group->next_group ) {
        if( group->totalsize == 0 ) continue;   // DANGER DANGER DANGER <--!!!
        if( group->grp_addr.seg == StackAddr.seg ) {
            header->stack_obj = StackAddr.seg;
            header->esp = StackAddr.off - group->grp_addr.off;
        }
        if( group->grp_addr.seg == StartInfo.addr.seg ) {
            header->start_obj = StartInfo.addr.seg;
            header->eip = StartInfo.addr.off - group->grp_addr.off;
        }
        objrec.size = group->totalsize;
        objrec.addr = group->linear;
        objrec.flags = 0;
        /* segflags are in OS/2 V1.x format, we have to translate them
            into the appropriate V2.0 bits */
        leader = Ring2First( group->leaders );
        if( leader->info & USE_32 ) {
            objrec.flags |= OBJ_BIG;
        } else { //if( group->u.miscflags & SEG_16_ALIAS ) {
            objrec.flags |= OBJ_ALIAS_REQUIRED;
        }
        if( (group->segflags & SEG_LEVEL_MASK) != SEG_LEVEL_3 ) {
            objrec.flags |= OBJ_IOPL;
        }
        if( group->segflags & SEG_DATA ) {
            objrec.flags |= OBJ_READABLE;
            if( !(group->segflags & SEG_READ_ONLY) ) {
                objrec.flags |= OBJ_WRITEABLE;
            }
        } else {
            objrec.flags |= OBJ_EXECUTABLE;
            if( !(group->segflags & SEG_READ_ONLY) ) {
                objrec.flags |= OBJ_READABLE;
            }
        }
        if( group->segflags & SEG_DISCARD ) {
            objrec.flags |= OBJ_DISCARDABLE;
        }
        if( group->segflags & SEG_PURE || (group == DataGroup &&
                         FmtData.u.os2.flags & SINGLE_AUTO_DATA) ) {
            objrec.flags |= OBJ_SHARABLE;
        }
        if( group->segflags & SEG_PRELOAD ) {
            objrec.flags |= OBJ_HAS_PRELOAD;
        }
        if( group->segflags & SEG_CONFORMING ) {
            objrec.flags |= OBJ_CONFORMING;
        }
        if( group->segflags & SEG_INVALID ) {
            objrec.flags |= OBJ_HAS_INVALID;
        }
        objrec.flags |= (group->segflags & SEG_RESIDENT_MASK)
                                                 << SEG_RESIDENT_SHIFT;
        objrec.mapidx = numpages + 1;
        objrec.mapsize = PAGE_COUNT( group->size );
        WriteLoad( &objrec, sizeof( object_record ) );
        numpages += objrec.mapsize;
        numobjects++;
    }
    header->num_objects = numobjects;
    header->num_pages = numpages;
    size = numobjects * sizeof(object_record);
    loc += size;
    header->objmap_off = loc;
    start = 0;
    for( group = Groups; group != NULL; group = group->next_group ) {
        if( group->totalsize == 0 ) continue;   // DANGER DANGER DANGER <--!!!
        sizeleft = group->size;
        while( sizeleft > PAGEMAP_BUF_SIZE ) {
            map_size = NumberBuf( &start, PAGEMAP_BUF_SIZE,
                                  (map_entry *)TokBuff );
            size += map_size;
            WriteLoad( TokBuff, map_size );
            sizeleft -= PAGEMAP_BUF_SIZE;
        }
        map_size = NumberBuf( &start, sizeleft, (map_entry *)TokBuff );
        size += map_size;
        WriteLoad( TokBuff, map_size );
    }
    return( size );
}

/*
 * NOTE: The routine DumpEntryTable in LOADOS2.C is very similar to this
 *       one, however there are 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 DumpFlatEntryTable( void )
/*********************************************/
/* Dump the entry table to the file */
{
    entry_export        *start;
    entry_export        *place;
    entry_export        *prev;
    unsigned            prevord;
    unsigned long       size;
    unsigned            gap;
    unsigned            entries;
    union {
        flat_bundle_prefix      real;
        flat_null_prefix        null;
    }                   prefix;
    flat_bundle_entry32 bundle_item;
    flat_bundle_entryfwd bundle_fwd;

    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.null.b32_cnt = 0xFF;
                prefix.null.b32_type = FLT_BNDL_EMPTY;   // Null bundles.
                while( gap > 0xff ) {
                    WriteLoad( &prefix.null, sizeof( prefix.null ) );
                    gap -= 0xFF;
                    size += sizeof( prefix.null );
                }
                prefix.null.b32_cnt = (unsigned_8) gap;
                WriteLoad( &prefix.null, sizeof( prefix.null ) );
                size += sizeof( prefix.null );
            }
            // now get a bundle of ordinals.
            entries = 1;
            prev = start = place;
            place = place->next;
            while( place != NULL ) {
                if( entries >= 0xff ) break;
                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;
            }
            prefix.real.b32_cnt = entries;
            if (start->addr.seg == 0xFFFF) {
                // Forwarder entry
                prefix.real.b32_type = FLT_BNDL_ENTRYFWD;
                prefix.real.b32_obj = 0;
                size += entries * sizeof( flat_bundle_entryfwd );
            } else {
                // 32-bit entry
                prefix.real.b32_type = FLT_BNDL_ENTRY32;
                prefix.real.b32_obj = start->addr.seg;
                size += entries * sizeof( flat_bundle_entry32 );
            }
            prevord = prev->ordinal;
            WriteLoad( &prefix.real, sizeof( prefix.real ) );
            size += sizeof( prefix.real );
            for( ; entries > 0; --entries, start = start->next ) {
                if (start->addr.seg == 0xFFFF) {
                    // Forwarder entry
                    dll_sym_info   *dll = start->sym->p.import;

                    bundle_fwd.e32_flags = 0;
                    bundle_fwd.modord    = dll->m.modnum->num;
                    if (dll->isordinal) {
                        bundle_fwd.e32_flags |= 1;
                        bundle_fwd.value     = dll->u.ordinal;
                    } else {

⌨️ 快捷键说明

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