support.c

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

C
1,334
字号
/****************************************************************************
*
*                            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:  Profiler support functions dealing with executable formats.
*
****************************************************************************/


#include <ctype.h>
#include <limits.h>
#include <string.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include "walloca.h"

#include "common.h"
#include "dip.h"
#include "mad.h"
#include "myassert.h"
#include "exedefs.h"
#include "machtype.h"
#include "sampinfo.h"
#include "ovltab.h"
#include "msg.h"


extern void *ProfAlloc(size_t size);
extern void ProfFree(void *ptr);
extern void *ProfRealloc(void *p,size_t new_size);
extern void *ProfCAlloc(size_t size);
extern void ErrorMsg(char *msg,... );

#define BYTE_SIZE       (8)      /* Number of bits in a byte */
#define MAX_INSTR_BYTES (8)
#define BUFF_SIZE       (512)

#if BUFF_SIZE > 0x7fff
#error buffer size is too large for strict POSIX compliance
#endif

static struct {
    uint_8              end_of_file : 1;        /* EOF was reached */
    uint_8              end_of_segment : 1;     /* EOS was reached */
    uint_8              is_32_bit : 1;          /* 386/486 application */
    uint_8              segment_split : 1;      /* cached seg isnt continuous */
} exeFlags;

static uint_16          cacheSegment;
static off_t            cacheExeOffset;
static uint_32          cacheLo;
static uint_32          cacheHi;
static bint             isHole = B_FALSE;
static address          currAddr;
static uint_16          segmentShift;
static file_handle      exeFH;
static off_t            exeImageOffset;
static image_info       *exeImage;
static EXE_TYPE         exeType;
static uint_16          exeAmount;
static uint_16          exeCurrent;
static off_t            exePosition;
static unsigned_16      nbytes = BUFF_SIZE;
static uint_16          numBytes = MAX_INSTR_BYTES;
static char             exeBuff[BUFF_SIZE];


STATIC void             AdvanceCurrentOffset( uint_32 );
STATIC uint_32          TransformExeOffset( uint_16, uint_32, uint_16 );
extern void             MapAddressToMap( addr_ptr *addr );

extern sio_data         *CurrSIOData;


static mad_disasm_data  *MDData;
static unsigned         MDSize;


void AsmSize( void )
{
    unsigned    new;

    new = MADDisasmDataSize();
    if( new > MDSize ) {
        MDData = ProfRealloc( MDData, new );
        //MAD: error check for realloc fail
        MDSize = new;
    }
}

void AsmFini( void )
{
    ProfFree( MDData );
}



extern file_handle ExeOpen( char * name )
/***************************************/
{
    file_handle     fh;

    fh = open( name, O_RDONLY | O_BINARY );
//    if( fh == -1 ) {
//        if( SourceRelease() != 0 ) {
//            fh = open( name, O_RDONLY | O_BINARY, S_IREAD );
//        }
//    }
    return( fh );
}



extern void ExeClose( file_handle fh )
/************************************/
{
    close( fh );
}



STATIC bint exeSeek( off_t posn )
/********************************/
{
    if(( posn >= exePosition )&&( posn < ( exePosition + exeAmount ))) {
        exeCurrent = posn - exePosition;
        return( B_TRUE );
    }
    if( lseek( exeFH, posn, SEEK_SET ) == posn ) {
        exePosition = posn;
        exeAmount = 0;
        exeCurrent = 0;
        exeFlags.end_of_file = B_FALSE;
        return( B_TRUE );
    }
    exeFlags.end_of_file = B_TRUE;
    return( B_FALSE );
}



STATIC void MapSetExeOffset( address a )
/**************************************/
{
    off_t   pos;

    pos = TransformExeOffset( a.mach.segment, a.mach.offset, a.sect_id );
    if( pos != -1 ) {
        exeSeek( pos );
    } else {
        exeFlags.end_of_file = B_TRUE;
    }
    currAddr = a;
    AdvanceCurrentOffset( 0 );
}

extern void SetExeOffset( address a )
/********************************/
{
    MapAddressToMap( &a.mach );
    MapSetExeOffset( a );
}


STATIC bint isWATCOM386Windows( file_handle fh )
/**********************************************/
{
    uint_32     MQ_offset;
    char        sig[2];

    if( lseek( fh, 0x38, SEEK_SET ) < 0 ) {
        return( B_FALSE );
    }
    if( read( fh, &MQ_offset, sizeof( MQ_offset ) ) != sizeof( MQ_offset ) ) {
        return( B_FALSE );
    }
    if( lseek( fh, MQ_offset, SEEK_SET ) < 0 ) {
        return( B_FALSE );
    }
    if( read( fh, &sig, sizeof( sig ) ) != sizeof( sig ) ) {
        return( B_FALSE );
    }
    if( sig[0] != 'M' || sig[1] != 'Q' ) {
        return( B_FALSE );
    }
    return( B_TRUE );
}



STATIC int exeHeader( file_handle fh )
/************************************/
{
    dos_exe_header      head;
    uint_32             pharlap_config;
    uint_32             pharlap_header;
    uint_32             os2_header;
    uint_16             format_level;
    uint_16             dummy_16;
    char                signature[2];
    char                copyrite[10];
    char                *sig;

    exeFlags.is_32_bit = B_FALSE;
    exeFlags.segment_split = B_FALSE;
    if( lseek( fh, 0, SEEK_SET ) != 0 ) {
        return( EXE_NOTYPE );
    }
    if( read( fh, &head, sizeof( head ) ) != sizeof( head ) ) {
        return( EXE_NOTYPE );
    }
    sig = (char *) &head.signature;
    switch( sig[0] ) {
    case 'M':
        if( sig[1] == 'P' || sig[1] == 'Q' ) {          /* MP & MQ */
            exeFlags.is_32_bit = B_TRUE;
            return( EXE_MP );
        }
        if( sig[1] == 'Z' ) {                           /* MZ */
            if( isWATCOM386Windows( fh ) ) {
                /* C/386 for Windows bound executable */
                exeFlags.is_32_bit = B_TRUE;
                return( EXE_MP_BOUND );
            }
            if( head.reloc_offset >= 0x40 ) {
                if( lseek( fh, sizeof( head ) + 32, SEEK_SET ) < 0 ) {
                    return( EXE_MZ );
                }
                if(read(fh,&os2_header,sizeof(os2_header))!=sizeof(os2_header)){
                    return( EXE_MZ );
                }
                if( lseek( fh, os2_header, SEEK_SET ) < 0 ) {
                    return( EXE_MZ );
                }
                if( read(fh,signature,sizeof(signature)) != sizeof(signature)) {
                    return( EXE_MZ );
                }
                if( signature[0] == 'N' && signature[1] == 'E' ) {  /* NE */
                    return( EXE_OS2 );
                }
                if( signature[0] == 'P' && signature[1] == 'E' ) {  /* PE */
                    exeFlags.is_32_bit = B_TRUE;
                    return( EXE_PE );
                }
                if( signature[0] == 'P' && signature[1] == 'L' ) {  /* PL */
                    exeFlags.is_32_bit = B_TRUE;
                    return( EXE_PL );
                }
                if( signature[0] == 'L' ) {
                    if( signature[1] == 'E' ) {         /* LE */
                        exeFlags.is_32_bit = B_TRUE;
                        return( EXE_OS2_FLAT );
                    }
                    if( signature[1] == 'X' ) {         /* LX */
                        exeFlags.is_32_bit = B_TRUE;
                        return( EXE_OS2_LX );
                    }
                }
                return( EXE_MZ );
            }
            /* check for bound PharLap Extended 386 executable */
            pharlap_config = head.hdr_size * 16;
            if( lseek( fh, pharlap_config, SEEK_SET ) < 0 ) {
                return( EXE_MZ );
            }
            if( read( fh, copyrite, sizeof(copyrite) ) != sizeof(copyrite)){
                return( EXE_MZ );
            }
            if( memcmp( copyrite, "Copyright", 9 ) != 0 ) {
                return( EXE_MZ );
            }
            if( lseek( fh, pharlap_config + 0x32, SEEK_SET ) < 0 ) {
                return( EXE_MZ );
            }
            if( read(fh,signature,sizeof(signature)) != sizeof(signature)) {
                return( EXE_MZ );
            }
            if( signature[0] != 'C' || signature[1] != '5' ) {
                return( EXE_MZ );
            }
            if( lseek( fh, pharlap_config + 0x32 + 6, SEEK_SET ) < 0 ) {
                return( EXE_MZ );
            }
            if( read(fh,signature,sizeof(signature)) != sizeof(signature)) {
                return( EXE_MZ );
            }
            if( signature[0] != 'P' || signature[1] != '6' ) {
                return( EXE_MZ );
            }
            pharlap_header = head.file_size * 512L;
            if( head.mod_size != 0 ) {
                pharlap_header += head.mod_size;
                pharlap_header -= 512;
            }
            if( lseek( fh, pharlap_header, SEEK_SET ) < 0 ) {
                return( EXE_MZ );
            }
            if( read(fh,signature,sizeof(signature)) != sizeof(signature)) {
                return( EXE_MZ );
            }
            if( signature[0] != 'P' || signature[1] != '3' ) {
                return( EXE_MZ );
            }
            pharlap_header += offsetof( extended_header, format_level );
            if( lseek( fh, pharlap_header, SEEK_SET ) < 0 ) {
                return( EXE_MZ );
            }
            read( fh, &format_level, sizeof( format_level ) );
            if( format_level != 1 ) {
                return( EXE_MZ );
            }
            exeFlags.is_32_bit = B_TRUE;
            return( EXE_P3_BOUND );
        }
        break;
    case 'P':
        if( sig[1] == '3' ) {                           /* P3 */
            lseek( fh, offsetof( extended_header, format_level ), SEEK_SET );
            read( fh, &format_level, sizeof( format_level ) );
            if( format_level != 1 ) {
                return( EXE_UNKNOWN );
            }
            exeFlags.is_32_bit = B_TRUE;
            return( EXE_P3 );
        }
        if( sig[1] == '2' ) {                           /* P2 */
            return( EXE_UNKNOWN );
            /* return( EXE_P2 );        (not supported 03-may-90 AFS) */
        }
        break;
    case 'N':
        if( sig[1] == 'e' ) {                           /* Ne */
            exeFlags.is_32_bit = B_TRUE;
            return( EXE_NW );
        }
        break;
    case '\0':
        if( sig[1] == '\0' ) {
            lseek( fh, sizeof( lmf_record ) + offsetof( lmf_header, version ),
                   SEEK_SET );
            dummy_16 = 0;
            read( fh, &dummy_16, sizeof( dummy_16 ) );
            if( dummy_16 >= QNX_VERSION ) {
                exeFlags.segment_split = B_TRUE;
                lseek( fh, sizeof( lmf_record ) + offsetof( lmf_header, cflags ),
                       SEEK_SET );
                read( fh, &dummy_16, sizeof( dummy_16 ) );
                if( dummy_16 & _TCF_32BIT ) {
                    exeFlags.is_32_bit = B_TRUE;
                    if( dummy_16 & _TCF_FLAT ) {
                        return( EXE_QNX_386_FLAT );
                    }
                    return( EXE_QNX_386 );
                }
                return( EXE_QNX );
            }
        }
        break;
    case ELFMAG0:
        if( memcmp( sig, ELF_SIGNATURE, ELF_SIGNATURE_LEN ) == 0 ) {
            exeFlags.is_32_bit = B_TRUE;
            return( EXE_ELF );
        }
        break;

    }
    return( EXE_UNKNOWN );
}



extern void SetExeImage( image_info *image )
/******************************************/
{
    exeImage = image;
}



extern bint SetExeFile( file_handle fh, bint overlay )
/****************************************************/
{
    dos_exe_header      head;
    off_t               new_header;
    off_t               header_base;
    off_t               seek_off;
    uint_16             dummy_16;
    uint_32             dummy_32;

    exeFH = fh;
    exeType = exeHeader( exeFH );
    if( exeType != EXE_MZ && overlay ) {        /* 16-may-90 AFS */
        exeType = EXE_OVL;
        exeFlags.is_32_bit = B_FALSE;
    }
    header_base = 0;
    switch( exeType ) {
    case EXE_MZ:
        /* exeImageOffset is in 16-byte paragraphs  */
        lseek( exeFH, offsetof( dos_exe_header, hdr_size ), SEEK_SET );
        read( exeFH, &dummy_16, sizeof( dummy_16 ) );
        exeImageOffset = dummy_16;
        break;
    case EXE_MP_BOUND:
        lseek( exeFH, 0x38, SEEK_SET );
        read( exeFH, &dummy_32, sizeof( dummy_32 ) );
        header_base = dummy_32;
        /* fall through to MP */
    case EXE_MP:
        /* exeImageOffset is in bytes */
        seek_off = header_base + offsetof( simple_header, hdr_size );
        lseek( exeFH, seek_off, SEEK_SET );
        read( exeFH, &dummy_16, sizeof( dummy_16 ) );
        exeImageOffset = dummy_16 * 16L;
        exeImageOffset += header_base;
        break;
    case EXE_P3_BOUND:
        lseek( exeFH, 0, SEEK_SET );
        read( exeFH, &head, sizeof( head ) );
        header_base = head.file_size * 512L;
        if( head.mod_size != 0 ) {

⌨️ 快捷键说明

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