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