loadnov.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 733 行 · 第 1/2 页
C
733 行
header->sharedExitProcedureOffset = sharehdr->exitProcedureOffset;
QSeek( handle, 0, name );
return( CopyToLoad( handle, name ) );
}
}
return( 0 );
}
static void GetProcOffsets( fixed_header *header )
/************************************************/
{
symbol * sym;
char * name;
header->checkUnloadProcedureOffset = 0;
if( FmtData.u.nov.checkfn != NULL ) {
sym = FindISymbol( FmtData.u.nov.checkfn );
if( sym == NULL ) {
LnkMsg( WRN+MSG_CHECK_NOT_FOUND, NULL );
} else {
header->checkUnloadProcedureOffset = sym->addr.off;
}
}
if( StartInfo.type == START_IS_SYM ) {
name = StartInfo.targ.sym->name;
} else {
name = DEFAULT_PRELUDE_FN_CLIB;
}
sym = FindISymbol( name );
if( ( sym == NULL ) || !( sym->info & SYM_DEFINED ) ) {
LnkMsg( ERR + MSG_START_PROC_NOT_FOUND, NULL );
} else {
header->codeStartOffset = sym->addr.off;
}
if( FmtData.u.nov.exitfn != NULL ) {
name = FmtData.u.nov.exitfn;
} else {
name = DEFAULT_EXIT_FN_CLIB;
}
sym = FindISymbol( name );
if( sym == NULL ) {
LnkMsg( ERR + MSG_EXIT_PROC_NOT_FOUND, NULL );
} else {
header->exitProcedureOffset = sym->addr.off;
}
}
static unsigned_32 WriteNovData( unsigned_32 file_pos, fixed_header * header )
/****************************************************************************/
// write both the code image and the data image.
{
unsigned_32 codesize;
DEBUG(( DBG_BASE, "Writing data" ));
OrderGroups( CompareProtSegments );
CurrSect = Root; // needed for WriteInfo.
Root->outfile->file_loc = file_pos;
Root->u.file_loc = file_pos;
Root->sect_addr.off = Groups->grp_addr.off;
Root->sect_addr.seg = CODE_SEGMENT;
codesize = WriteNovImage( file_pos, TRUE ); // TRUE = do code.
header->codeImageSize = codesize;
file_pos += codesize;
header->dataImageOffset = file_pos;
Root->outfile->file_loc = file_pos;
Root->u.file_loc = file_pos;
Root->sect_addr.off = Groups->grp_addr.off;
Root->sect_addr.seg = DATA_SEGMENT;
header->dataImageSize = WriteNovImage( file_pos, FALSE ); // do data.
return( codesize + header->dataImageSize );
}
static unsigned_32 WriteNovImage( unsigned_32 file_pos, bool docode )
/*******************************************************************/
// Write a Novell image
{
group_entry *group;
outfilelist * fnode;
bool repos;
bool iscode;
/* write groups.*/
fnode = Root->outfile;
group = Groups;
while( group != NULL ) {
if( group->grp_addr.seg == CODE_SEGMENT ) {
iscode = TRUE;
} else {
iscode = FALSE;
}
if( iscode == docode ) { // logical XNOR would be better, but...
repos = WriteDOSGroup( group );
if( repos ) {
SeekLoad( fnode->file_loc );
}
}
group = group->next_group;
}
return( fnode->file_loc - file_pos );
}
static void NovNameWrite( char *name )
/************************************/
// write a name to the loadfile in the typical novell fashion
{
unsigned_8 len;
if( name != NULL ) {
len = strlen( name );
} else {
len = 0;
name = &len;
}
WriteLoad( &len, sizeof( unsigned_8 ) );
WriteLoad( name, len + 1 );
}
static int __min__(int a, int b)
{
if( a > b )
return( b );
else
return( a );
}
extern void FiniNovellLoadFile( void )
/************************************/
{
unsigned_32 file_size;
fixed_header nov_header;
fixed_hdr_2 second_header;
fixed_hdr_3 third_header;
extended_nlm_header ext_header;
unsigned_32 temp;
unsigned_32 image_size;
char * filename;
char * lastslash;
char ch;
unsigned_8 len;
struct tm * currtime;
time_t thetime;
char * pPeriod = NULL;
char module_name[NOV_MAX_MODNAME_LEN+1];
/* find module name (output file name without the path.) */
lastslash = filename = Root->outfile->fname;
while( *filename != '\0' ) {
ch = *filename++;
if( IS_PATH_SEP( ch ) ) {
lastslash = filename; // NOTE: 1 added already.
}
if( '.' == ch ) {
pPeriod = filename-1;
}
}
strupr( lastslash );
/*
// cull the module name to 8.3 (NOV_MAX_MODNAME_LEN) if necessary
*/
if( pPeriod ) {
len = __min__((pPeriod - lastslash), NOV_MAX_NAME_LEN);
strncpy(module_name, lastslash, len);
strncpy(&module_name[len], pPeriod, NOV_MAX_EXT_LEN + 2); /* + period and null */
module_name[len + NOV_MAX_EXT_LEN + 1] = '\0';
} else {
/* still only copy 8 chars else the module name will be too long */
strncpy(module_name, lastslash, NOV_MAX_NAME_LEN);
}
module_name[NOV_MAX_MODNAME_LEN] = '\0';
if( 0 != strcmp( module_name, lastslash ) ) {
LnkMsg( WRN+MSG_INTERNAL_MOD_NAME_DIFF_FROM_FILE, "s", module_name );
}
len = strlen( module_name ); // length of module name;
file_size = strlen( FmtData.u.nov.description ) + sizeof( fixed_header )
+ sizeof( extended_nlm_header ) + 2 * sizeof( unsigned_32 )
+ 12*sizeof( unsigned_8 );
if( FmtData.u.nov.screenname != NULL ) {
file_size += strlen( FmtData.u.nov.screenname );
}
if( FmtData.u.nov.threadname != NULL ) {
file_size += strlen( FmtData.u.nov.threadname );
} else {
file_size += len;
}
if( ( FmtData.major != 0 ) || ( FmtData.minor != 0 ) ) {
file_size += sizeof( fixed_hdr_2 );
}
if( FmtData.u.nov.copyright != NULL ) {
file_size += sizeof( fixed_hdr_3 ) + strlen( FmtData.u.nov.copyright );
}
SeekLoad( file_size );
nov_header.codeImageOffset = file_size;
image_size = WriteNovData( file_size, &nov_header );
temp = MemorySize() - image_size;
if( temp > 0 ) { // write out BSS.
PadLoad( temp );
nov_header.dataImageSize += temp;
image_size += temp;
}
file_size += image_size;
nov_header.relocationFixupOffset = file_size;
file_size += WriteNovRelocs( &nov_header );
nov_header.externalReferencesOffset = file_size;
file_size += WriteNovImports( &nov_header );
nov_header.publicsOffset = file_size;
file_size += WriteNovExports( &nov_header );
nov_header.moduleDependencyOffset = file_size;
file_size += WriteNovModules( &nov_header );
nov_header.customDataOffset = file_size;
temp = AppendToLoadFile( FmtData.u.nov.customdata );
nov_header.customDataSize = temp;
file_size += temp;
memset( &ext_header, 0, sizeof( ext_header ) );
memcpy( ext_header.stamp, EXTENDED_NLM_SIGNATURE,
EXTENDED_NLM_SIGNATURE_LENGTH );
ext_header.messageFileOffset = file_size;
file_size += WriteMessages( &ext_header );
ext_header.helpFileOffset = file_size;
temp = AppendToLoadFile( FmtData.u.nov.help );
ext_header.helpFileLength = temp;
file_size += temp;
ext_header.RPCDataOffset = file_size;
temp = AppendToLoadFile( FmtData.u.nov.rpcdata );
ext_header.RPCDataLength = temp;
file_size += temp;
file_size += WriteSharedNLM( &ext_header, file_size );
nov_header.debugInfoOffset = file_size;
file_size += WriteNovDBI( &nov_header );
WriteDBI();
memcpy( nov_header.signature, NLM_SIGNATURE, sizeof( NLM_SIGNATURE ) );
nov_header.version = NLM_VERSION;
nov_header.moduleName[0] = len;
memcpy( &nov_header.moduleName[1], module_name, len );
memset( &nov_header.moduleName[ len + 1 ], 0, NOV_MAX_MODNAME_LEN-len ); // zero rest.
nov_header.uninitializedDataSize = 0; // MemorySize() - image_size;
GetProcOffsets( &nov_header );
nov_header.moduleType = FmtData.u.nov.moduletype;
nov_header.flags = FmtData.u.nov.exeflags;
nov_header.descriptionLength = strlen( FmtData.u.nov.description );
SeekLoad( 0L );
WriteLoad( &nov_header, sizeof( nov_header ) );
WriteLoad( FmtData.u.nov.description, nov_header.descriptionLength + 1 );
WriteLoad( &StackSize, sizeof( unsigned_32 ) );
temp = 0;
WriteLoad( &temp, sizeof( unsigned_32 ) ); // reserved.
WriteLoad( DUMMY_THREAD_NAME, OLD_THREAD_NAME_LENGTH );
NovNameWrite( FmtData.u.nov.screenname );
if( FmtData.u.nov.threadname != NULL ) {
NovNameWrite( FmtData.u.nov.threadname );
} else {
NovNameWrite( module_name ); // use module name as a default
}
if( ( FmtData.major != 0 ) || ( FmtData.minor != 0 ) ) {
memcpy( second_header.versionSignature, VERSION_SIGNATURE,
VERSION_SIGNATURE_LENGTH );
second_header.majorVersion = FmtData.major;
second_header.minorVersion = FmtData.minor;
second_header.revision = FmtData.revision;
thetime = time( NULL );
currtime = localtime( &thetime );
second_header.year = currtime->tm_year + 1900;
second_header.month = currtime->tm_mon + 1;
second_header.day = currtime->tm_mday;
WriteLoad( &second_header, sizeof( second_header ) );
}
if( FmtData.u.nov.copyright != NULL ) {
memcpy( third_header.copyrightSignature, COPYRIGHT_SIGNATURE,
COPYRIGHT_SIGNATURE_LENGTH);
WriteLoad( &third_header, sizeof( third_header ) );
NovNameWrite( FmtData.u.nov.copyright );
}
WriteLoad( &ext_header, sizeof( ext_header ) );
}
extern void AddNovImpReloc( symbol *sym, unsigned_32 offset, bool isrelative,
bool isdata )
/****************************************************************************/
// add a relocation to the import record.
{
nov_import * imp;
nov_import * new;
virt_mem vmem_ptr;
unsigned vblock; // which virt_mem block
unsigned voff; // offset into a virt_mem block
if( !isrelative ) {
offset |= NOV_IMP_NONRELATIVE;
}
if( !isdata ) {
offset |= NOV_IMP_ISCODE;
}
imp = sym->p.import;
if( imp == DUMMY_IMPORT_PTR ) {
_ChkAlloc( imp, sizeof( nov_import ) );
sym->p.import = imp;
imp->contents = 1;
imp->num_relocs = offset;
} else if( imp->contents < MAX_IMP_INTERNAL ) {
if( imp->contents == 2 ) {
_ChkAlloc( new, ( MAX_IMP_INTERNAL - 2 ) * sizeof( unsigned_32 )
+ sizeof( nov_import ) );
memcpy( new, imp, sizeof( nov_import ) );
_LnkFree( imp );
imp = new;
sym->p.import = imp;
}
*(&imp->num_relocs + imp->contents) = offset;
imp->contents++;
} else if( imp->contents == MAX_IMP_INTERNAL ) { // set up virt.mem
vmem_ptr = AllocStg( IMP_VIRT_ALLOC_SIZE );
PutInfo( vmem_ptr, &imp->num_relocs,
MAX_IMP_INTERNAL * sizeof( unsigned_32 ) );
PutInfo( vmem_ptr + MAX_IMP_INTERNAL * sizeof( unsigned_32 ), &offset,
sizeof( unsigned_32 ) );
imp->contents++;
imp->num_relocs = imp->contents;
imp->addr[ 0 ] = vmem_ptr;
} else {
vblock = imp->num_relocs / IMP_NUM_VIRT;
voff = imp->num_relocs % IMP_NUM_VIRT;
if( voff == 0 ) {
if( vblock >= (imp->contents - MAX_IMP_INTERNAL) * MAX_IMP_VIRT ) {
_ChkAlloc( new, sizeof( nov_import ) - sizeof( unsigned_32 ) +
vblock * sizeof( unsigned_32 ) * 2 );
memcpy( new, imp, sizeof( nov_import ) - sizeof( unsigned_32 ) +
vblock * sizeof( unsigned_32 ) );
_LnkFree( imp );
imp = new;
imp->contents++;
sym->p.import = imp;
}
imp->addr[ vblock ] = AllocStg( IMP_VIRT_ALLOC_SIZE );
}
PutInfo( imp->addr[ vblock ] + voff * sizeof( unsigned_32 ), &offset,
sizeof( unsigned_32 ) );
imp->num_relocs++;
}
}
extern void FindExportedSyms( void )
/**********************************/
{
name_list * export;
symbol * sym;
debug_info * dinfo;
dinfo = CurrSect->dbg_info;
if( ( FmtData.u.nov.flags & DO_WATCOM_EXPORTS ) && ( dinfo != NULL ) ) {
export = FmtData.u.nov.exp.export;
while( export != NULL ) {
sym = SymOp( ST_FIND, export->name, export->len );
if( ( sym != NULL ) && !IS_SYM_IMPORTED( sym ) ) {
dinfo->global.curr += strlen( sym->name ) + sizeof( gblinfo );
}
export = export->next;
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?