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