loadfile.c

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

C
1,187
字号
/****************************************************************************
*
*                            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:  Utilities for processing creation of load files.
*
****************************************************************************/


#include <string.h>
#include <stdlib.h>
#include "walloca.h"
#include "linkstd.h"
#if !defined( __LINUX__ ) || defined(__WATCOMC__)
#include <process.h>
#endif
#include "ring.h"
#include "pcobj.h"
#include "newmem.h"
#include "msg.h"
#include "alloc.h"
#include "specials.h"
#include "wlnkmsg.h"
#include "virtmem.h"
#include "fileio.h"
#include "mapio.h"
#include "spillio.h"
#include "omfreloc.h"
#include "objcalc.h"
#include "dbgall.h"
#include "loadpe.h"
#include "loados2.h"
#include "loaddos.h"
#include "pharlap.h"
#include "loadnov.h"
#include "loadqnx.h"
#include "loadelf.h"
#include "loadraw.h"
#include "loadfile.h"
#include "objstrip.h"
#include "impexp.h"
#include "objnode.h"
#include "strtab.h"
#include "permdata.h"

seg_leader *    StackSegPtr;
startinfo       StartInfo;

#define IMPLIB_BUFSIZE 4096

typedef struct {
    f_handle    handle;
    char *      fname;
    char *      buffer;
    unsigned    bufsize;
    char *      dllname;
    size_t      dlllen;
    unsigned    didone : 1;
} implibinfo;

static implibinfo       ImpLib;

static void OpenOutFiles( void );
static void CloseOutFiles( void );
static void SetupImpLib( void );
static void DoCVPack( void );
static void FlushImpBuffer( void );
static void ExecWlib( void );
static void WriteBuffer( char *info, unsigned long len, outfilelist *outfile,
                         void * (*rtn)(void *, const void *, unsigned) );
static void BufImpWrite( char *buffer, int len );
static void FlushBuffFile( outfilelist *outfile );

extern void ResetLoadFile( void )
/*******************************/
{
    ClearStartAddr();
}

extern void CleanLoadFile( void )
/*******************************/
{
}

extern void InitLoadFile( void )
/******************************/
/* open the file, and write out header info */
{
    DEBUG(( DBG_OLD, "InitLoadFile()" ));
    LnkMsg( INF+MSG_CREATE_EXE, "f" );
}

extern void FiniLoadFile( void )
/******************************/
/* terminate writing of load file */
{
    CurrSect = Root;
    FreeSavedRelocs();
    OpenOutFiles();
    SetupImpLib();
    if ( FmtData.output_raw ) {   // These must come first because they
        BinOutput();              //   apply to all formats and override
    }                             //   native output
    else if ( FmtData.output_hex ) {
        HexOutput();
    }
    else if( FmtData.type & MK_REAL_MODE ) {
        FiniDOSLoadFile();
#ifdef _OS2
    } else if( IS_PPC_OS2 ) {
        // development temporarly on hold:
        // FiniELFLoadFile();
    } else if( FmtData.type & MK_OS2_FLAT ) {
        FiniOS2FlatLoadFile();
    } else if( FmtData.type & MK_PE ) {
        FiniPELoadFile();
    } else if( FmtData.type & MK_OS2_16BIT ) {
        FiniOS2LoadFile();
#endif
#ifdef _PHARLAP
    } else if( FmtData.type & MK_PHAR_LAP ) {
        FiniPharLapLoadFile();
#endif
#ifdef _NOVELL
    } else if( FmtData.type & MK_NOVELL ) {
        FiniNovellLoadFile();
#endif
#ifdef _QNXLOAD
    } else if( FmtData.type & MK_QNX ) {
        FiniQNXLoadFile();
#endif
#ifdef _ELF
    } else if( FmtData.type & MK_ELF ) {
        FiniELFLoadFile();
#endif
    }
    MapSizes();
    CloseOutFiles();
    DoCVPack();
}

#if defined( __LINUX__ ) && !defined(__WATCOMC__)
static void DoCVPack( void ) {}
#else
#if defined( __LINUX__ )
#define CVPACK_EXE "cvpack"
#else
#define CVPACK_EXE "cvpack.exe"
#endif
static void DoCVPack( void )
/**************************/
{
    int         retval;
    char *      name;

    if( LinkFlags & CVPACK_FLAG && !(LinkState & LINK_ERROR) ) {
        if( SymFileName != NULL ) {
            name = SymFileName;
        } else {
            name = Root->outfile->fname;
        }
        retval = spawnlp( P_WAIT, CVPACK_EXE, CVPACK_EXE, "/nologo",
                          name, NULL );
        if( retval == -1 ) {
            PrintIOError( ERR+MSG_CANT_EXECUTE, "12", CVPACK_EXE );
        }
    }
}
#endif

static seg_leader * FindStack( class_entry *class )
/*************************************************/
{
    while( class != NULL ) {
        if( class->flags & CLASS_STACK ) {
            return RingFirst( class->segs );
        }
        class = class->next_class;
    }
    return( NULL );
}

static seg_leader *StackSegment( void )
/*************************************/
/* Find stack segment. */
{
    seg_leader  *seg;

    seg = FindStack( Root->classlist );
    if( seg == NULL ) {
        if( FmtData.type & MK_OVERLAYS ) {
            seg = FindStack( NonSect->classlist );
        }
    }
    return( seg );
}

extern void GetStkAddr( void )
/****************************/
/* Find the address of the stack */
{
    if( !(FmtData.type & MK_NOVELL) && !FmtData.dll ) {
        if( StackSegPtr != NULL ) {
            StackAddr.seg = StackSegPtr->seg_addr.seg;
            StackAddr.off = StackSegPtr->seg_addr.off + StackSegPtr->size;
        } else {
#ifdef _OS2
            if( FmtData.type & MK_WINDOWS && LinkFlags & STK_SIZE_FLAG ) {
                PhoneyStack();
            } else
#endif
            if( !(FmtData.type & (MK_COM|MK_PE|MK_QNX|MK_ELF)) ) {
                LnkMsg( WRN+MSG_STACK_NOT_FOUND, NULL );
                StackAddr.seg = 0;
                StackAddr.off = 0;
            }
        }
    }
}

static class_entry * LocateBSSClass( void )
/*****************************************/
{
    class_entry *currclass;

    currclass = ((Root->areas == NULL) ? Root : NonSect)->classlist;
    for(;;) {
        if( currclass == NULL ) return( NULL );
        if( stricmp( currclass->name, BSSClassName ) == 0 ) return( currclass );
        currclass = currclass->next_class;
    }
}

static void DefABSSSym( char *name )
/**********************************/
{
   symbol          *sym;

    sym = RefISymbol( name );
    if( !(sym->info & SYM_DEFINED) || sym->info & SYM_LINK_GEN ) {
        sym->info |= SYM_DEFINED | SYM_LINK_GEN;
        if( FmtData.type & MK_OVERLAYS ) {
            sym->u.d.ovlstate |= OVL_NO_VECTOR | OVL_FORCE;
        }
        sym->addr.seg = UNDEFINED;
        sym->addr.off = 0;
    }
 }

extern void DefBSSSyms( void )
/****************************/
{
    DefABSSSym( BSSStartSym );
    DefABSSSym( BSS_StartSym );
    DefABSSSym( BSSEndSym );
    DefABSSSym( BSS_EndSym );
}

static bool CompSymPtr( void *sym, void *chk )
/********************************************/
{
    return chk == sym;
}

static void CheckBSSInStart( symbol * sym, char * name )
/******************************************************/
/* It's OK to define _edata if:
        1) the DOSSEG flag is not set
                or
        2) the definition occurs in the module containing the
            start addresses */
{
    symbol *    chk;

    chk = NULL;
    if( StartInfo.mod != NULL ) {
        chk = Ring2Lookup( StartInfo.mod->publist, CompSymPtr, sym );
    }
    if( chk == NULL ) {
        LnkMsg( ERR+MSG_RESERVED_SYM_DEFINED, "s", name );
    }
}

static void DefBSSStartSize( char * name, class_entry * class )
/*************************************************************/
/* set the value of an start symbol, and see if it has been defined */
{
    symbol *    sym;
    seg_leader *seg;

    sym = FindISymbol( name );
    if( sym->addr.seg == UNDEFINED ) {
        /* if the symbol was defined internally */
        seg = (seg_leader *) RingFirst( class->segs );
        sym->p.seg = (segdata *) RingFirst( seg->pieces );
        sym->addr = seg->seg_addr;
        ConvertToFrame( &sym->addr, seg->group->grp_addr.seg );
    } else if( LinkState & DOSSEG_FLAG ) {
        CheckBSSInStart( sym, name );
    }
}

static void DefBSSEndSize( char * name, class_entry * class )
/***********************************************************/
/* set the value of an end symbol, and see if it has been defined */
{
    symbol *    sym;
    seg_leader *seg;

    sym = FindISymbol( name );
    if( sym->addr.seg == UNDEFINED ) {
        /* if the symbol was defined internally */
        /* find last segment in BSS class */
        seg = (seg_leader *) RingLast( class->segs );
        /* set end of BSS class */
        sym->p.seg = (segdata *) RingLast( seg->pieces );
        sym->addr.seg = seg->seg_addr.seg;
        sym->addr.off = seg->seg_addr.off + seg->size;
        ConvertToFrame( &sym->addr, seg->group->grp_addr.seg );
    } else if( LinkState & DOSSEG_FLAG ) {
        CheckBSSInStart( sym, name );
    }
}

extern void GetBSSSize( void )
/****************************/
/* Find size of BSS segment, and set the special symbols */
{
    class_entry *class;

    class = LocateBSSClass();
    if( class != NULL ) {
        /* set start of BSS class */
        DefBSSStartSize( BSSStartSym, class );
        DefBSSStartSize( BSS_StartSym, class );
        DefBSSEndSize( BSSEndSym, class );
        DefBSSEndSize( BSS_EndSym, class );
    }
}

extern void SetStkSize( void )
/****************************/
{
    StackSegPtr = StackSegment();
    if( FmtData.dll ) {
        StackSize = 0;  // DLLs don't have their own stack
    } else if( StackSize < 0x200 ) {
        StackSize = 0x200;
    }
    if( StackSegPtr != NULL ) {
        if( FmtData.dll ) {
            StackSegPtr->size = StackSize;
        } else if( LinkFlags & STK_SIZE_FLAG ) {
            if( !(FmtData.type & MK_NOVELL) ) {
                StackSegPtr->size = StackSize;
            }
        } else if( StackSegPtr->size >= 0x200 ) {
            StackSize = StackSegPtr->size;
        } else {
            StackSegPtr->size = StackSize;
        }
    }
}

extern void ClearStartAddr( void )
/********************************/
{
    memset( &StartInfo, 0, sizeof(startinfo) );
}

extern void SetStartSym( char *name )
/***********************************/
{
    size_t      namelen;

⌨️ 快捷键说明

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