loadqnx.c

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

C
459
字号
    record.data_nbytes = sizeof( RWEndRec );
    WriteLoad( &record, sizeof( lmf_record ) );
    RWEndRec.verify ^= (unsigned_16) ~0;
    WriteLoad( &RWEndRec, sizeof( RWEndRec ) );
    /* write all read only segment data */
    for( grp = Groups; grp != NULL; grp = grp->next_group ){
        if( grp->u.qnxflags != QNX_READ_WRITE && grp->totalsize != 0 ) {
            WriteQNXGroup( grp, segments );
        }
        WriteQNXRelocs( grp->g.grp_relocs, LMF_LINEAR_FIXUP_REC,
                        QNX_SEL_NUM(grp->grp_addr.seg) );
    }
}


static void WriteQNXRelocs( void *head, unsigned lmf_type, unsigned_16 seg )
/**************************************************************************/
{
    lmf_record          record;
    unsigned_32         pos;
    unsigned_32         size;
    bool                islinear;
    unsigned            adjust;

    adjust = 0;
    record.reserved = record.spare = 0;
    record.rec_type = lmf_type;
    islinear = (lmf_type == LMF_LINEAR_FIXUP_REC);
    if( islinear ) {
        adjust = 2;
    }
    pos = PosLoad();    /* get current position */
    while( head != NULL ) {
        SeekLoad( pos + sizeof(lmf_record) );
        if( islinear ) {
            WriteLoad( &seg, sizeof(unsigned_16) );
        }
        size = DumpMaxRelocList( &head, QNX_MAX_FIXUPS - adjust ) + adjust;
        SeekLoad( pos );
        record.data_nbytes = size;
        WriteLoad( &record, sizeof( lmf_record ) );
        pos += size + sizeof( lmf_record );
    }
    SeekLoad( pos );
}

extern void SetQNXSegFlags( void )
/********************************/
{
    SetSegFlags( (seg_flags *) FmtData.u.qnx.seg_flags );
    FmtData.u.qnx.seg_flags = NULL;        // segsegflags frees the list.
    SetQNXGroupFlags();
}

static void WriteQNXResource( void )
/**********************************/
{
    unsigned long   len;
    lmf_record      rec;
    f_handle        file;
    lmf_resource    resource;
    void *          buf;

    if( FmtData.resource != NULL ) {
        rec.reserved = 0;
        rec.spare = 0;
        rec.rec_type = LMF_RESOURCE_REC;
        memset( &resource, 0, sizeof( lmf_resource ) );
        if( FmtData.res_name_only ) {
            file = QObjOpen( FmtData.resource );
            if( file == NIL_HANDLE ) {
                PrintIOError( WRN+MSG_CANT_OPEN_NO_REASON, "s",
                                        FmtData.resource );
                return;
            }
            len = QFileSize( file );
            if( len + sizeof(lmf_resource) > QNX_MAX_REC_SIZE ) {
                LnkMsg( WRN+MSG_RESOURCE_TOO_BIG, "s", FmtData.resource );
                return;
            }
            _ChkAlloc( buf, len );
            rec.data_nbytes = len + sizeof( lmf_resource );
            WriteLoad( &rec, sizeof( lmf_record ) );
            WriteLoad( &resource, sizeof( lmf_resource ) );
            QRead( file, buf, len, FmtData.resource );
            WriteLoad( buf, len );
            _LnkFree( buf );
            QClose( file, FmtData.resource );
        } else {
            len = strlen( FmtData.resource );
            FmtData.resource[len] = '\n';
            len++;
            rec.data_nbytes = len + sizeof( lmf_resource );
            WriteLoad( &rec, sizeof( lmf_record ) );
            WriteLoad( &resource, sizeof( lmf_resource ) );
            WriteLoad( FmtData.resource, len );
        }
    }
}

extern void FiniQNXLoadFile( void )
/*********************************/
{
    unsigned_32 *   segments;
    unsigned_16     nbytes;
    lmf_record      record;
    lmf_header      header;
    lmf_eof         trailer;
    unsigned        adseg;

    CurrSect = Root;
    if( FmtData.type & MK_QNX_FLAT ) {
        if( FmtData.base < StackSize ) {
            LnkMsg( WRN+MSG_QNX_BASE_LT_STACK, NULL );
        }
    }
    nbytes = NumGroups * sizeof( unsigned_32 );
    segments = (unsigned_32 *) alloca( nbytes );
    SeekLoad( sizeof(lmf_header) + nbytes + sizeof(lmf_record) );
    WriteQNXResource();
    WriteQNXData( segments );
    WriteQNXRelocs( Root->reloclist, LMF_FIXUP_REC, 0 );
    WriteQNXRelocs( FloatFixups, LMF_8087_FIXUP_REC, 0 );
    record.reserved = record.spare = 0;
    record.rec_type = LMF_IMAGE_END_REC;
    record.data_nbytes = sizeof( trailer );
    WriteLoad( &record, sizeof( lmf_record ) );
    memset( &trailer, 0, sizeof( trailer ) );
    WriteLoad( &trailer, sizeof( trailer ) );
    WriteDBI();

    SeekLoad( 0 );
    record.rec_type = LMF_HEADER_REC;
    record.data_nbytes = sizeof( lmf_header ) + nbytes;
    WriteLoad( &record, sizeof( lmf_record ) );
    memset( &header, 0, sizeof( header ) );
    header.version = QNX_VERSION;
    header.cflags = (FmtData.u.qnx.flags
                | (FmtData.u.qnx.priv_level << QNX_PRIV_SHIFT))
                & QNX_FLAG_MASK;
    if( LinkState & FMT_SEEN_32_BIT ) {
        header.cflags |= _TCF_32BIT;
    }
    if( FmtData.type & MK_QNX_FLAT ) {
        header.cflags |= _TCF_FLAT;
    }
    header.fpu = 0;     //NYI: need to set 87, 287, 387
    if( FmtData.cpu_type == 0 ) {        // no model specified, so assume...
        if( LinkState & FMT_SEEN_32_BIT ) {
            header.cpu = 386;
        } else {
            header.cpu = 86;
        }
    } else {
        header.cpu = (FmtData.cpu_type * 100) + 86;
    }
    header.code_index = QNX_SEL_NUM( StartInfo.addr.seg );
    header.stack_index = QNX_SEL_NUM( StackAddr.seg );
    adseg = header.stack_index;
    if( DataGroup != NULL ) {
        adseg = QNX_SEL_NUM( DataGroup->grp_addr.seg );
    }
    header.heap_index = adseg;  // all in DGROUP.
    header.argv_index = adseg;
    header.code_offset = StartInfo.addr.off;
    header.stack_nbytes = StackSize;
    header.heap_nbytes = FmtData.u.qnx.heapsize;
    header.image_base = FmtData.base;
    WriteLoad( &header, sizeof( lmf_header ) );
    WriteLoad( segments, nbytes );
}

extern unsigned_16 ToQNXSel( unsigned_16 seg )
/********************************************/
{
    return( QNX_SELECTOR( seg - 1 ) );
}

extern unsigned_16 ToQNXIndex( unsigned_16 sel )
/**********************************************/
{
    return( QNX_SEL_NUM( sel ) );
}

static bool CheckQNXGrpFlag( void *_seg, void *_grp )
/**************************************************************/
{
    seg_leader     *seg = _seg;
    group_entry    *grp = _grp;
    unsigned_16     sflags;

    sflags = seg->segflags;

// the default value for segflags is set to SEG_LEVEL_3 (0xC00) for OS/2
// and SEG_MOVABLE (0x10) for windows. Since the highest value that can be
// specified for a QNX seg flag is 4, if sflags >= 0x10, there was no QNX value
// specified.

    if( sflags < 0x10 ) {
        if( !(sflags & 1) ) {     // if can read/write or exec/read
            grp->u.qnxflags &= ~1;       // can for all segments.
            return TRUE;                // no need to check others
        }
    } else {
// make segments read/write or exec/read unless every segment is specifically
// set otherwise.
        grp->u.qnxflags &= ~1;
        return TRUE;
    }
    return FALSE;
}

static void SetQNXGroupFlags( void )
/**********************************/
// This goes through the groups, setting the flag word to be compatible with
// the flag words that are specified in the segments.
{
    group_entry *   group;

    for( group = Groups; group != NULL; group = group->next_group ) {
        if( group->segflags & SEG_DATA ) {
            group->u.qnxflags = QNX_READ_ONLY;      // 1
        } else {
            group->u.qnxflags = QNX_EXEC_ONLY;     // 3
        }
        Ring2Lookup( group->leaders, CheckQNXGrpFlag, group );
    }
}

⌨️ 快捷键说明

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