formasm.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 889 行 · 第 1/2 页
C
889 行
/****************************************************************************
*
* 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 <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "dis.h"
#include "formasm.h"
#include "langenv.h"
#include "memfuncs.h"
#include "buffer.h"
#include "hashtabl.h"
#include "pass1.h"
#include "pass2.h"
#include "print.h"
#include "main.h"
#include "init.h"
#define STRING_LINE_LEN 41
#define UNPRINT_MAX_LEN 6
extern hash_table HandleToLabelListTable;
extern hash_table HandleToRefListTable;
extern hash_table SkipRefTable;
extern wd_options Options;
extern dis_format_flags DFormat;
extern char LabelChar;
extern char QuoteChar;
static const char * const masmTypes[] = {NULL, // 0
"DB\t", // 1
"DW\t", // 2
NULL, // 3
"DD\t", // 4
NULL, // 5
"DF\t", // 6
NULL, // 7
"DQ\t" // 8
};
static const char *const unixTypes[] = {NULL, // 0
".byte\t", // 1
".word\t", // 2
NULL, // 3
".long\t", // 4
NULL, // 5
NULL, // 6
NULL, // 7
".quad\t" // 8
};
// do a strncpy with max # characters = sec_size - current_position
// if # chars copied == sec_size - current_position and last character
// is not a NULL
// <<.ascii>>
// otherwise
// <<.asciz>>
// print it out
// update the current position
// repeat until end of section reached
typedef enum {
ASCII,
ASCIZ
} string_type;
int IsMasmOutput( void )
{
return( !( DFormat & DFF_X86_UNIX ) && ( GetFormat() == ORL_OMF ) );
}
static void printRawAndAddress( char * raw_data, orl_sec_offset address )
{
switch( strlen( raw_data ) ) {
case 0:
BufferStore( " 00 %04X", address );
break;
case 1:
BufferStore( " 00%02X %04X", raw_data[0], address );
break;
case 2:
BufferStore( " 00%02X%02X %04X", raw_data[1], raw_data[0],
address );
break;
case 3:
BufferStore( "00%02X%02X%02X %04X", raw_data[2], raw_data[1],
raw_data[0], address );
break;
default:
BufferStore( "%02X%02X%02X%02X %04X", raw_data[3],
raw_data[2], raw_data[1], raw_data[0], address );
break;
}
}
static bool printableChar( char c )
{
// fixme: which characters should be printed as is and which not?
if( isprint( c ) || c == '\n' || c == '\r' || c == '\t' || c == '\f' ) {
return TRUE;
} else {
return FALSE;
}
}
static bool printableString( char *s )
{
int i;
for( i = 0; i < strlen( s ); i++ ){
if( !printableChar( s[i] ) ) {
return FALSE;
}
}
return TRUE;
}
static orl_sec_offset printString( char * string, string_type type )
{
char *buffer;
orl_sec_offset i,j;
buffer = MemAlloc( strlen( string ) * 2 + 1 );
for( i=0, j=0; i < strlen( string ); i++ ){
switch( string[i] ){
case '\n':
buffer[j++] = '\\';
buffer[j++] = 'n';
break;
case '\r':
buffer[j++] = '\\';
buffer[j++] = 'r';
break;
case '\t':
buffer[j++] = '\\';
buffer[j++] = 't';
break;
case '\f':
buffer[j++] = '\\';
buffer[j++] = 'f';
break;
case '\\':
buffer[j++] = '\\';
buffer[j++] = '\\';
break;
case '\"':
buffer[j++] = QuoteChar;
buffer[j++] = '\"';
break;
case '\'':
buffer[j++] = '\\';
buffer[j++] = '\'';
break;
default:
buffer[j++] = string[i];
break;
}
}
buffer[j] = 0;
BufferStore( "\"%s\"", buffer );
BufferPrint();
MemFree( buffer );
switch( type ) {
case ASCII:
return( strlen( string ) );
case ASCIZ:
return( strlen( string ) + 1 );
}
// shouldn't get here, but compiler complains.
return( 0 );
}
static orl_sec_offset tryDUP(char *string, orl_sec_offset i, orl_sec_size size)
{
orl_sec_offset d;
unsigned int dup;
if( i >= ( size - ( 8 * MIN_DUP_LINES ) ) ) return( 0 );
for( d = i + 8; d < ( size - 8 ); d += 8 ) {
if( memcmp( &string[i], &string[d], 8 ) ) return( 0 );
}
d -= i;
dup = d / 8;
if( dup < MIN_DUP_LINES ) return( 0 );
BufferStore( "0%XH DUP(", dup, string[i] );
for( dup = 0; dup < 7; dup++ ) {
BufferHex( 2, string[i + dup] );
BufferConcat( "," );
}
BufferHex( 2, string[i + 7] );
BufferConcat( ")" );
return( d );
}
static void printRest( char *string, orl_sec_size size )
{
orl_sec_offset i;
orl_sec_offset d;
char *btype;
int is_masm;
is_masm = IsMasmOutput();
if( is_masm ) {
btype = " DB\t";
} else {
btype = " .byte\t";
}
BufferConcat( btype );
for( i = 0; i < size; ) {
// see if we can replace large chunks of homogenous
// segment space by using the DUP macro
if( is_masm && !( i % 8 ) ) {
d = tryDUP( string, i, size );
if( d > 0 ) {
i += d;
if( i < size ) {
BufferConcatNL();
BufferConcat( btype );
BufferPrint();
}
continue;
}
}
BufferHex( 2, string[i] );
if( i < size-1 ) {
if( ( i % 8 ) == 7 ) {
BufferConcatNL();
BufferConcat( btype );
BufferPrint();
} else {
BufferConcat(", ");
}
}
i++;
}
BufferConcatNL();
BufferPrint();
}
dis_value HandleAddend( ref_entry r_entry )
// sign-extend an addend value by the appropriate number of bits.
{
dis_value r_addend;
int bits;
r_addend = r_entry->addend;
switch( r_entry->type ) {
case ORL_RELOC_TYPE_REL_14:
case ORL_RELOC_TYPE_WORD_14:
case ORL_RELOC_TYPE_TOCREL_14:
case ORL_RELOC_TYPE_TOCVREL_14:
bits = 14;
break;
case ORL_RELOC_TYPE_REL_24:
case ORL_RELOC_TYPE_WORD_24:
case ORL_RELOC_TYPE_PLTREL_24:
bits = 24;
break;
case ORL_RELOC_TYPE_WORD_26:
bits = 26;
break;
case ORL_RELOC_TYPE_REL_16:
case ORL_RELOC_TYPE_WORD_16:
case ORL_RELOC_TYPE_HALF_HI:
case ORL_RELOC_TYPE_HALF_HA:
case ORL_RELOC_TYPE_HALF_LO:
case ORL_RELOC_TYPE_TOCREL_16:
case ORL_RELOC_TYPE_TOCVREL_16:
case ORL_RELOC_TYPE_GOT_16:
case ORL_RELOC_TYPE_GOT_16_HI:
case ORL_RELOC_TYPE_GOT_16_HA:
case ORL_RELOC_TYPE_GOT_16_LO:
case ORL_RELOC_TYPE_PLT_16_HI:
case ORL_RELOC_TYPE_PLT_16_HA:
case ORL_RELOC_TYPE_PLT_16_LO:
bits = 16;
break;
case ORL_RELOC_TYPE_WORD_32:
case ORL_RELOC_TYPE_WORD_32_NB:
case ORL_RELOC_TYPE_JUMP:
case ORL_RELOC_TYPE_SEC_REL:
case ORL_RELOC_TYPE_REL_32:
case ORL_RELOC_TYPE_REL_32_NOADJ:
case ORL_RELOC_TYPE_REL_32_ADJ1:
case ORL_RELOC_TYPE_REL_32_ADJ2:
case ORL_RELOC_TYPE_REL_32_ADJ3:
case ORL_RELOC_TYPE_REL_32_ADJ4:
case ORL_RELOC_TYPE_REL_32_ADJ5:
case ORL_RELOC_TYPE_PLTREL_32:
case ORL_RELOC_TYPE_PLT_32:
default:
bits = 32;
break;
case ORL_RELOC_TYPE_REL_21_SH:
// Will NEVER happen
bits = 21;
break;
case ORL_RELOC_TYPE_WORD_64:
// Will NEVER happen
bits = 64;
break;
}
if( (bits != 32) && (r_addend & (1 << (bits-1) ) ) ) {
return( r_addend | ( 0xFFFFFFFF ^ ( (1<<bits) - 1 ) ) );
} else {
return( r_addend );
}
}
int IsDataReloc( ref_entry r_entry )
{
switch( r_entry->type ) {
case ORL_RELOC_TYPE_ABSOLUTE:
case ORL_RELOC_TYPE_WORD_32:
case ORL_RELOC_TYPE_WORD_32_NB:
case ORL_RELOC_TYPE_SECTION:
case ORL_RELOC_TYPE_REL_32:
case ORL_RELOC_TYPE_REL_32_NOADJ:
case ORL_RELOC_TYPE_REL_32_ADJ1:
case ORL_RELOC_TYPE_REL_32_ADJ2:
case ORL_RELOC_TYPE_REL_32_ADJ3:
case ORL_RELOC_TYPE_REL_32_ADJ4:
case ORL_RELOC_TYPE_REL_32_ADJ5:
case ORL_RELOC_TYPE_PLTREL_32:
case ORL_RELOC_TYPE_PLT_32:
case ORL_RELOC_TYPE_WORD_64:
return( 1 );
default:
return( 0 );
}
}
orl_sec_offset RelocSize( ref_entry r_entry )
{
switch( r_entry->type ) {
case ORL_RELOC_TYPE_ABSOLUTE:
case ORL_RELOC_TYPE_WORD_32:
case ORL_RELOC_TYPE_WORD_32_NB:
case ORL_RELOC_TYPE_JUMP:
case ORL_RELOC_TYPE_SECTION:
case ORL_RELOC_TYPE_SEC_REL:
case ORL_RELOC_TYPE_REL_21_SH:
case ORL_RELOC_TYPE_WORD_24:
case ORL_RELOC_TYPE_WORD_26:
case ORL_RELOC_TYPE_REL_24:
case ORL_RELOC_TYPE_REL_32:
case ORL_RELOC_TYPE_REL_32_NOADJ:
case ORL_RELOC_TYPE_REL_32_ADJ1:
case ORL_RELOC_TYPE_REL_32_ADJ2:
case ORL_RELOC_TYPE_REL_32_ADJ3:
case ORL_RELOC_TYPE_REL_32_ADJ4:
case ORL_RELOC_TYPE_REL_32_ADJ5:
case ORL_RELOC_TYPE_PLTREL_24:
case ORL_RELOC_TYPE_PLTREL_32:
case ORL_RELOC_TYPE_PLT_32:
case ORL_RELOC_TYPE_WORD_16_SEG:
case ORL_RELOC_TYPE_REL_16_SEG:
return 4;
case ORL_RELOC_TYPE_WORD_16:
case ORL_RELOC_TYPE_HALF_HI:
case ORL_RELOC_TYPE_HALF_LO:
case ORL_RELOC_TYPE_REL_16:
case ORL_RELOC_TYPE_SEGMENT:
case ORL_RELOC_TYPE_WORD_14:
case ORL_RELOC_TYPE_REL_14:
case ORL_RELOC_TYPE_TOCREL_16:
case ORL_RELOC_TYPE_TOCREL_14:
case ORL_RELOC_TYPE_TOCVREL_16:
case ORL_RELOC_TYPE_TOCVREL_14:
case ORL_RELOC_TYPE_GOT_16:
case ORL_RELOC_TYPE_GOT_16_HI:
case ORL_RELOC_TYPE_GOT_16_HA:
case ORL_RELOC_TYPE_GOT_16_LO:
case ORL_RELOC_TYPE_PLT_16_HI:
case ORL_RELOC_TYPE_PLT_16_HA:
case ORL_RELOC_TYPE_PLT_16_LO:
return 2;
case ORL_RELOC_TYPE_WORD_64:
return 8;
case ORL_RELOC_TYPE_WORD_32_SEG:
case ORL_RELOC_TYPE_REL_32_SEG:
return 6;
case ORL_RELOC_TYPE_WORD_8:
case ORL_RELOC_TYPE_REL_8:
case ORL_RELOC_TYPE_WORD_HI_8:
case ORL_RELOC_TYPE_REL_HI_8:
return 1;
default:
// This should never happen, but 4 is the most likely size.
return 4;
}
}
orl_sec_offset HandleRefInData( ref_entry r_entry, void *data, bool asmLabels )
{
orl_sec_offset rv;
const char * const *types;
char buff[MAX_SYM_LEN]; // fixme: should be TS_MAX_OBJNAME or something
if( IsMasmOutput() ) {
types = masmTypes;
} else {
types = unixTypes;
}
rv = RelocSize( r_entry );
switch( rv ) {
case 6:
if( asmLabels && types[rv] ) {
BufferConcat( types[rv] );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?