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 + -
显示快捷键?