loadqnx.c

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

C
459
字号
/****************************************************************************
*
*                            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:  Routines for creating QNX load files.
*
****************************************************************************/


#include <string.h>
#include "walloca.h"
#include "linkstd.h"
#include "ring.h"
#include "alloc.h"
#include "msg.h"
#include "wlnkmsg.h"
#include "exeqnx.h"
#include "loadqnx.h"
#include "reloc.h"
#include "specials.h"
#include "objcalc.h"
#include "virtmem.h"
#include "fileio.h"
#include "dbgall.h"
#include "loadfile.h"

static offset           AmountWritten;
static bool             InVerifySegment;
static lmf_rw_end       RWEndRec;
static group_entry *    CurrGroup;

static void WriteQNXRelocs( void *head, unsigned lmf_type, unsigned_16 seg );
static void SetQNXGroupFlags( void );

#define QNX_MAX_DATA_SIZE (QNX_MAX_REC_SIZE - sizeof(lmf_data))
#define VERIFY_END (VERIFY_OFFSET + sizeof(RWEndRec.verify))

static void WriteLoadRec( void )
/******************************/
{
    lmf_record      record;
    lmf_data        data;

    record.rec_type = LMF_LOAD_REC;
    record.reserved = record.spare = 0;
    if( CurrGroup->size - AmountWritten > QNX_MAX_DATA_SIZE ){
        record.data_nbytes = QNX_MAX_REC_SIZE;
    } else {
        record.data_nbytes = CurrGroup->size - AmountWritten + sizeof(lmf_data);
    }
    WriteLoad( &record, sizeof( lmf_record ) );
    data.segment = QNX_SEL_NUM( CurrGroup->grp_addr.seg );
    data.offset = AmountWritten;
    WriteLoad( &data, sizeof( lmf_data ) );
}

static void ZeroLoad( virt_mem dummy, unsigned long length )
/**********************************************************/
{
    dummy = dummy;
    PadLoad( length );
}

static void CopyLoad( virt_mem data, unsigned long length )
/*********************************************************/
{
    WriteInfo( data, length );
}

static void WriteQNXInfo( void (*wrfn)(virt_mem, unsigned long), virt_mem data,
                          unsigned long length )
/*****************************************************************************/
{
    unsigned    bufmod;
    unsigned    adjust;

    bufmod = AmountWritten % QNX_MAX_DATA_SIZE;
    while(( bufmod + length ) >= QNX_MAX_DATA_SIZE ) {
        adjust = QNX_MAX_DATA_SIZE - bufmod;
        wrfn( data, adjust );
        AmountWritten += adjust;
        length -= adjust;
        data += adjust;
        bufmod = 0;
        WriteLoadRec();
    }
    if( length > 0 ) {
        wrfn( data, length );
        AmountWritten += length;
    }
}

static void CopyVerify( char *targ, virt_mem src, unsigned long size )
/********************************************************************/
{
    ReadInfo( src, targ, size );
}

static void ZeroVerify( char *targ, virt_mem dummy, unsigned long size )
/**********************************************************************/
{
    dummy = dummy;
    memset( targ, 0, size );
}

static void SetVerifyInfo( void (*wrfn)(char *, virt_mem, unsigned long),
                           virt_mem data, unsigned long length )
/************************************************************************/
{
    offset      newstart;
    char *      targ;

    if( AmountWritten + length <= VERIFY_OFFSET ) return;
    if( AmountWritten >= VERIFY_END ) return;
    newstart = AmountWritten;
    if( AmountWritten < VERIFY_OFFSET ) {
        data += VERIFY_OFFSET - AmountWritten;
        newstart = VERIFY_OFFSET;
    }
    if( newstart + length >= VERIFY_END ) {
        length = VERIFY_END - newstart;
        InVerifySegment = FALSE;
    }
    targ = (char *)(&RWEndRec.verify);
    if( AmountWritten > VERIFY_OFFSET ) {
        targ += AmountWritten - VERIFY_OFFSET;
    }
    wrfn( targ, data, length );
}

static bool WriteSegData( void *_sdata, void *_start )
/****************************************************/
{
    segdata *sdata = _sdata;
    unsigned long *start = _start;
    unsigned long newpos;
    signed long pad;

    if( !sdata->isuninit && !sdata->isdead && sdata->length > 0 ) {
        newpos = *start + sdata->a.delta;
        pad = newpos - AmountWritten;
        DbgAssert( pad >= 0 );
        if( pad > 0 ) {
            if( InVerifySegment ) {
                SetVerifyInfo( ZeroVerify, NULL, pad );
            }
            WriteQNXInfo( ZeroLoad, NULL, pad );
        }
        if( InVerifySegment ) {
            SetVerifyInfo( CopyVerify, sdata->data, sdata->length );
        }
        WriteQNXInfo( CopyLoad, sdata->data, sdata->length );
    }
    return FALSE;
}

static void DoGroupLeader( void *_seg )
/*************************************/
{
    offset      start;
    seg_leader *seg = _seg;

    start = GetLeaderDelta( seg );
    RingLookup( seg->pieces, WriteSegData, &start );
}

static void WriteQNXGroup( group_entry *grp, unsigned_32 *segments )
/******************************************************************/
{
    segment     seg;

    seg = QNX_SEL_NUM( grp->grp_addr.seg );
    segments[seg] = grp->totalsize | ((unsigned_32)grp->u.qnxflags << 28);
    if( StackSegPtr != NULL && grp == StackSegPtr->group ) {
        segments[seg] -= StackSize;      // stack size gets
    }                                    // added on by QNX loader.
    if( grp->size == 0 ) return;
    AmountWritten = 0;
    CurrGroup = grp;
    WriteLoadRec();
    Ring2Walk( grp->leaders, DoGroupLeader );
}

static void WriteQNXData( unsigned_32 * segments )
/************************************************/
{
    group_entry *   grp;
    lmf_record      record;
    bool            first;

    first = TRUE;
    InVerifySegment = FALSE;
    /* write all read/write segment data */
    RWEndRec.signature = 0;
    for( grp = Groups; grp != NULL; grp = grp->next_group ){
        if( grp->u.qnxflags == QNX_READ_WRITE && grp->totalsize != 0 ) {
            if( first && grp->size >= VERIFY_END ) {
                InVerifySegment = TRUE;
                first = FALSE;
            }
            WriteQNXGroup( grp, segments );
        }
        RWEndRec.signature += grp->totalsize;
        RWEndRec.signature <<= 3;
        RWEndRec.signature ^= 0x32476235;
    }
    record.reserved = record.spare = 0;
    record.rec_type = LMF_RW_END_REC;

⌨️ 快捷键说明

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