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