cvpack.cpp

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C++ 代码 · 共 361 行

CPP
361
字号
/****************************************************************************
*
*                            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:  CVPACK mainline.
*
****************************************************************************/


#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <new.h>
#include "common.hpp"
#include "cverror.hpp"

#include "typemap.hpp"
#include "cvpack.hpp"
#include "retrieve.hpp"
#include "makeexe.hpp"
#include "subsect.hpp"
#include "packtype.hpp"
#include "cssymbol.hpp"
#include "symdis.hpp"

#include "banner.h"

static const char* CVpackHeader =
    banner1w( "CV4 Symbolic Debugging Information Compactor", BAN_VER_STR ) "\n" \
    banner2( "1995" ) "\n" \
    banner3 "\n" \
    banner3a;

static const char* CVpackUsage = "usage : cvpack [/nologo] <exefile>\n";

static const MAX_FILE_NAME = 256;
static char  fName[MAX_FILE_NAME];

// map table for type indices.
TypeIndexMap    TypeMap;

// Table of numeric leaf size except variable length string, because its
// length is not constant.
static const NumLeafSize[] = { 1, 2, 2, 4, 4, 4, 8, 10,
                               16, 8, 8, 6, 8, 16, 20, 32 };

//
// This function returns the length of a numeric leaf starting at buffer.
//
uint NumLeafLength( const char* buffer )
/**************************************/
{
    uint length = 0;
    uint index = * (unsigned_16 *) buffer;

    // skip the index of the numeric leaf.
    buffer += WORD;

    // length of the leaf index.
    length += WORD;

    //
    // If it is a variable length string, its length is specified by the
    // next 2 bytes.
    //
    if ( index == LF_VARSTRING ) {
        length += * (unsigned_16 *) buffer;
    } else if ( index >= LF_NUMERIC ) {
        length += NumLeafSize[index-LF_NUMERIC];
    }
    return length;
}

void ConvertFName( char* f )
/**************************/
{
    strcpy(fName,f);
    if ( strchr(f,'.') == NULL ) {
        strcat(fName,".exe");
    }
}
void outOfMemory() {
/******************/
    throw OutOfMemory();
}

void CVpack::DoExeCode()
/**********************/
{
    unsigned_32 length = _aRetriever.TellExeLength();
    if ( length ) {
        char* buffer = new char [length];
        if ( ! _aRetriever.ReadExeCode(buffer) ) {
            throw MiscError("error while reading executable code.");
        }
        _eMaker.DumpToExe(buffer,length);
        delete [] buffer;
    }
    _lfaBase = length;
}

uint CVpack::DoSstModule()
/************************/
{
    char*       buffer;
    unsigned_32 length;
    uint        module;

    for( module = 1;
          _aRetriever.ReadSubsection( buffer, length, sstModule, module );
          module++ ) {
        _newDir.Insert( sstModule, module, OFBase(), length );
        _eMaker.DumpToExe( buffer, length );
    }
    return module-1;
}

void CVpack::DumpSig()
/********************/
{
    _eMaker.DumpToExe( NB09, LONG_WORD );
}

uint CVpack::DoSrcModule( const uint module )
/*******************************************/
{
    unsigned_32 length;
    char*       buffer;

    if ( _aRetriever.ReadSubsection(buffer,length,sstSrcModule,module) ) {
        _newDir.Insert(sstSrcModule,module,OFBase(),length);
        _eMaker.DumpToExe(buffer,length);
        return ( * (unsigned_16 *) (buffer + WORD) );
    } else {
        return( 0 );
    }
}


uint CVpack::DoSegMap()
/*********************/
{
    uint        cSeg = 0;
    unsigned_32 length;
    char*       buffer;

    if ( _aRetriever.ReadSubsection(buffer,length,sstSegMap) ) {
        cSeg = * (unsigned_16 *) buffer;
        _newDir.Insert(sstSegMap,MODULE_INDEPENDENT,OFBase(),length);
        _eMaker.DumpToExe(buffer,length);
    } else {
        throw MiscError("no sstSegMap present.");
    }
    return( cSeg );
}

void CVpack::DoAlignSym( SstAlignSym*      alignSym,
                         const uint        module )
/**************************************************/
{
    _newDir.Insert(sstAlignSym,module,OFBase(),alignSym -> Length());
    alignSym -> Put(_eMaker);
}


void CVpack::DoGlobalSym( SstGlobalSym& globalSym, const uint cSeg )
/******************************************************************/
{
    unsigned_32 oldOffset = OFBase();
    globalSym.Put(_eMaker,cSeg);
    unsigned_32 length = OFBase() - oldOffset;
    _newDir.Insert(sstGlobalSym,MODULE_INDEPENDENT,oldOffset,length);
}

void CVpack::DoStaticSym( SstStaticSym& staticSym, const uint cSeg )
/******************************************************************/
{
    unsigned_32 oldOffset = OFBase();
    staticSym.Put(_eMaker,cSeg);
    unsigned_32 length = OFBase() - oldOffset;
    _newDir.Insert(sstStaticSym,MODULE_INDEPENDENT,oldOffset,length);
}

void CVpack::DoDirectory()
/************************/
{
    streampos dirOffset = OFBase();
    _newDir.Put(_eMaker);
    DumpSig();
    // compute lfoBase and dump it out.
    _eMaker.DumpToExe((unsigned_32)(_eMaker.TellPos()+LONG_WORD-_lfaBase));

    _eMaker.SeekTo(_lfaBase+LONG_WORD);
    _eMaker.DumpToExe((unsigned_32)dirOffset);
}

void CVpack::DoPublics( const uint segNum,
                        const uint moduleNum )
/********************************************/
{
    unsigned_32  length;
    uint         index;
    char*        buffer = NULL;
    char*        ptr = NULL;
    char*        end = NULL;
    SstGlobalPub globalPub;
    for ( uint module = 1; module <= moduleNum; module++ ) {
        if ( ! _aRetriever.ReadSubsection(buffer,length,sstPublicSym,module)) {
            continue;
        }
        ptr = buffer;
        end = &ptr[length];
        ptr += LONG_WORD; // skip 0x00000001 header.
        while ( ptr < end ) {
            index = * (unsigned_16 *)(ptr + WORD);
            if ( index == S_PUB16 ) {
                globalPub.Insert(CSPub16::Construct(ptr));
            } else if ( index == S_PUB32 ) {
                globalPub.Insert(CSPub32::Construct(ptr));
            }
            ptr += * (unsigned_16 *) ptr + WORD;
        }
    }
    unsigned_32 oldOffset = OFBase();
    globalPub.Put(_eMaker,segNum);
    unsigned_32 secLen = OFBase() - oldOffset;
    if ( secLen != 0 ) {
        _newDir.Insert(sstGlobalPub,MODULE_INDEPENDENT,oldOffset,secLen);
    }
}

void CVpack::DoLibraries()
/************************/
{
    unsigned_32 length;
    char*       buffer;
    if ( _aRetriever.ReadSubsection(buffer,length,sstLibraries) ) {
        _newDir.Insert(sstLibraries,MODULE_INDEPENDENT,OFBase(),length);
        _eMaker.DumpToExe(buffer,length);
    }
}

void CVpack::DoGlobalTypes( SstGlobalTypes& globalType )
/******************************************************/
{
    unsigned_32 oldOffset = OFBase();
    globalType.Put(_eMaker);
    unsigned_32 length = OFBase() - oldOffset;
    _newDir.Insert(sstGlobalTypes,MODULE_INDEPENDENT,oldOffset,length);
}

void CVpack::CreatePackExe()
/**************************/
{
    uint moduleNum = 0;
    // number of segment received code from a module.
    uint moduleSeg = 0;
    DoExeCode();
    DumpSig();
    // reserve for directory offset.
    _eMaker.Reserve(LONG_WORD);
    moduleNum = DoSstModule();

    SstGlobalTypes globalType;
    SstAlignSym*   alignSym;
    SstGlobalSym   globalSym;
    SstStaticSym   staticSym;
    bool           gottype;
    SymbolDistributor symDis(_aRetriever, globalSym, staticSym);
    for ( uint module = 1; ; module++ ) {
        if( _aRetriever.IsAtSubsection( sstSegMap ) ) break;
        gottype = globalType.LoadTypes(_aRetriever,module);
        moduleSeg = DoSrcModule(module);
        if( gottype ) {
            alignSym = new SstAlignSym(moduleSeg);
            if ( ! symDis.Distribute(module, *alignSym) ) {
                delete alignSym;
                break;
            }
            DoAlignSym(alignSym, module);
            delete alignSym;
        }
    }
    uint cSeg = DoSegMap();
    DoPublics(cSeg,moduleNum);
    DoGlobalSym(globalSym,cSeg);
    DoLibraries();
    DoGlobalTypes(globalType);
    DoStaticSym(staticSym,cSeg);
    DoDirectory();
    _eMaker.Close();
}


int main(int argc, char* argv[])
/******************************/
{
    char tmpFile[L_tmpnam];
    bool quiet;

    quiet = FALSE;
    set_new_handler(outOfMemory);
    try {
        if( argc != 2 ) {
            if( argc == 3 && stricmp( argv[1], "/nologo" ) == 0 ) {
                quiet = TRUE;
                argv[1] = argv[2];
            } else {
                cerr << CVpackUsage;
                return 1;
            }
        }
        if( !quiet ) {
            cout << CVpackHeader << endl;
        }
        ::ConvertFName(argv[1]);
        ifstream  fd(fName, ios::in | ios::binary);
        if ( !fd ) {
            throw FileError(fName);
        }
        tmpnam(tmpFile);
        CVpack packMaker(fd,tmpFile);
        packMaker.CreatePackExe();
        fd.close();
        if ( remove(fName) ) {
            throw MiscError(strerror(errno));
        }
        if ( rename(tmpFile,fName) ) {
            throw MiscError(strerror(errno));
        }
    }
    catch (CVpackError& CVerr) {
        CVerr.ErrorPrint();
        remove(tmpFile);
        exit(1);
    }
    return 0;
}

⌨️ 快捷键说明

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