pass2.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 652 行 · 第 1/2 页
C
652 行
/****************************************************************************
*
* 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: Disassembler pass 2.
*
****************************************************************************/
#include <stdio.h>
#include <string.h>
#include "global.h"
#include "dis.h"
#include "pass2.h"
#include "buffer.h"
#include "srcmix.h"
#include "formasm.h"
#include "init.h"
#include "main.h"
#include "print.h"
#define COMMENT_TAB_POS 4
#define OPS_REP_TAB_POS 10
#define DIS_X86_SEG_OR ( DIF_X86_CS | DIF_X86_DS | DIF_X86_ES | DIF_X86_FS | \
DIF_X86_GS | DIF_X86_SS )
struct pass2 {
orl_sec_offset loop;
orl_sec_size size;
num_errors disassembly_errors;
ref_entry r_entry;
};
extern wd_options Options;
extern char LabelChar;
extern dis_handle DHnd;
extern bool Prettify;
extern section_list_struct Sections;
extern hash_table HandleToSectionTable;
extern hash_table SymbolToLabelTable;
extern dis_format_flags DFormat;
extern bool source_mix;
extern char * CommentString;
static orl_sec_offset routineBase = 0;
static orl_sec_size routineSize = 0;
dis_return DisCliGetData( void *d, unsigned off, unsigned size, void *buff )
{
//NYI: need to handle going beyond the end of the section
memcpy( buff, (char *)d + off, size );
return( DR_OK );
}
static label_entry handleLabels( char *sec_name, orl_sec_offset offset, orl_sec_offset end,
label_entry l_entry, orl_sec_size size )
// handle any labels at this offset and skip all unused non-label symbols
{
for( ; ( l_entry != NULL ) && ( l_entry->offset < end ); l_entry = l_entry->next ) {
switch( l_entry->type ) {
case LTYP_SECTION:
case LTYP_NAMED:
if( strcmp( l_entry->label.name, sec_name ) == 0 )
continue;
/* fall through */
case LTYP_UNNAMED:
if( l_entry->offset > offset )
return( l_entry );
break;
case LTYP_ABSOLUTE:
case LTYP_FUNC_INFO:
default:
continue;
}
switch( l_entry->type ) {
case LTYP_NAMED:
if( !( DFormat & DFF_ASM ) ) {
if( offset != 0 && l_entry->binding == ORL_SYM_BINDING_GLOBAL ) {
routineSize = offset - routineBase;
BufferConcatNL();
BufferMsg( ROUTINE_SIZE );
BufferStore(" %d ", routineSize );
BufferMsg( BYTES );
BufferConcat(", ");
BufferMsg( ROUTINE_BASE );
BufferStore(" %s + %04X\n\n", sec_name, routineBase );
routineBase = offset;
}
}
case LTYP_SECTION:
if( !( DFormat & DFF_ASM ) ) {
PrintLinePrefix( NULL, offset, size, 1, 0 );
}
BufferStore( "%s:\n", l_entry->label.name );
break;
case LTYP_UNNAMED:
if( !( DFormat & DFF_ASM ) ) {
PrintLinePrefix( NULL, offset, size, 1, 0 );
}
BufferStore( "%c$%d:\n", LabelChar, l_entry->label.number );
break;
}
BufferPrint();
}
return( l_entry );
}
static return_val referenceString( ref_entry r_entry, orl_sec_size size,
char *ext_pref, char *int_pref, char *post,
char *buff, ref_flags flags )
{
label_entry l_entry;
char *sep = ":";
char *frame;
char temp[15];
frame = r_entry->frame;
if( !frame || ( flags & RFLAG_NO_FRAME ) ) {
frame = "";
sep = "";
}
l_entry = r_entry->label;
if( Options & METAWARE_COMPATIBLE || (ext_pref[0]==0 && int_pref[0]==0) ) {
switch( l_entry->type ) {
case LTYP_ABSOLUTE:
FmtHexNum( temp, 0, l_entry->offset );
if( *frame == 0 && ( ( flags & RFLAG_NO_FRAME ) == 0 ) )
frame = "ds:";
sprintf( buff, "%s%s[%s]", frame, sep, temp);
break;
case LTYP_UNNAMED:
sprintf( buff, "%s%s%c$%d%s", frame, sep, LabelChar,
l_entry->label.number, post );
break;
default:
sprintf( buff, "%s%s%s%s", frame, sep, l_entry->label.name,
post );
break;
}
} else {
switch( l_entry->type ) {
case LTYP_EXTERNAL_NAMED:
sprintf( buff, "%s%s%s%s", ext_pref, frame, sep,
l_entry->label.name );
break;
case LTYP_NAMED:
case LTYP_SECTION:
case LTYP_GROUP:
sprintf( buff, "%s%s%s%s", int_pref, frame, sep,
l_entry->label.name );
break;
case LTYP_ABSOLUTE:
FmtHexNum( temp, 0, l_entry->offset );
if( *frame == 0 && ( ( flags & RFLAG_NO_FRAME ) == 0 ) )
frame = "ds:";
sprintf( buff, "%s%s%s[%s]", int_pref, frame, sep, temp);
break;
default:
sprintf( buff, "%s%s%s%c$%d", int_pref, frame, sep,
LabelChar, l_entry->label.number );
if( l_entry->offset > size ) {
return( ERROR );
}
break;
}
}
return( OKAY );
}
unsigned HandleAReference( dis_value value, int ins_size, ref_flags flags,
orl_sec_offset offset, orl_sec_size sec_size,
ref_entry * r_entry, char *buff )
// handle any references at this offset
{
return_val error;
dis_value nvalue;
char *p;
buff[0] = '\0';
for( ; *r_entry && (*r_entry)->offset == offset; *r_entry = (*r_entry)->next ) {
if( (*r_entry)->no_val == 0 ) {
nvalue = value;
} else if( (*r_entry)->addend ) {
nvalue = HandleAddend( *r_entry );
} else {
nvalue = 0;
}
switch( (*r_entry)->type ) {
case ORL_RELOC_TYPE_MAX + 1:
case ORL_RELOC_TYPE_JUMP:
case ORL_RELOC_TYPE_REL_21_SH:
case ORL_RELOC_TYPE_WORD_26:
error = referenceString( *r_entry, sec_size, "j^", "", "",
buff, flags );
if( error != OKAY ) {
// label is defined to be beyond the boundaries of the section!
if( !(DFormat & DFF_ASM) ){
BufferStore("\t %04X", offset );
BufferAlignToTab( COMMENT_TAB_POS );
} else {
BufferConcat("\t" );
}
BufferConcat( CommentString );
BufferMsg( LABEL_BEYOND_SECTION );
BufferConcatNL();
BufferPrint();
*r_entry = (*r_entry)->next;
return( 0 );
}
continue; // Don't print addend
break;
case ORL_RELOC_TYPE_SEC_REL:
referenceString( *r_entry, sec_size, "s^", "s^", "@s", buff,
flags );
break;
case ORL_RELOC_TYPE_HALF_HI:
referenceString( *r_entry, sec_size, "h^", "h^", "@h", buff,
flags );
break;
case ORL_RELOC_TYPE_HALF_HA:
referenceString( *r_entry, sec_size, "ha^", "ha^", "@ha", buff,
flags );
break;
case ORL_RELOC_TYPE_HALF_LO:
referenceString( *r_entry, sec_size, "l^", "l^", "@l", buff,
flags );
break;
case ORL_RELOC_TYPE_REL_14:
case ORL_RELOC_TYPE_REL_24:
case ORL_RELOC_TYPE_WORD_14:
case ORL_RELOC_TYPE_WORD_24:
nvalue &= ~0x3;
case ORL_RELOC_TYPE_WORD_16:
case ORL_RELOC_TYPE_WORD_32:
case ORL_RELOC_TYPE_WORD_64:
if( ( (*r_entry)->label->type != LTYP_GROUP ) &&
( flags & RFLAG_IS_IMMED ) && IsMasmOutput() ) {
referenceString( *r_entry, sec_size, "offset ", "offset ",
"", buff, flags );
} else {
referenceString( *r_entry, sec_size, "", "", "", buff,
flags );
}
break;
case ORL_RELOC_TYPE_REL_16:
if( IsIntelx86() && !(*r_entry)->no_val ) {
nvalue -= ins_size;
}
if( ( (*r_entry)->label->type != LTYP_GROUP ) &&
( flags & RFLAG_IS_IMMED ) && IsMasmOutput() ) {
referenceString( *r_entry, sec_size, "offset ", "offset ",
"", buff, flags );
} else {
referenceString( *r_entry, sec_size, "", "", "", buff,
flags );
}
break;
case ORL_RELOC_TYPE_WORD_8:
case ORL_RELOC_TYPE_WORD_16_SEG:
case ORL_RELOC_TYPE_WORD_HI_8:
case ORL_RELOC_TYPE_WORD_32_SEG:
// Keep these seperate because they are OMF specific
referenceString( *r_entry, sec_size, "", "", "", buff, flags );
break;
case ORL_RELOC_TYPE_SEGMENT:
if( ( (*r_entry)->label->type != LTYP_GROUP )
&& ( (*r_entry)->label->type != LTYP_SECTION )
&& ( flags & RFLAG_IS_IMMED )
&& IsMasmOutput() ) {
referenceString( *r_entry, sec_size, "seg ", "seg ", "",
buff, flags );
} else {
referenceString( *r_entry, sec_size, "", "", "", buff,
flags );
}
break;
case ORL_RELOC_TYPE_REL_32_NOADJ:
// this is a little kluge because Brian's ELF files seem to have
// -4 in the implicit addend for calls and such BBB May 09, 1997
nvalue += 4;
// fall through
case ORL_RELOC_TYPE_REL_8:
case ORL_RELOC_TYPE_REL_16_SEG:
case ORL_RELOC_TYPE_REL_HI_8:
case ORL_RELOC_TYPE_REL_32_SEG:
case ORL_RELOC_TYPE_REL_32:
case ORL_RELOC_TYPE_REL_32_ADJ5:
case ORL_RELOC_TYPE_REL_32_ADJ4:
case ORL_RELOC_TYPE_REL_32_ADJ3:
case ORL_RELOC_TYPE_REL_32_ADJ2:
case ORL_RELOC_TYPE_REL_32_ADJ1:
// For some reason we add the instruction size to the value
// of the displacement in a relative call and get a bad
// offset, due to CORE implementation
//
// Main reason :
// instruction size with displacement and with addend is correct for
// relative addresses without relocate
//
// in amd64 code the instruction size will be added in pass1.c!
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?