can2ms2.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 719 行 · 第 1/2 页
C
719 行
/****************************************************************************
*
* 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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include <string.h>
#include "womp.h"
#include "msdbg.h"
#include "canaddr.h"
#include "cansymb.h"
#include "cantype.h"
#include "namemgr.h"
#include "genutil.h"
#include "memutil.h"
#include "myassert.h"
#include "canmisc.h"
#include "pcobj.h"
#include "fixup.h"
#include "objprs.h"
#include "objrec.h"
/*
We keep a pointer to the obj_rec for our segdef so we can set seg_length
and set the ledata records appropriately.
*/
STATIC obj_rec *mySegdef;
/*
blockIndent is used to represent the current block "indentation". Each
SYMB_BLOCK increments it, and each SYMB_BLOCK_END decrements it. If
blockIndent == 0 then we are outside all procedures. == 1 means we are in
a procedure, but not inside any internal blocks of the procedure.
*/
STATIC uint blockIndent;
/*
Only procedure-style blocks have types which indicate them to be 386 or
not. We save that info here for inner blocks.
block386 == MS_SYM_386_FLAG (0x80) if in a 386 block.
block386 == 0 otherwise
For Metaware it doesn't matter if block386 is set or not, we'll write
everything using Metaware 32-bit extensions. newRec() ensures the high
bit is not set on Metaware records.
*/
STATIC uint_8 block386;
/*
A canaddr fixup for SYMB_CHANGE_SEG can be any arbitrary style of
fixup. Microsoft debugging information only supports BASE fixups attached
to their equivalent of SYMB_CHANGE_SEG. For POINTER (and POINTER386) fixups
we must break the fixup apart, and output an OFFSET (or OFFSET386) fixup
for every single offset field affected.
codeOffset is set first in symbChangeSeg to the data from the canaddr for
the segment change. Then it is adjusted within each block we enter and
leave.
offsetFixup is a copy of the split up fixup from the SYMB_CHANGE_SEG.
if offsetFixup is NULL then we don't apply any fixup to offsets in blocks
and procedures.
*/
STATIC uint_32 codeOffset;
STATIC fixup *offsetFixup;
/*
Microsoft can't do anything with parm locations or return value locations,
so we must skip them.
*/
STATIC int skipParms;
STATIC int skipALocal;
/*
myRecBuf is a 256 byte buffer for building Microsoft symbolic records.
myRecPtr points into myRecBuf at the next write position.
waitFixups are fixups attached to data in myRecBuf with their loc_offsets
set to the offset from beginning of myRecBuf.
wait386Fixups indicates there are 386-style fixups waiting
*/
#define MAX_REC 257
STATIC uint_8 *myRecBuf;
STATIC uint_8 *myRecPtr;
STATIC fixup *waitFixups;
STATIC int wait386Fixups;
/*
ledataBuf is a 1024 byte buffer for building LEDATAs.
ledataOffset is the offset of the next byte to be added to ledataBuf.
doneFixups are fixups attached to data in ledataBuf with their loc_offsets
set to the offset from beginning of ledataBuf.
done386Fixups there are 386-style fixups done
writeLEOffset is the offset field for the next LEDATA. i.e., it is the
current size of the $$SYMBOLS segment.
*/
#define MAX_LEDATA 1024
STATIC uint_8 *ledataBuf;
STATIC size_t ledataOffset;
STATIC fixup *doneFixups;
STATIC int done386Fixups;
STATIC uint_16 writeLEOffset;
STATIC void setupObjIO( void ) {
myRecBuf = MemAlloc( MAX_REC );
ledataBuf = MemAlloc( MAX_LEDATA );
ledataOffset = 0;
writeLEOffset = 0;
doneFixups = NULL;
waitFixups = NULL;
offsetFixup = NULL;
mySegdef = Can2MsSegdef( MS_DDSYMBOLS MS_DEBSYM,
MS_DDSYMBOLS_LEN + MS_DEBSYM_LEN );
}
STATIC void flushLedata( void ) {
uint_16 length;
obj_rec *ledata;
obj_rec *fixups;
if( ledataOffset > 0 ) {
ledata = Can2MsRec( CMD_LEDATA );
ledata->d.ledata.idx = mySegdef->d.segdef.idx;
ledata->d.ledata.offset = writeLEOffset;
length = ledataOffset;
ObjAllocData( ledata, length );
ObjPut( ledata, ledataBuf, length );
ObjTruncRec( ledata );
ObjRSeek( ledata, 0 ); /* so filters can find the data */
/* update state */
ledataOffset = 0;
writeLEOffset += length;
if( doneFixups != NULL ) {
fixups = Can2MsRec( CMD_FIXUP );
fixups->d.fixup.data_rec = ledata;
fixups->d.fixup.fixup = doneFixups;
fixups->is_32 = done386Fixups;
doneFixups = NULL;
done386Fixups = 0;
}
}
}
STATIC void finishObjIO( void ) {
flushLedata();
/**/myassert( waitFixups == NULL );
/**/myassert( doneFixups == NULL );
mySegdef->d.segdef.seg_length = writeLEOffset;
MemFree( ledataBuf );
MemFree( myRecBuf );
if( offsetFixup != NULL ) {
FixKill( offsetFixup );
}
}
/*
newRec, put8, put16, putName, putAddr, and endRec are used
to create, build, and finish a Microsoft symbolic record.
*/
STATIC void newRec( uint_8 typ ) {
uint_8 *p;
p = myRecBuf;
*p++ = 0; /* len - will be corrected in endRec */
if( Can2MSMetaware ) {
*p++ = typ & ~0x80;
} else {
*p++ = typ; /* typ */
}
myRecPtr = p;
}
STATIC void put8( uint_8 byte ) {
*myRecPtr++ = byte;
/**/myassert( myRecPtr - myRecBuf < MAX_REC );
}
STATIC void put16( uint_16 word ) {
WriteU16( myRecPtr, word );
myRecPtr += 2;
/**/myassert( myRecPtr - myRecBuf < MAX_REC );
}
STATIC void put32( uint_32 dword ) {
WriteU32( myRecPtr, dword );
myRecPtr += 4;
/**/myassert( myRecPtr - myRecBuf < MAX_REC );
}
STATIC void putEither( uint_32 dword ) {
if( block386 || Can2MSMetaware ) {
put32( dword );
} else {
put16( dword );
}
}
STATIC void putMetaware( uint_32 dword ) {
if( Can2MSMetaware ) {
put32( dword );
} else {
put16( dword );
}
}
STATIC void putName( name_handle hdl ) {
const char *p;
size_t len;
if( hdl == NAME_NULL ) {
put8( 0 );
} else {
p = NameGet( hdl );
len = strlen( p );
if( len > MAX_REC - 1 - ( myRecPtr - myRecBuf ) ) {
len = MAX_REC - 1 - ( myRecPtr - myRecBuf );
PrtMsg( WRN | MSG_NAME_TOO_LONG, p );
}
/**/ myassert( len <= 255 );
*myRecPtr++ = len;
memcpy( myRecPtr, p, len );
myRecPtr += len;
/**/ myassert( myRecPtr - myRecBuf < MAX_REC );
}
}
STATIC void putAddr( fixup *fix, uint_8 *data, size_t len ) {
/**/myassert( data != NULL && fix != NULL );
fix->loc_offset = myRecPtr - myRecBuf;
fix->next = waitFixups;
waitFixups = fix;
switch( fix->loc_method ) {
case FIX_POINTER386:
case FIX_OFFSET386:
wait386Fixups = 1;
break;
}
memcpy( myRecPtr, data, len );
myRecPtr += len;
/**/myassert( myRecPtr - myRecBuf < MAX_REC );
}
STATIC void endRec( void ) {
size_t len;
uint_16 fudge;
fixup *cur;
fixup *next;
len = myRecPtr - myRecBuf;
/**/myassert( len <= 256 );
if( ledataOffset + len > MAX_LEDATA ) {
flushLedata();
}
/**/myassert( ledataOffset + len <= MAX_LEDATA );
myRecBuf[ 0 ] = len - 1;
fudge = ledataOffset;
cur = waitFixups;
while( cur ) {
next = cur->next;
cur->loc_offset += fudge;
/**/ myassert( cur->loc_offset < 1024 );
cur->next = doneFixups;
doneFixups = cur;
cur = next;
}
memcpy( ledataBuf + ledataOffset, myRecBuf, len );
ledataOffset += len;
waitFixups = NULL;
done386Fixups = done386Fixups || wait386Fixups;
wait386Fixups = 0;
}
STATIC void symbChangeSeg( symb_handle cur ) {
addr_info *seg;
fixup *oldfix;
fixup *newfix;
/**/myassert( cur != NULL && cur->class == CANS_CHANGE_SEG );
if( blockIndent > 0 ) {
Fatal( MSG_CHANGE_SEG_IN_BLOCK );
}
seg = CanAFind( cur->d.cseg.seg );
oldfix = seg->fixup;
/**/myassert( oldfix->self_relative == 0 ); /* no self-relative */
/* if we had a saved fixup, we nuke it now */
if( offsetFixup != NULL ) {
FixKill( offsetFixup );
}
/* now we can begin writing the record */
newfix = FixDup( oldfix );
newRec( MS_SYM_CHANGE_DEF_SEG );
switch( oldfix->loc_method ) {
case FIX_BASE:
/* great! a simple base fixup, we're done */
codeOffset = 0UL;
putAddr( newfix, seg->data, 2 );
offsetFixup = NULL;
break;
case FIX_POINTER:
/* not so great, this is a pointer fixup and we can only do seg
fixups */
codeOffset = (uint_32)ReadU16( seg->data );
offsetFixup = FixDup( newfix );
offsetFixup->loc_method = FIX_OFFSET;
newfix->loc_method = FIX_BASE;
putAddr( newfix, seg->data + 2, 2 );
break;
case FIX_POINTER386:
/* not so great, this is a pointer fixup and we can only do seg
fixups */
codeOffset = ReadU32( seg->data );
offsetFixup = FixDup( newfix );
offsetFixup->loc_method = FIX_OFFSET386;
newfix->loc_method = FIX_BASE;
putAddr( newfix, seg->data + 4, 2 );
break;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?