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