loados2.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,176 行 · 第 1/3 页
C
1,176 行
for( node = val; node != NULL; node = node->next ) {
++i;
WriteLoad( &(node->len), sizeof(unsigned char) ); // NOTE:little endian
if( upper ) {
for( j = node->len-1; j >= 0; --j ) {
node->name[j] = toupper( node->name[j] );
}
}
WriteLoad( node->name, node->len );
off += node->len + 1;
}
*count = i;
return( off );
}
extern unsigned long ImportProcTable( unsigned long *count )
/**********************************************************/
{
return( WriteTabList( FmtData.u.os2.imp_tab_list, count,
!(LinkFlags & CASE_FLAG) ) );
}
extern unsigned long ImportModTable( unsigned long *count )
/*********************************************************/
{
return( WriteTabList( FmtData.u.os2.mod_ref_list, count, FALSE ) );
}
static unsigned long ImportNameTable( void )
/******************************************/
{
unsigned long count;
unsigned long size;
PadLoad( 1 );
size = 1;
size += ImportProcTable( &count );
size += ImportModTable( &count );
return( size );
}
static unsigned long ModRefTable( void )
/**************************************/
/* count total number of groups */
{
name_list * node;
name_list * inode;
unsigned long nodenum;
unsigned long off;
if( FmtData.type & MK_OS2_16BIT ) {
off = 1;
for( inode = FmtData.u.os2.imp_tab_list; inode != NULL;
inode = inode->next ) {
off += inode->len + 1;
}
} else {
off = 0;
}
nodenum = 0;
for( node = FmtData.u.os2.mod_ref_list; node != NULL; node = node->next ) {
WriteLoad( &off, sizeof(unsigned_16) );
off += node->len + 1;
nodenum++;
}
return nodenum;
}
extern unsigned long ResNonResNameTable( bool dores )
/***************************************************/
/* NOTE: this routine assumes INTEL byte ordering (in the use of namelen) */
{
entry_export * exp;
int namelen;
unsigned long size;
char * name;
size = 0;
if( dores ) {
if( FmtData.u.os2.res_module_name != NULL ) {
name = FmtData.u.os2.res_module_name;
namelen = strlen( name );
} else {
name = RemovePath( Root->outfile->fname, &namelen );
}
} else { /* in non-resident names table */
if( FmtData.u.os2.description != NULL ) {
name = FmtData.u.os2.description;
} else if( FmtData.type & MK_OS2_16BIT ) {
name = Root->outfile->fname;
} else {
name = "";
}
namelen = strlen( name );
}
if( dores || namelen > 0 ) {
WriteLoad( &namelen, 1 );
WriteLoad( name, namelen );
PadLoad( 2 );
size += namelen + 3;
}
if( dores && FmtData.u.os2.res_module_name != NULL ) {
_LnkFree( name );
FmtData.u.os2.res_module_name = NULL;
}
if( !dores && FmtData.u.os2.description != NULL ) {
_LnkFree( name );
FmtData.u.os2.description = NULL;
}
for( exp = FmtData.u.os2.exports; exp != NULL; exp = exp->next ) {
if( !exp->isexported ) continue;
if( exp->isanonymous ) continue;
if( (dores && exp->isresident) || (!dores && !exp->isresident) ) {
if( !(LinkFlags & CASE_FLAG) ) {
strupr( exp->name );
}
namelen = strlen( exp->name );
WriteLoad( &namelen, 1 );
WriteLoad( exp->name, namelen );
WriteLoad( &(exp->ordinal), 2 );
size += namelen + 3;
if( !exp->isprivate ) {
if( exp->impname != NULL ) {
AddImpLibEntry(exp->impname, exp->name, NOT_IMP_BY_ORDINAL);
} else {
AddImpLibEntry( exp->sym->name, NULL, exp->ordinal );
}
}
}
}
if( size > 0 ) {
PadLoad( 1 );
++size;
}
return( size );
}
/*
* NOTE: The routine DumpFlatEntryTable in LOADFLAT.C is very similar to this
* one, however there are a 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 DumpEntryTable( void )
/*****************************************/
/* Dump the entry table to the file */
{
entry_export * start;
entry_export * place;
entry_export * prev;
unsigned_16 prevord;
unsigned long size;
unsigned gap;
unsigned entries;
bundle_prefix prefix;
union {
fixed_record f;
movable_record m;
} bundle_item;
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.number = 0xFF;
prefix.type = 0x00; // Null bundles.
while( gap > 0xff ) {
WriteLoad( &prefix, sizeof( bundle_prefix ) );
gap -= 0xFF;
size += 2;
}
prefix.number = (unsigned_8) gap;
WriteLoad( &prefix, sizeof( bundle_prefix ) );
size += 2;
}
// now get a bundle of ordinals.
entries = 1;
prev = start = place;
place = place->next;
while( place != NULL ) {
if( entries >= 0xff ) break;
if( start->ismovable ) {
if( !place->ismovable )break;
} else {
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;
}
if( start->ismovable ) {
prefix.type = MOVABLE_ENTRY_PNT;
bundle_item.m.reserved = 0x3fcd; /* int 0x3f */
size += entries * sizeof( movable_record );
} else {
prefix.type = start->addr.seg; // fixed segment records.
size += entries * sizeof( fixed_record );
}
prevord = prev->ordinal;
prefix.number = (unsigned_8) entries;
WriteLoad( &prefix, sizeof( bundle_prefix ) );
size += 2;
for( ; entries > 0; --entries ) {
bundle_item.f.info = (start->iopl_words << IOPL_WORD_SHIFT);
if( start->isexported ) {
bundle_item.f.info |= ENTRY_EXPORTED;
if( FmtData.u.os2.flags & SHARABLE_DGROUP ) {
bundle_item.f.info |= ENTRY_SHARED;
}
}
if( start->ismovable ) {
if( start->addr.seg > 0xFF ) {
LnkMsg( WRN+MSG_BAD_MOVABLE_SEG_NUM, NULL );
}
bundle_item.m.entrynum = start->addr.seg;
bundle_item.m.entry = start->addr.off;
WriteLoad( &bundle_item, sizeof( movable_record ) );
} else {
bundle_item.f.entry = start->addr.off;
WriteLoad( &bundle_item, sizeof( fixed_record ) );
}
start = start->next;
}
}
}
PadLoad( 2 );
return( size + 2 );
}
extern void ChkOS2Data()
/**********************/
{
SetSegFlags( (seg_flags *) FmtData.u.os2.os2_seg_flags );
FmtData.u.os2.os2_seg_flags = NULL;
}
extern void ChkOS2Exports( void )
/*******************************/
// NOTE: there is a continue in this loop!
{
symbol * symptr;
entry_export * exp;
group_entry * group;
unsigned num_entries;
SetGroupFlags(); // NOTE: there is a continue in this loop!
num_entries = 0;
for( exp = FmtData.u.os2.exports; exp != NULL; exp = exp->next ) {
num_entries++;
symptr = exp->sym;
if( IS_SYM_ALIAS( symptr ) ) {
symptr = UnaliasSym( ST_FIND, symptr );
if( symptr == NULL || !(symptr->info & SYM_DEFINED) ) {
LnkMsg( ERR+MSG_EXP_SYM_NOT_FOUND, "s", exp->sym->name );
continue; // <----- DANGER weird control flow!
} else if( exp->sym->info & SYM_WAS_LAZY ) {
LnkMsg( WRN+MSG_EXP_SYM_NOT_FOUND, "s", exp->sym->name );
}
exp->sym = symptr;
}
if( !(symptr->info & SYM_DEFINED) ) {
LnkMsg( ERR+MSG_EXP_SYM_NOT_FOUND, "s", symptr->name );
} else {
exp->addr = symptr->addr;
if( symptr->p.seg == NULL || IS_SYM_IMPORTED(symptr) ) {
if( FmtData.type & MK_OS2_FLAT ) {
// MN: Create a forwarder - add a special flag?
// Currently DumpFlatEntryTable() in loadflat.c will
// recognize a forwarder by segment == 0xFFFF
} else {
LnkMsg( ERR+MSG_CANT_EXPORT_ABSOLUTE, "S", symptr );
}
} else {
group = symptr->p.seg->u.leader->group;
if( FmtData.type & MK_OS2_FLAT ) {
exp->addr.off -= group->grp_addr.off;
} else if( FmtData.type & MK_PE ) {
exp->addr.off += (group->linear - group->grp_addr.off);
}
if( group->segflags & SEG_MOVABLE ) {
exp->ismovable = TRUE;
}
}
}
} // NOTE: there is a continue in this loop!
AssignOrdinals(); /* make sure all exports have ordinals */
if(( FmtData.type & MK_WIN_VXD ) && ( num_entries != 1 )) {
LnkMsg( FTL+MSG_VXD_INCORRECT_EXPORT, NULL );
}
}
extern void PhoneyStack( void )
/*****************************/
// signal that we will be making a fake stack later on.
{
FmtData.u.os2.flags |= PHONEY_STACK_FLAG;
}
static WResDir InitNEResources(int *resHandle, ResTable *outRes)
/**************************************************************/
{
WResDir inRes;
int dup_discarded;
int error;
if( FmtData.resource ) {
*resHandle = QOpenR( FmtData.resource );
inRes = WResInitDir();
error = WResReadDir( *resHandle, inRes, &dup_discarded );
if( error ) {
LnkMsg( WRN+MSG_PROBLEM_IN_RESOURCE, NULL );
inRes = NULL;
}
outRes->Dir.NumTypes = WResGetNumTypes( inRes );
outRes->Dir.NumResources = WResGetNumResources( inRes );
outRes->Dir.TableSize = outRes->Dir.NumTypes * sizeof(resource_type_record) +
outRes->Dir.NumResources * sizeof(resource_record) +
2 * sizeof(uint_16);
/* the 2 uint_16 are the resource shift count and the type 0 record */
outRes->Dir.Head = NULL;
outRes->Dir.Tail = NULL;
StringBlockBuild( &outRes->Str, inRes, FALSE );
} else {
inRes = NULL;
}
return inRes;
}
static void FiniNEResources( int resHandle, WResDir inRes, ResTable *outRes )
/***************************************************************************/
{
if( inRes != NULL ) {
if( outRes->Str.StringBlock != NULL ) {
_LnkFree( outRes->Str.StringBlock );
outRes->Str.StringBlock = NULL;
}
if( outRes->Str.StringList != NULL ) {
_LnkFree( outRes->Str.StringList );
outRes->Str.StringList = NULL;
}
WResFreeDir( inRes );
QClose( resHandle, FmtData.resource );
}
}
static uint_32 ComputeResourceSize( WResDir dir )
/***********************************************/
{
uint_32 length;
WResDirWindow wind;
WResLangInfo * res;
if( dir == NULL ) {
return 0;
}
length = 0;
wind = WResFirstResource( dir );
while( !WResIsEmptyWindow( wind ) ) {
res = WResGetLangInfo( wind );
length += res->Length;
wind = WResNextResource( wind, dir );
}
return( length );
}
#define MAX_DGROUP_SIZE (64*1024UL)
extern void FiniOS2LoadFile()
/***************************/
/* terminate writing of load file */
{
os2_exe_header exe_head;
unsigned long temp;
unsigned_16 adseg;
group_entry * group;
unsigned_32 stub_len;
unsigned_32 dgroup_size;
unsigned long size;
entry_export * exp;
unsigned long imageguess; // estimated length of the image
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?