loadnov.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 733 行 · 第 1/2 页

C
733
字号
/****************************************************************************
*
*                            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:  routines for creating novell netware load files
*
****************************************************************************/


#include <string.h>
#include <time.h>
#include "linkstd.h"
#include "alloc.h"
#include "msg.h"
#include "exenov.h"
#include "dbginfo.h"
#include "reloc.h"
#include "wlnkmsg.h"
#include "virtmem.h"
#include "fileio.h"
#include "dbgall.h"
#include "impexp.h"
#include "loadfile.h"
#include "loadnov.h"

static unsigned_32 WriteNovData( unsigned_32, fixed_header * );
static unsigned_32 WriteNovImage( unsigned_32, bool );

#define DUMMY_THREAD_NAME " LONG"

static unsigned_32  DbgInfoCount;
static unsigned_32  DbgInfoLen;
static virt_mem     NovDbgInfo;
static virt_mem     CurrDbgLoc;

extern void ResetLoadNov( void )
/******************************/
{
    DbgInfoCount = 0;
    DbgInfoLen = 0;
}

static unsigned_32 WriteNovRelocs( fixed_header *header )
/*******************************************************/
// write the relocations.
{
    DumpRelocList( Root->reloclist );
    header->numberOfRelocationFixups = Root->relocs;
    return( (unsigned_32)Root->relocs * sizeof( nov_reloc_item ) );
}

static unsigned_32 WriteNovImports( fixed_header *header )
/********************************************************/
{
    nov_import *    import;
    unsigned_32     count;
    char *          name;
    unsigned_8      namelen;
    unsigned_32     wrote;
    unsigned_32     refs;
    virt_mem *      vmem_array;
    symbol *        sym;

    wrote = count = 0;
    for( sym = HeadSym; sym != NULL; sym = sym->link ) {
        if( !( IS_SYM_IMPORTED( sym ) ) )
            continue;
        /* so SymFini doesn't try to free it */
        if( sym->p.import == DUMMY_IMPORT_PTR )
            sym->p.import = NULL;
        import = sym->p.import;

        if( import != NULL ) {
            count++;
            name = sym->name;
            namelen = strlen( name );

            /*
            // netware prefix support
            */
            if( sym->prefix ) {
                namelen += ( strlen( sym->prefix ) + 1);
                WriteLoad( &namelen, sizeof( unsigned_8 ) );
                WriteLoad( sym->prefix, strlen( sym->prefix ) );
                WriteLoad( "@", 1 );
                WriteLoad( name, strlen( sym->name ) );
            } else {
                WriteLoad( &namelen, sizeof( unsigned_8 ) );
                WriteLoad( name, namelen );
            }

            wrote += namelen + sizeof( unsigned_8 ) + sizeof( unsigned_32 );
            if( import->contents <= MAX_IMP_INTERNAL ) {
                refs = import->contents;
                WriteLoad( &refs, sizeof( unsigned_32 ) );
                refs *= sizeof( unsigned_32 );
                WriteLoad( &import->num_relocs, refs );
            } else {        // imports are in virtual memory.
                refs = import->num_relocs;
                WriteLoad( &refs, sizeof( unsigned_32 ) );
                vmem_array = import->addr;
                while( refs > IMP_NUM_VIRT ) {
                    WriteInfo( *vmem_array, IMP_VIRT_ALLOC_SIZE );
                    vmem_array++;
                    refs -= IMP_NUM_VIRT;
                }
                WriteInfo( *vmem_array, refs * sizeof( unsigned_32 ) );
                refs = import->num_relocs * sizeof( unsigned_32 );
            }
            wrote += refs;
        }
    }
    header->numberOfExternalReferences = count;
    return( wrote );
}

static unsigned_32 WriteNovExports( fixed_header *header )
/********************************************************/
{
    name_list * export;
    symbol *    sym;
    unsigned_32 count;
    unsigned_32 wrote;
    unsigned_32 off;
    unsigned_8  len;

    count = wrote = 0;
    export = FmtData.u.nov.exp.export;
    while( export != NULL ) {

        len = export->len;
        sym = SymOp( ST_FIND, export->name, len );
        if( ( sym == NULL ) || !( sym->info & SYM_DEFINED ) ) {
            LnkMsg( WRN+MSG_EXP_SYM_NOT_FOUND, "s", export->name );
        } else if( !IS_SYM_IMPORTED(sym) ) {

            /*
            //    netware prefix support
            */
            if( sym->prefix ) {

                char        full_name[255+1];

                strcpy(full_name, sym->prefix);
                strcat(full_name, "@");
                strcat(full_name, sym->name);
                AddImpLibEntry( sym->name, full_name, NOT_IMP_BY_ORDINAL );

                len = strlen( full_name );
                
                WriteLoad( &len, sizeof( unsigned_8 ) );
                WriteLoad( full_name, len );
            } else {
                AddImpLibEntry( sym->name, sym->name, NOT_IMP_BY_ORDINAL );
                WriteLoad( &len, sizeof( unsigned_8 ) );
                WriteLoad( export->name, len );
            }

            count++;
            off = sym->addr.off;
            if( sym->addr.seg == CODE_SEGMENT ) {
                off |= NOV_EXP_ISCODE;
            }
            WriteLoad( &off, sizeof( unsigned_32 ) );
            wrote += sizeof( unsigned_32 ) + sizeof( unsigned_8 ) + len;
        }
        export = export->next;
    }
    header->numberOfPublics = count;
    return( wrote );
}

static unsigned_32 WriteNovModules( fixed_header *header )
/********************************************************/
{
    name_list * module;
    unsigned_32 count;
    unsigned_32 wrote;

    count = wrote = 0;
    module = FmtData.u.nov.exp.module;
    while( module != NULL ) {
        count++;
        WriteLoad( &module->len, sizeof( unsigned_8 ) );
        WriteLoad( module->name, module->len );
        wrote += sizeof( unsigned_8 ) + module->len;
        module = module->next;
    }
    header->numberOfModuleDependencies = count;
    return( wrote );
}

extern void NovDBIAddGlobal( void * _sym )
/****************************************/
{
    symbol *sym = _sym;
        
    if( !IS_SYM_A_REF(sym)
            && !IS_SYM_ALIAS(sym)
            && ( sym->p.seg != NULL )
            && !( sym->info & SYM_DEAD )
            && !sym->p.seg->isabs
            && !( sym->info & SYM_STATIC )
            && !( FmtData.u.nov.flags & DO_NOV_EXPORTS ) ) {
        DbgInfoLen += strlen( sym->name ) + sizeof( nov_dbg_info );
    }
}

extern void NovDBIAddrStart( void )
/*********************************/
{
    if( DbgInfoLen != 0 ) {
        NovDbgInfo = AllocStg( DbgInfoLen );
        CurrDbgLoc = NovDbgInfo;
    }
}

extern void NovDBIGenGlobal( symbol *sym )
/****************************************/
{
    nov_dbg_info    info;

    if( ( DbgInfoLen != 0 )
        && ( !( FmtData.u.nov.flags & DO_NOV_REF_ONLY )
        || ( sym->info & SYM_REFERENCED ) ) ) {
        DbgInfoCount++;
        if( sym->addr.seg == DATA_SEGMENT ) {
            info.type = DBG_DATA;
        } else {
            info.type = DBG_CODE;
        }
        info.offset = sym->addr.off;
        info.namelen = strlen( sym->name );
        PutInfo( CurrDbgLoc, &info, sizeof( nov_dbg_info ) );
        CurrDbgLoc += sizeof( nov_dbg_info );
        PutInfo( CurrDbgLoc, sym->name, info.namelen );
        CurrDbgLoc += info.namelen;
    }
}

static unsigned_32 WriteNovDBI( fixed_header *header )
/****************************************************/
{
    name_list *     export;
    symbol *        sym;
    unsigned_32     count;
    unsigned_32     wrote;
    unsigned_8      len;
    nov_dbg_info    info;

    if( DbgInfoLen > 0 ) {
        WriteInfo( NovDbgInfo, CurrDbgLoc - NovDbgInfo );
        header->numberOfDebugRecords = DbgInfoCount;
        return( CurrDbgLoc - NovDbgInfo );
    } else if( FmtData.u.nov.flags & DO_NOV_EXPORTS ) {
        count = wrote = 0;
        export = FmtData.u.nov.exp.export;
        while( export != NULL ) {
            len = export->len;
            sym = SymOp( ST_FIND, export->name, len );
            if( ( sym != NULL ) && !IS_SYM_IMPORTED( sym ) ) {
                count++;
                if( sym->addr.seg == DATA_SEGMENT ) {
                    info.type = DBG_DATA;
                } else {
                    info.type = DBG_CODE;
                }
                info.offset = sym->addr.off;
                info.namelen = len;
                WriteLoad( &info, sizeof( nov_dbg_info ) );
                WriteLoad( export->name, len );
                wrote += sizeof( nov_dbg_info ) + len;
            }
            export = export->next;
        }
        header->numberOfDebugRecords = count;
        return( wrote );
    }
    header->numberOfDebugRecords = 0;
    return( 0 );
}

static unsigned_32 WriteMessages( extended_nlm_header * header )
/**************************************************************/
/* write out the messages file */
{
    f_handle    handle;
    char *      name;
    unsigned_32 buf[2];

    name = FmtData.u.nov.messages;
    header->messageFileLength = 0;
    if( name != NULL ) {
        handle = QOpenR( name );
        QRead( handle, TokBuff, MSG_FILE_SIGNATURE_LENGTH, name );
        if( memcmp( TokBuff, MSG_FILE_SIGNATURE, MSG_FILE_SIGNATURE_LENGTH ) != 0 ) {
            LnkMsg( WRN+MSG_INV_MESSAGE_FILE, "s", name );
            QClose( handle, name );
        } else {
            QSeek( handle, LANGUAGE_ID_OFFSET, name );
            QRead( handle, buf, 2*sizeof( unsigned_32 ), name );
            header->languageID = buf[0];
            header->messageCount = buf[1];
            QSeek( handle, 0, name );
            header->messageFileLength = CopyToLoad( handle, name );
        }
    }
    return( header->messageFileLength );
}

static unsigned_32 WriteSharedNLM( extended_nlm_header * header,
                                                unsigned_32 file_size )
/*********************************************************************/
{
    f_handle            handle;
    char *              name;
    fixed_header *      sharehdr;

    name = FmtData.u.nov.sharednlm;
    if( name != NULL ) {
        handle = QOpenR( name );
        QRead( handle, TokBuff, sizeof( fixed_header ), name );
        if( memcmp( TokBuff, NLM_SIGNATURE, sizeof( NLM_SIGNATURE ) - 1 ) != 0 ) {
            LnkMsg( WRN+MSG_INV_SHARED_NLM_FILE, "s", name );
            QClose( handle, name );
        } else {
            sharehdr = (fixed_header *) TokBuff;
            header->sharedCodeOffset = sharehdr->codeImageOffset + file_size;
            header->sharedCodeLength = sharehdr->codeImageSize;
            header->sharedDataOffset = sharehdr->dataImageOffset + file_size;
            header->sharedDataLength = sharehdr->dataImageSize;
            header->sharedRelocationFixupOffset
                        = sharehdr->relocationFixupOffset + file_size;
            header->sharedRelocationFixupCount
                        = sharehdr->numberOfRelocationFixups;
            header->sharedExternalReferenceOffset
                        = sharehdr->externalReferencesOffset + file_size;
            header->sharedExternalReferenceCount
                        = sharehdr->numberOfExternalReferences;
            header->sharedPublicsOffset = sharehdr->publicsOffset + file_size;
            header->sharedPublicsCount = sharehdr->numberOfPublics;
            header->sharedDebugRecordOffset
                        = sharehdr->debugInfoOffset + file_size;
            header->sharedDebugRecordCount = sharehdr->numberOfDebugRecords;
            header->sharedInitializationOffset = sharehdr->codeStartOffset;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?