1 /*
   2  * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 // We have interfaces for the following instructions:
  26 // - NativeInstruction
  27 // - - NativeCall
  28 // - - NativeMovConstReg
  29 // - - NativeMovConstRegPatching
  30 // - - NativeMovRegMem
  31 // - - NativeMovRegMemPatching
  32 // - - NativeJump
  33 // - - NativeIllegalOpCode
  34 // - - NativeGeneralJump
  35 // - - NativeReturn
  36 // - - NativeReturnX (return with argument)
  37 // - - NativePushConst
  38 // - - NativeTstRegMem
  39 
  40 // The base class for different kinds of native instruction abstractions.
  41 // Provides the primitive operations to manipulate code relative to this.
  42 
  43 class NativeInstruction VALUE_OBJ_CLASS_SPEC {
  44   friend class Relocation;
  45 
  46  public:
  47   enum Intel_specific_constants {
  48     nop_instruction_code        = 0x90,
  49     nop_instruction_size        =    1
  50   };
  51 
  52   bool is_nop()                        { return ubyte_at(0) == nop_instruction_code; }
  53   bool is_dtrace_trap();
  54   inline bool is_call();
  55   inline bool is_illegal();
  56   inline bool is_return();
  57   inline bool is_jump();
  58   inline bool is_cond_jump();
  59   inline bool is_safepoint_poll();
  60   inline bool is_mov_literal64();
  61 
  62  protected:
  63   address addr_at(int offset) const    { return address(this) + offset; }
  64 
  65   s_char sbyte_at(int offset) const    { return *(s_char*) addr_at(offset); }
  66   u_char ubyte_at(int offset) const    { return *(u_char*) addr_at(offset); }
  67 
  68   jint int_at(int offset) const         { return *(jint*) addr_at(offset); }
  69 
  70   intptr_t ptr_at(int offset) const    { return *(intptr_t*) addr_at(offset); }
  71 
  72   oop  oop_at (int offset) const       { return *(oop*) addr_at(offset); }
  73 
  74 
  75   void set_char_at(int offset, char c)        { *addr_at(offset) = (u_char)c; wrote(offset); }
  76   void set_int_at(int offset, jint  i)        { *(jint*)addr_at(offset) = i;  wrote(offset); }
  77   void set_ptr_at (int offset, intptr_t  ptr) { *(intptr_t*) addr_at(offset) = ptr;  wrote(offset); }
  78   void set_oop_at (int offset, oop  o)        { *(oop*) addr_at(offset) = o;  wrote(offset); }
  79 
  80   // This doesn't really do anything on Intel, but it is the place where
  81   // cache invalidation belongs, generically:
  82   void wrote(int offset);
  83 
  84  public:
  85 
  86   // unit test stuff
  87   static void test() {}                 // override for testing
  88 
  89   inline friend NativeInstruction* nativeInstruction_at(address address);
  90 };
  91 
  92 inline NativeInstruction* nativeInstruction_at(address address) {
  93   NativeInstruction* inst = (NativeInstruction*)address;
  94 #ifdef ASSERT
  95   //inst->verify();
  96 #endif
  97   return inst;
  98 }
  99 
 100 inline NativeCall* nativeCall_at(address address);
 101 // The NativeCall is an abstraction for accessing/manipulating native call imm32/rel32off
 102 // instructions (used to manipulate inline caches, primitive & dll calls, etc.).
 103 
 104 class NativeCall: public NativeInstruction {
 105  public:
 106   enum Intel_specific_constants {
 107     instruction_code            = 0xE8,
 108     instruction_size            =    5,
 109     instruction_offset          =    0,
 110     displacement_offset         =    1,
 111     return_address_offset       =    5
 112   };
 113 
 114   enum { cache_line_size = BytesPerWord };  // conservative estimate!
 115 
 116   address instruction_address() const       { return addr_at(instruction_offset); }
 117   address next_instruction_address() const  { return addr_at(return_address_offset); }
 118   int   displacement() const                { return (jint) int_at(displacement_offset); }
 119   address displacement_address() const      { return addr_at(displacement_offset); }
 120   address return_address() const            { return addr_at(return_address_offset); }
 121   address destination() const;
 122   void  set_destination(address dest)       {
 123 #ifdef AMD64
 124     assert((labs((intptr_t) dest - (intptr_t) return_address())  &
 125             0xFFFFFFFF00000000) == 0,
 126            "must be 32bit offset");
 127 #endif // AMD64
 128     set_int_at(displacement_offset, dest - return_address());
 129   }
 130   void  set_destination_mt_safe(address dest);
 131 
 132   void  verify_alignment() { assert((intptr_t)addr_at(displacement_offset) % BytesPerInt == 0, "must be aligned"); }
 133   void  verify();
 134   void  print();
 135 
 136   // Creation
 137   inline friend NativeCall* nativeCall_at(address address);
 138   inline friend NativeCall* nativeCall_before(address return_address);
 139 
 140   static bool is_call_at(address instr) {
 141     return ((*instr) & 0xFF) == NativeCall::instruction_code;
 142   }
 143 
 144   static bool is_call_before(address return_address) {
 145     return is_call_at(return_address - NativeCall::return_address_offset);
 146   }
 147 
 148   static bool is_call_to(address instr, address target) {
 149     return nativeInstruction_at(instr)->is_call() &&
 150       nativeCall_at(instr)->destination() == target;
 151   }
 152 
 153   // MT-safe patching of a call instruction.
 154   static void insert(address code_pos, address entry);
 155 
 156   static void replace_mt_safe(address instr_addr, address code_buffer);
 157 };
 158 
 159 inline NativeCall* nativeCall_at(address address) {
 160   NativeCall* call = (NativeCall*)(address - NativeCall::instruction_offset);
 161 #ifdef ASSERT
 162   call->verify();
 163 #endif
 164   return call;
 165 }
 166 
 167 inline NativeCall* nativeCall_before(address return_address) {
 168   NativeCall* call = (NativeCall*)(return_address - NativeCall::return_address_offset);
 169 #ifdef ASSERT
 170   call->verify();
 171 #endif
 172   return call;
 173 }
 174 
 175 // An interface for accessing/manipulating native mov reg, imm32 instructions.
 176 // (used to manipulate inlined 32bit data dll calls, etc.)
 177 class NativeMovConstReg: public NativeInstruction {
 178 #ifdef AMD64
 179   static const bool has_rex = true;
 180   static const int rex_size = 1;
 181 #else
 182   static const bool has_rex = false;
 183   static const int rex_size = 0;
 184 #endif // AMD64
 185  public:
 186   enum Intel_specific_constants {
 187     instruction_code            = 0xB8,
 188     instruction_size            =    1 + rex_size + wordSize,
 189     instruction_offset          =    0,
 190     data_offset                 =    1 + rex_size,
 191     next_instruction_offset     =    instruction_size,
 192     register_mask               = 0x07
 193   };
 194 
 195   address instruction_address() const       { return addr_at(instruction_offset); }
 196   address next_instruction_address() const  { return addr_at(next_instruction_offset); }
 197   intptr_t data() const                     { return ptr_at(data_offset); }
 198   void  set_data(intptr_t x)                { set_ptr_at(data_offset, x); }
 199 
 200   void  verify();
 201   void  print();
 202 
 203   // unit test stuff
 204   static void test() {}
 205 
 206   // Creation
 207   inline friend NativeMovConstReg* nativeMovConstReg_at(address address);
 208   inline friend NativeMovConstReg* nativeMovConstReg_before(address address);
 209 };
 210 
 211 inline NativeMovConstReg* nativeMovConstReg_at(address address) {
 212   NativeMovConstReg* test = (NativeMovConstReg*)(address - NativeMovConstReg::instruction_offset);
 213 #ifdef ASSERT
 214   test->verify();
 215 #endif
 216   return test;
 217 }
 218 
 219 inline NativeMovConstReg* nativeMovConstReg_before(address address) {
 220   NativeMovConstReg* test = (NativeMovConstReg*)(address - NativeMovConstReg::instruction_size - NativeMovConstReg::instruction_offset);
 221 #ifdef ASSERT
 222   test->verify();
 223 #endif
 224   return test;
 225 }
 226 
 227 class NativeMovConstRegPatching: public NativeMovConstReg {
 228  private:
 229     friend NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address) {
 230     NativeMovConstRegPatching* test = (NativeMovConstRegPatching*)(address - instruction_offset);
 231     #ifdef ASSERT
 232       test->verify();
 233     #endif
 234     return test;
 235   }
 236 };
 237 
 238 // An interface for accessing/manipulating native moves of the form:
 239 //      mov[b/w/l/q] [reg + offset], reg   (instruction_code_reg2mem)
 240 //      mov[b/w/l/q] reg, [reg+offset]     (instruction_code_mem2reg
 241 //      mov[s/z]x[w/b/q] [reg + offset], reg
 242 //      fld_s  [reg+offset]
 243 //      fld_d  [reg+offset]
 244 //      fstp_s [reg + offset]
 245 //      fstp_d [reg + offset]
 246 //      mov_literal64  scratch,<pointer> ; mov[b/w/l/q] 0(scratch),reg | mov[b/w/l/q] reg,0(scratch)
 247 //
 248 // Warning: These routines must be able to handle any instruction sequences
 249 // that are generated as a result of the load/store byte,word,long
 250 // macros.  For example: The load_unsigned_byte instruction generates
 251 // an xor reg,reg inst prior to generating the movb instruction.  This
 252 // class must skip the xor instruction.
 253 
 254 class NativeMovRegMem: public NativeInstruction {
 255  public:
 256   enum Intel_specific_constants {
 257     instruction_prefix_wide_lo          = Assembler::REX,
 258     instruction_prefix_wide_hi          = Assembler::REX_WRXB,
 259     instruction_code_xor                = 0x33,
 260     instruction_extended_prefix         = 0x0F,
 261     instruction_code_mem2reg_movslq     = 0x63,
 262     instruction_code_mem2reg_movzxb     = 0xB6,
 263     instruction_code_mem2reg_movsxb     = 0xBE,
 264     instruction_code_mem2reg_movzxw     = 0xB7,
 265     instruction_code_mem2reg_movsxw     = 0xBF,
 266     instruction_operandsize_prefix      = 0x66,
 267     instruction_code_reg2mem            = 0x89,
 268     instruction_code_mem2reg            = 0x8b,
 269     instruction_code_reg2memb           = 0x88,
 270     instruction_code_mem2regb           = 0x8a,
 271     instruction_code_float_s            = 0xd9,
 272     instruction_code_float_d            = 0xdd,
 273     instruction_code_long_volatile      = 0xdf,
 274     instruction_code_xmm_ss_prefix      = 0xf3,
 275     instruction_code_xmm_sd_prefix      = 0xf2,
 276     instruction_code_xmm_code           = 0x0f,
 277     instruction_code_xmm_load           = 0x10,
 278     instruction_code_xmm_store          = 0x11,
 279     instruction_code_xmm_lpd            = 0x12,
 280 
 281     instruction_size                    = 4,
 282     instruction_offset                  = 0,
 283     data_offset                         = 2,
 284     next_instruction_offset             = 4
 285   };
 286 
 287   // helper
 288   int instruction_start() const;
 289 
 290   address instruction_address() const;
 291 
 292   address next_instruction_address() const;
 293 
 294   int   offset() const;
 295 
 296   void  set_offset(int x);
 297 
 298   void  add_offset_in_bytes(int add_offset)     { set_offset ( ( offset() + add_offset ) ); }
 299 
 300   void verify();
 301   void print ();
 302 
 303   // unit test stuff
 304   static void test() {}
 305 
 306  private:
 307   inline friend NativeMovRegMem* nativeMovRegMem_at (address address);
 308 };
 309 
 310 inline NativeMovRegMem* nativeMovRegMem_at (address address) {
 311   NativeMovRegMem* test = (NativeMovRegMem*)(address - NativeMovRegMem::instruction_offset);
 312 #ifdef ASSERT
 313   test->verify();
 314 #endif
 315   return test;
 316 }
 317 
 318 class NativeMovRegMemPatching: public NativeMovRegMem {
 319  private:
 320   friend NativeMovRegMemPatching* nativeMovRegMemPatching_at (address address) {
 321     NativeMovRegMemPatching* test = (NativeMovRegMemPatching*)(address - instruction_offset);
 322     #ifdef ASSERT
 323       test->verify();
 324     #endif
 325     return test;
 326   }
 327 };
 328 
 329 
 330 
 331 // An interface for accessing/manipulating native leal instruction of form:
 332 //        leal reg, [reg + offset]
 333 
 334 class NativeLoadAddress: public NativeMovRegMem {
 335 #ifdef AMD64
 336   static const bool has_rex = true;
 337   static const int rex_size = 1;
 338 #else
 339   static const bool has_rex = false;
 340   static const int rex_size = 0;
 341 #endif // AMD64
 342  public:
 343   enum Intel_specific_constants {
 344     instruction_prefix_wide             = Assembler::REX_W,
 345     instruction_prefix_wide_extended    = Assembler::REX_WB,
 346     lea_instruction_code                = 0x8D,
 347     mov64_instruction_code              = 0xB8
 348   };
 349 
 350   void verify();
 351   void print ();
 352 
 353   // unit test stuff
 354   static void test() {}
 355 
 356  private:
 357   friend NativeLoadAddress* nativeLoadAddress_at (address address) {
 358     NativeLoadAddress* test = (NativeLoadAddress*)(address - instruction_offset);
 359     #ifdef ASSERT
 360       test->verify();
 361     #endif
 362     return test;
 363   }
 364 };
 365 
 366 // jump rel32off
 367 
 368 class NativeJump: public NativeInstruction {
 369  public:
 370   enum Intel_specific_constants {
 371     instruction_code            = 0xe9,
 372     instruction_size            =    5,
 373     instruction_offset          =    0,
 374     data_offset                 =    1,
 375     next_instruction_offset     =    5
 376   };
 377 
 378   address instruction_address() const       { return addr_at(instruction_offset); }
 379   address next_instruction_address() const  { return addr_at(next_instruction_offset); }
 380   address jump_destination() const          {
 381      address dest = (int_at(data_offset)+next_instruction_address());
 382      // 32bit used to encode unresolved jmp as jmp -1
 383      // 64bit can't produce this so it used jump to self.
 384      // Now 32bit and 64bit use jump to self as the unresolved address
 385      // which the inline cache code (and relocs) know about
 386 
 387      // return -1 if jump to self
 388     dest = (dest == (address) this) ? (address) -1 : dest;
 389     return dest;
 390   }
 391 
 392   void  set_jump_destination(address dest)  {
 393     intptr_t val = dest - next_instruction_address();
 394     if (dest == (address) -1) {
 395       val = -5; // jump to self
 396     }
 397 #ifdef AMD64
 398     assert((labs(val)  & 0xFFFFFFFF00000000) == 0 || dest == (address)-1, "must be 32bit offset or -1");
 399 #endif // AMD64
 400     set_int_at(data_offset, (jint)val);
 401   }
 402 
 403   // Creation
 404   inline friend NativeJump* nativeJump_at(address address);
 405 
 406   void verify();
 407 
 408   // Unit testing stuff
 409   static void test() {}
 410 
 411   // Insertion of native jump instruction
 412   static void insert(address code_pos, address entry);
 413   // MT-safe insertion of native jump at verified method entry
 414   static void check_verified_entry_alignment(address entry, address verified_entry);
 415   static void patch_verified_entry(address entry, address verified_entry, address dest);
 416 };
 417 
 418 inline NativeJump* nativeJump_at(address address) {
 419   NativeJump* jump = (NativeJump*)(address - NativeJump::instruction_offset);
 420 #ifdef ASSERT
 421   jump->verify();
 422 #endif
 423   return jump;
 424 }
 425 
 426 // Handles all kinds of jump on Intel. Long/far, conditional/unconditional
 427 class NativeGeneralJump: public NativeInstruction {
 428  public:
 429   enum Intel_specific_constants {
 430     // Constants does not apply, since the lengths and offsets depends on the actual jump
 431     // used
 432     // Instruction codes:
 433     //   Unconditional jumps: 0xE9    (rel32off), 0xEB (rel8off)
 434     //   Conditional jumps:   0x0F8x  (rel32off), 0x7x (rel8off)
 435     unconditional_long_jump  = 0xe9,
 436     unconditional_short_jump = 0xeb,
 437     instruction_size = 5
 438   };
 439 
 440   address instruction_address() const       { return addr_at(0); }
 441   address jump_destination()    const;
 442 
 443   // Creation
 444   inline friend NativeGeneralJump* nativeGeneralJump_at(address address);
 445 
 446   // Insertion of native general jump instruction
 447   static void insert_unconditional(address code_pos, address entry);
 448   static void replace_mt_safe(address instr_addr, address code_buffer);
 449 
 450   void verify();
 451 };
 452 
 453 inline NativeGeneralJump* nativeGeneralJump_at(address address) {
 454   NativeGeneralJump* jump = (NativeGeneralJump*)(address);
 455   debug_only(jump->verify();)
 456   return jump;
 457 }
 458 
 459 class NativePopReg : public NativeInstruction {
 460  public:
 461   enum Intel_specific_constants {
 462     instruction_code            = 0x58,
 463     instruction_size            =    1,
 464     instruction_offset          =    0,
 465     data_offset                 =    1,
 466     next_instruction_offset     =    1
 467   };
 468 
 469   // Insert a pop instruction
 470   static void insert(address code_pos, Register reg);
 471 };
 472 
 473 
 474 class NativeIllegalInstruction: public NativeInstruction {
 475  public:
 476   enum Intel_specific_constants {
 477     instruction_code            = 0x0B0F,    // Real byte order is: 0x0F, 0x0B
 478     instruction_size            =    2,
 479     instruction_offset          =    0,
 480     next_instruction_offset     =    2
 481   };
 482 
 483   // Insert illegal opcode as specific address
 484   static void insert(address code_pos);
 485 };
 486 
 487 // return instruction that does not pop values of the stack
 488 class NativeReturn: public NativeInstruction {
 489  public:
 490   enum Intel_specific_constants {
 491     instruction_code            = 0xC3,
 492     instruction_size            =    1,
 493     instruction_offset          =    0,
 494     next_instruction_offset     =    1
 495   };
 496 };
 497 
 498 // return instruction that does pop values of the stack
 499 class NativeReturnX: public NativeInstruction {
 500  public:
 501   enum Intel_specific_constants {
 502     instruction_code            = 0xC2,
 503     instruction_size            =    2,
 504     instruction_offset          =    0,
 505     next_instruction_offset     =    2
 506   };
 507 };
 508 
 509 // Simple test vs memory
 510 class NativeTstRegMem: public NativeInstruction {
 511  public:
 512   enum Intel_specific_constants {
 513     instruction_code_memXregl   = 0x85
 514   };
 515 };
 516 
 517 inline bool NativeInstruction::is_illegal()      { return (short)int_at(0) == (short)NativeIllegalInstruction::instruction_code; }
 518 inline bool NativeInstruction::is_call()         { return ubyte_at(0) == NativeCall::instruction_code; }
 519 inline bool NativeInstruction::is_return()       { return ubyte_at(0) == NativeReturn::instruction_code ||
 520                                                           ubyte_at(0) == NativeReturnX::instruction_code; }
 521 inline bool NativeInstruction::is_jump()         { return ubyte_at(0) == NativeJump::instruction_code ||
 522                                                           ubyte_at(0) == 0xEB; /* short jump */ }
 523 inline bool NativeInstruction::is_cond_jump()    { return (int_at(0) & 0xF0FF) == 0x800F /* long jump */ ||
 524                                                           (ubyte_at(0) & 0xF0) == 0x70;  /* short jump */ }
 525 inline bool NativeInstruction::is_safepoint_poll() {
 526 #ifdef AMD64
 527   if ( ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
 528        ubyte_at(1) == 0x05 ) { // 00 rax 101
 529      address fault = addr_at(6) + int_at(2);
 530      return os::is_poll_address(fault);
 531   } else {
 532     return false;
 533   }
 534 #else
 535   return ( ubyte_at(0) == NativeMovRegMem::instruction_code_mem2reg ||
 536            ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl ) &&
 537            (ubyte_at(1)&0xC7) == 0x05 && /* Mod R/M == disp32 */
 538            (os::is_poll_address((address)int_at(2)));
 539 #endif // AMD64
 540 }
 541 
 542 inline bool NativeInstruction::is_mov_literal64() {
 543 #ifdef AMD64
 544   return ((ubyte_at(0) == Assembler::REX_W || ubyte_at(0) == Assembler::REX_WB) &&
 545           (ubyte_at(1) & (0xff ^ NativeMovConstReg::register_mask)) == 0xB8);
 546 #else
 547   return false;
 548 #endif // AMD64
 549 }