size_t DisCliValueString( void *d, dis_dec_ins *ins, unsigned op_num, char *buff, size_t buff_len ) { struct pass2 *pd = d; size_t len; dis_operand *op; ref_flags rf; buff_len = buff_len; buff[0] = '\0'; rf = RFLAG_DEFAULT; op = &ins->op[op_num]; switch( op->type & DO_MASK ) { case DO_RELATIVE: case DO_MEMORY_REL: case DO_ABSOLUTE: case DO_MEMORY_ABS: if( pd->r_entry != NULL ) { /* if there is an override we must avoid the frame */ if( ( ins->flags.u.x86 & DIS_X86_SEG_OR ) && IsIntelx86() ) { rf |= RFLAG_NO_FRAME; } len = HandleAReference( op->value, ins->size, rf, pd->loop + op->op_position, pd->size, &pd->r_entry, buff ); if( len != 0 ) { return( len ); } } switch( op->type & DO_MASK ) { case DO_RELATIVE: case DO_MEMORY_REL: op->value += pd->loop; break; } if( op->base == DR_NONE && op->index == DR_NONE ) { FmtSizedHexNum( buff, ins, op_num ); } else if( op->value > 0 ) { FmtHexNum( buff, 0, op->value, FALSE ); } else if( op->value < 0 ) { buff[0] = '-'; FmtHexNum( &buff[1], 0, -op->value, FALSE ); } break; case DO_IMMED: if( pd->r_entry != NULL ) { rf |= RFLAG_IS_IMMED; len = HandleAReference( op->value, ins->size, rf, pd->loop + op->op_position, pd->size, &pd->r_entry, buff ); if( len != 0 ) { return( len ); } } FmtSizedHexNum( buff, ins, op_num ); break; } return( strlen( buff ) ); }
static void FmtSizedHexNum( char *buff, dis_dec_ins *ins, unsigned op_num ) { unsigned size; unsigned i; unsigned len; static const unsigned long mask[] = { 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff, 0xffffffff }; size = 0; for( i = 0; i < ins->num_ops; ++i ) { switch( ins->op[i].ref_type ) { case DRT_X86_BYTE: len = 1; break; case DRT_X86_WORD: len = 2; break; case DRT_X86_DWORD: case DRT_X86_DWORDF: len = 4; break; default: len = 0; break; } if( len > size ) size = len; } if( size == 0 ) size = 4; FmtHexNum( buff, size * 2, mask[size] & ins->op[op_num].value ); }
extern unsigned DisCliValueString( void *d, dis_dec_ins *ins, unsigned op_num, char *buff ) { dis_operand *op; code_buff *header; header = (code_buff *)d; buff[0] = '\0'; op = &ins->op[op_num]; switch( op->type & DO_MASK ) { case DO_RELATIVE: case DO_MEMORY_REL: case DO_ABSOLUTE: case DO_MEMORY_ABS: switch( op->type & DO_MASK ) { case DO_RELATIVE: case DO_MEMORY_REL: op->value += header->offset; break; } if( op->base == DR_NONE && op->index == DR_NONE ) { FmtSizedHexNum( buff, ins, op_num ); } else if( op->value > 0 ) { FmtHexNum( buff, 0, op->value ); } else if( op->value < 0 ) { buff[0] = '-'; FmtHexNum( &buff[1], 0, -op->value ); } break; case DO_IMMED: // FmtSizedHexNum( buff, ins, op_num ); if( op->value < 0 ) { buff[0] = '-'; FmtHexNum( &buff[1], 0, -op->value ); } else { FmtHexNum( buff, 0, op->value ); } break; } return( strlen( buff ) ); }
static void FmtSizedHexNum( char *buff, dis_dec_ins *ins, unsigned op_num ) { unsigned size; unsigned len; unsigned i; unsigned mask; bool sign_extended; bool no_prefix; signed_32 value; mask = 0; sign_extended = FALSE; no_prefix = FALSE; value = ins->op[op_num].value; switch( ins->op[op_num].ref_type ) { case DRT_SPARC_BYTE: case DRT_X86_BYTE: case DRT_X64_BYTE: size = 2; mask = 0x000000ff; break; case DRT_SPARC_HALF: case DRT_X86_WORD: case DRT_X64_WORD: size = 4; mask = 0x0000ffff; break; case DRT_SPARC_WORD: case DRT_SPARC_SFLOAT: case DRT_X86_DWORD: case DRT_X86_DWORDF: case DRT_X64_DWORD: size = 8; mask = 0xffffffff; break; case DRT_X64_QWORD: sign_extended = TRUE; // fall down case DRT_SPARC_DWORD: case DRT_SPARC_DFLOAT: size = 16; mask = 0xffffffff; break; default: size = 0; for( i = 0; i < ins->num_ops; i++ ) { switch( ins->op[i].ref_type ) { case DRT_X86_BYTE: case DRT_X64_BYTE: len = 2; if ( len > size ) { size = len; mask = 0x000000ff; } break; case DRT_X86_WORD: case DRT_X64_WORD: len = 4; if ( len > size ) { size = len; mask = 0x0000ffff; } break; case DRT_X86_DWORD: case DRT_X86_DWORDF: case DRT_X64_DWORD: len = 8; if ( len > size ) { size = len; mask = 0xffffffff; } break; case DRT_X64_QWORD: len = 16; if ( len > size ) { size = len; mask = 0xffffffff; sign_extended = TRUE; } break; default: break; } } if ( size == 0 ) { size = 8; mask = 0xffffffff; } break; } if( size > 8 ) { size = 8; if( sign_extended ) { if( value < 0 ) { FmtHexNum( buff, size, 0xffffffff, no_prefix ); } else { FmtHexNum( buff, size, 0, no_prefix ); } buff += strlen( buff ); no_prefix = TRUE; } } FmtHexNum( buff, size, mask & value, no_prefix ); }
size_t 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 != RC_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! if( (*r_entry)->no_val == 0 && !( GetMachineType() == ORL_MACHINE_TYPE_AMD64 ) ) { nvalue -= ins_size; } referenceString( *r_entry, sec_size, "", "", "", buff, flags ); break; case ORL_RELOC_TYPE_TOCREL_14: nvalue &= ~0x3; case ORL_RELOC_TYPE_TOCREL_16: referenceString( *r_entry, sec_size, "[toc]", "[toc]", "@toc", buff, flags ); break; case ORL_RELOC_TYPE_TOCVREL_14: nvalue &= ~0x3; case ORL_RELOC_TYPE_TOCVREL_16: referenceString( *r_entry, sec_size, "[tocv]", "[tocv]", "@tocv", buff, flags ); break; case ORL_RELOC_TYPE_GOT_16: referenceString( *r_entry, sec_size, "", "", "@got", buff, flags ); break; case ORL_RELOC_TYPE_GOT_16_HI: referenceString( *r_entry, sec_size, "", "", "@got@h", buff, flags ); break; case ORL_RELOC_TYPE_GOT_16_HA: referenceString( *r_entry, sec_size, "", "", "@got@ha", buff, flags ); break; case ORL_RELOC_TYPE_GOT_16_LO: referenceString( *r_entry, sec_size, "", "", "@got@l", buff, flags ); break; case ORL_RELOC_TYPE_PLTREL_24: case ORL_RELOC_TYPE_PLTREL_32: case ORL_RELOC_TYPE_PLT_32: referenceString( *r_entry, sec_size, "", "", "@plt", buff, flags ); break; case ORL_RELOC_TYPE_PLT_16_HI: referenceString( *r_entry, sec_size, "", "", "@plt@h", buff, flags ); break; case ORL_RELOC_TYPE_PLT_16_HA: referenceString( *r_entry, sec_size, "", "", "@plt@ha", buff, flags ); break; case ORL_RELOC_TYPE_PLT_16_LO: referenceString( *r_entry, sec_size, "", "", "@plt@l", buff, flags ); break; default: continue; } // LTYP_UNNAMED labels are always at the correct location // if( nvalue != 0 && (*r_entry)->label->type != LTYP_UNNAMED ) { // not so - BBB Oct 28, 1996 if(( (*r_entry)->no_val == 0 ) && ( nvalue != 0 )) { p = &buff[strlen(buff)]; if( nvalue < 0 ) { *p++ = '-'; nvalue = -nvalue; } else { *p++ = '+'; } FmtHexNum( p, 0, nvalue, FALSE ); } } return( strlen( buff ) ); }
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, FALSE ); 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$%ld%s", frame, sep, LabelChar, (long)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, FALSE ); 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$%ld", int_pref, frame, sep, LabelChar, (long)l_entry->label.number ); if( l_entry->offset > size ) { return( RC_ERROR ); } break; } } return( RC_OKAY ); }