loados2.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,176 行 · 第 1/3 页
C
1,176 行
unsigned pad_len;
WResDir inRes; // Directory of resources to read
int resHandle; // Handle for resources file
ResTable outRes; // Resources to go out
stub_len = Write_Stub_File();
temp = sizeof(os2_exe_header);
exe_head.segment_off = temp;
SeekLoad( stub_len+sizeof(os2_exe_header) );
adseg = 0;
exe_head.segments = 0;
dgroup_size = 0;
imageguess = 0;
if( DataGroup != NULL ) {
adseg = DataGroup->grp_addr.seg;
if( DataGroup->segflags & SEG_PURE ) {
FmtData.u.os2.flags |= SHARABLE_DGROUP;
}
if( StackSegPtr != NULL ) {
if( DataGroup->totalsize - DataGroup->size < StackSize ) {
StackSize = DataGroup->totalsize - DataGroup->size;
DataGroup->totalsize = DataGroup->size;
} else {
DataGroup->totalsize -= StackSize;
}
}
dgroup_size = DataGroup->totalsize;
}
for( group = Groups; group != NULL; group = group->next_group ) {
if( group->totalsize == 0 ) continue; // DANGER DANGER DANGER <--!!!
imageguess += group->size;
exe_head.segments++;
}
temp += exe_head.segments * sizeof(segment_record);
inRes = InitNEResources(&resHandle, &outRes);
exe_head.resource_off = temp;
if (inRes) {
exe_head.resource = outRes.Dir.NumResources;
temp += outRes.Dir.TableSize;
temp += outRes.Str.StringBlockSize;
} else {
exe_head.resource = 0;
}
exe_head.resident_off = temp;
SeekLoad( stub_len+temp );
temp += ResNonResNameTable( TRUE ); // TRUE - do resident table.
exe_head.module_off = temp;
exe_head.modrefs = ModRefTable();
temp += exe_head.modrefs * sizeof( unsigned_16 );
exe_head.import_off = temp;
temp += ImportNameTable();
exe_head.entry_off = temp;
size = DumpEntryTable();
exe_head.entry_size = size;
temp += size;
temp += stub_len;
exe_head.nonres_off = temp;
exe_head.nonres_size = ResNonResNameTable( FALSE ); // FALSE = do non-res.
temp += exe_head.nonres_size;
/*
* if no segment shift specified, figure out the best one, assuming that
* the maximum padding will happen every time.
*/
if( FmtData.u.os2.segment_shift == 0 ) {
imageguess += temp +(unsigned long)Root->relocs * sizeof(os2_reloc_item)
+ stub_len + exe_head.segments * 3;
pad_len = binary_log( (imageguess >> 16) << 1 );
imageguess += ((1 << pad_len) - 1) * exe_head.segments;
imageguess += ComputeResourceSize( inRes ); // inRes may be 0
FmtData.u.os2.segment_shift = binary_log( (imageguess >> 16) << 1 );
if( FmtData.u.os2.segment_shift == 0 ) {
FmtData.u.os2.segment_shift = 1; // since microsoft thinks 0 == 9
}
}
exe_head.gangstart = NullAlign( 1 << FmtData.u.os2.segment_shift ) >>
FmtData.u.os2.segment_shift;
WriteOS2Data( stub_len, &exe_head );
WriteOS2Resources( resHandle, inRes, &outRes );
exe_head.gangstart = 0;
exe_head.ganglength = 0;
if( inRes ) {
SeekLoad( exe_head.resource_off + stub_len );
WriteResTable( &outRes );
FreeResTable( &outRes );
}
SeekEndLoad( 0 );
FiniNEResources( resHandle, inRes, &outRes );
WriteDBI();
exe_head.signature = OS2_SIGNATURE_WORD;
exe_head.version = 0x0105; /* version 5.1 */
exe_head.chk_sum = 0L;
exe_head.info = 0;
if( FmtData.type & MK_WINDOWS ) {
exe_head.target = TARGET_WINDOWS;
} else {
exe_head.target = TARGET_OS2;
}
if( FmtData.u.os2.flags & PROTMODE_ONLY ) {
exe_head.info |= OS2_PROT_MODE_ONLY;
}
if( FmtData.u.os2.flags & SINGLE_AUTO_DATA ) {
exe_head.info |= OS2_SINGLE_AUTO;
} else if( FmtData.u.os2.flags & MULTIPLE_AUTO_DATA ){
exe_head.info |= OS2_MULT_AUTO;
} else {
adseg = 0; // no automatic data segment.
}
if( FmtData.u.os2.flags & PM_NOT_COMPATIBLE ) {
exe_head.info |= OS2_NOT_PM_COMPATIBLE;
} else if( FmtData.u.os2.flags & PM_APPLICATION ) {
exe_head.info |= OS2_PM_APP;
} else {
exe_head.info |= OS2_PM_COMPATIBLE;
}
if( FmtData.u.os2.is_private_dll ) {
exe_head.info |= WIN_PRIVATE_DLL;
}
if( FmtData.dll ) {
exe_head.info |= OS2_IS_DLL;
if( FmtData.u.os2.flags & INIT_INSTANCE_FLAG ) {
exe_head.info |= OS2_INIT_INSTANCE;
}
}
if( LinkState & LINK_ERROR ) {
exe_head.info |= OS2_LINK_ERROR;
}
exe_head.adsegnum = adseg;
exe_head.heap = FmtData.u.os2.heapsize;
/*
* the microsoft linker for windows will generate a stack even if no stack
* segment has been explicitly specified. (as long as the user specifies a stack
* size). Since microsoft's windows libraries rely on this, we have to mimic
* it.
*/
if( FmtData.u.os2.flags & PHONEY_STACK_FLAG ) {
exe_head.SP = 0;
exe_head.stacknum = adseg;
} else {
exe_head.SP = 0;
//exe_head.SP = StackAddr.off;
if( StackAddr.seg != UNDEFINED ) {
exe_head.stacknum = StackAddr.seg;
} else {
exe_head.stacknum = 0;
}
}
exe_head.stack = StackSize;
if( dgroup_size + exe_head.heap > MAX_DGROUP_SIZE ) {
LnkMsg( WRN+MSG_HEAP_TOO_BIG, NULL );
if( dgroup_size < MAX_DGROUP_SIZE ) {
exe_head.heap = MAX_DGROUP_SIZE - dgroup_size;
}
}
exe_head.IP = StartInfo.addr.off;
if( StartInfo.type == START_UNDEFED ) {
exe_head.entrynum = 0;
} else {
exe_head.entrynum = StartInfo.addr.seg;
}
exe_head.align = FmtData.u.os2.segment_shift;
exe_head.movable = 0;
for( exp = FmtData.u.os2.exports; exp != NULL; exp = exp->next ) {
if( exp->ismovable ) {
exe_head.movable++;
}
}
exe_head.otherflags = 0;
if( FmtData.u.os2.flags & LONG_FILENAMES ) {
exe_head.otherflags = OS2_LONG_FILE_NAMES;
}
if( FmtData.u.os2.flags & PROPORTIONAL_FONT ) {
exe_head.otherflags |= WIN_CLEAN_MEMORY | WIN_PROPORTIONAL_FONT;
} else if( FmtData.u.os2.flags & CLEAN_MEMORY ) {
exe_head.otherflags |= WIN_CLEAN_MEMORY;
}
if (exe_head.ganglength) {
exe_head.otherflags |= WIN_GANGLOAD_PRESENT;
}
exe_head.swaparea = 0;
if( FmtData.type & MK_WINDOWS ) {
if( FmtData.ver_specified ) {
exe_head.expver = (FmtData.major << 8) | (FmtData.minor & 0xFF);
} else {
exe_head.expver = 0x300;
}
} else {
exe_head.expver = 0;
}
SeekLoad( stub_len );
WriteLoad( &exe_head, sizeof(os2_exe_header) );
}
extern void FreeImpNameTab( void )
/********************************/
{
FmtData.u.os2.mod_ref_list = NULL; /* these are permalloc'd */
FmtData.u.os2.imp_tab_list = NULL;
}
#define DEF_SEG_ON (SEG_PURE|SEG_READ_ONLY|SEG_CONFORMING|SEG_MOVABLE|SEG_DISCARD|SEG_RESIDENT|SEG_CONTIGUOUS|SEG_NOPAGE)
#define DEF_SEG_OFF (SEG_PRELOAD|SEG_INVALID)
static void CheckGrpFlags( void *_leader )
/****************************************/
{
seg_leader *leader = _leader;
unsigned_16 sflags;
sflags = leader->segflags;
// if any of these flags are on, turn it on for the entire group.
leader->group->segflags |= sflags & DEF_SEG_OFF;
// if any of these flags off, make sure they are off in the group.
leader->group->segflags &= sflags & DEF_SEG_ON | ~DEF_SEG_ON;
if( (sflags & SEG_LEVEL_MASK) == SEG_LEVEL_2 ) {
/* if any are level 2 then all have to be. */
leader->group->segflags &= ~SEG_LEVEL_MASK;
leader->group->segflags |= SEG_LEVEL_2;
}
}
static void SetGroupFlags( 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->totalsize == 0 ) continue; // DANGER DANGER DANGER <--!!!
group->segflags |= DEF_SEG_ON;
Ring2Walk( group->leaders, CheckGrpFlags );
/* for some insane reason, level 2 segments must be marked as
movable */
if( (group->segflags & SEG_LEVEL_MASK) == SEG_LEVEL_2 ) {
group->segflags |= SEG_MOVABLE;
}
}
}
static unsigned DoExeName( void )
/*******************************/
/* make up the "program is %f" string, and put it in tokbuff.*/
{
char rc_buff[RESOURCE_MAX_SIZE];
unsigned msgsize;
Msg_Get( MSG_IS_A_EXE, rc_buff );
msgsize = FmtStr( TokBuff, TokSize, rc_buff );
TokBuff[msgsize++] = '\r';
TokBuff[msgsize++] = '\n';
TokBuff[msgsize] = '$'; /* end of string for int 21 fn. 9 */
return( msgsize + 1 );
}
#define STUB_ALIGN 8 /* for PE format */
#define PARA_ALIGN( x ) (((x)+0xf) & ~0xfUL)
extern unsigned_32 GetStubSize( void )
/************************************/
/* return the size of the stub file */
{
unsigned_32 stub_len;
f_handle the_file;
dos_exe_header dosheader;
unsigned_32 read_len;
unsigned_32 reloc_size;
unsigned_32 code_start;
char * name;
name = FmtData.u.os2.stub_file_name;
stub_len = PARA_ALIGN( sizeof(DosStub) + DoExeName() );
if( name != NULL && stricmp( name, Root->outfile->fname ) != 0 ) {
the_file = SearchPath( name );
if( the_file != NIL_HANDLE ) {
QRead( the_file, &dosheader, sizeof(dos_exe_header), name );
if( dosheader.signature == 0x5A4D ) {
if( dosheader.mod_size == 0 ) {
read_len = 512;
} else {
read_len = dosheader.mod_size;
}
code_start = dosheader.hdr_size * 16ul;
read_len += (dosheader.file_size - 1) * 512ul - code_start;
// make sure reloc_size is a multiple of 16.
reloc_size = (dosheader.num_relocs * 4ul + 15) & ~0xFul;
dosheader.hdr_size = 4 + reloc_size/16;
stub_len = read_len + dosheader.hdr_size * 16ul;
stub_len = (stub_len + (STUB_ALIGN-1)) & ~(STUB_ALIGN-1);
}
QClose( the_file, name );
}
}
return( stub_len );
}
static unsigned WriteDefStub( void )
/**********************************/
/* write the default stub to the executable file */
{
unsigned msgsize;
unsigned fullsize;
unsigned_32 * stubend;
msgsize = DoExeName();
fullsize = PARA_ALIGN(msgsize + sizeof(DosStub) );
stubend = (unsigned_32 *) (DosStub + 0x3c);
*stubend = fullsize;
WriteLoad( DosStub, sizeof(DosStub) );
WriteLoad( TokBuff, msgsize );
PadLoad( fullsize - msgsize - sizeof(DosStub) );
return( fullsize );
}
extern unsigned_32 Write_Stub_File( void )
/****************************************/
{
unsigned_32 stub_len;
f_handle the_file;
dos_exe_header dosheader;
unsigned_32 read_len;
unsigned amount;
unsigned_32 reloc_size;
unsigned_16 num_relocs;
unsigned_32 the_reloc;
unsigned_32 code_start;
char * name;
name = FmtData.u.os2.stub_file_name;
if( name == NULL ) {
stub_len = WriteDefStub();
} else if( stricmp( name, Root->outfile->fname ) == 0 ) {
LnkMsg( ERR+MSG_STUB_SAME_AS_LOAD, NULL );
stub_len = WriteDefStub();
} else {
the_file = SearchPath( name );
if( the_file == NIL_HANDLE ) {
LnkMsg( WRN+MSG_CANT_OPEN_NO_REASON, "s", name );
return( WriteDefStub() ); // NOTE: <== a return here.
}
QRead( the_file, &dosheader, sizeof(dos_exe_header), name );
if( dosheader.signature != 0x5A4D ) {
LnkMsg( ERR + MSG_INV_STUB_FILE, NULL );
stub_len = WriteDefStub();
} else {
if( dosheader.mod_size == 0 ) {
read_len = 512;
} else {
read_len = dosheader.mod_size;
}
QSeek( the_file, dosheader.reloc_offset, name );
dosheader.reloc_offset = 0x40;
code_start = dosheader.hdr_size * 16ul;
read_len += (dosheader.file_size - 1) * 512ul - code_start;
// make sure reloc_size is a multiple of 16.
reloc_size = (dosheader.num_relocs * 4ul + 15) & ~0xFul;
dosheader.hdr_size = 4 + reloc_size/16;
stub_len = read_len + dosheader.hdr_size * 16ul;
dosheader.file_size = (stub_len + 511) >> 9; // round up.
dosheader.mod_size = stub_len % 512;
WriteLoad( &dosheader, sizeof( dos_exe_header ) );
PadLoad( 0x3c - sizeof( dos_exe_header ) );
stub_len = (stub_len + (STUB_ALIGN-1)) & ~(STUB_ALIGN-1);
WriteLoad( &stub_len, sizeof( unsigned_32 ) );
for(num_relocs = dosheader.num_relocs;num_relocs > 0;num_relocs--) {
QRead( the_file, &the_reloc, sizeof( unsigned_32 ), name );
WriteLoad( &the_reloc, sizeof( unsigned_32 ) );
reloc_size -= sizeof(unsigned_32 );
}
if( reloc_size != 0 ) { // need padding
PadLoad( reloc_size );
}
QSeek( the_file, code_start, name );
while( read_len > 0 ) {
if( read_len < TokSize ) {
amount = read_len;
} else {
amount = TokSize;
}
QRead( the_file, TokBuff, amount, name );
WriteLoad( TokBuff, amount );
read_len -= amount;
}
}
QClose( the_file, name );
_LnkFree( name );
FmtData.u.os2.stub_file_name = NULL;
stub_len = NullAlign( STUB_ALIGN );
}
return( stub_len );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?