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