1 /*
   2  * Copyright 1998-2005 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  20  * CA 95054 USA or visit www.sun.com if you need additional information or
  21  * have any questions.
  22  *
  23  */
  24 
  25 # include "incls/_precompiled.incl"
  26 # include "incls/_relocInfo_x86.cpp.incl"
  27 
  28 
  29 void Relocation::pd_set_data_value(address x, intptr_t o) {
  30 #ifdef AMD64
  31   x += o;
  32   typedef Assembler::WhichOperand WhichOperand;
  33   WhichOperand which = (WhichOperand) format(); // that is, disp32 or imm64, call32
  34   assert(which == Assembler::disp32_operand ||
  35          which == Assembler::imm64_operand, "format unpacks ok");
  36   if (which == Assembler::imm64_operand) {
  37     *pd_address_in_code() = x;
  38   } else {
  39     // Note:  Use runtime_call_type relocations for call32_operand.
  40     address ip = addr();
  41     address disp = Assembler::locate_operand(ip, which);
  42     address next_ip = Assembler::locate_next_instruction(ip);
  43     *(int32_t*) disp = x - next_ip;
  44   }
  45 #else
  46   *pd_address_in_code() = x + o;
  47 #endif // AMD64
  48 }
  49 
  50 
  51 address Relocation::pd_call_destination(address orig_addr) {
  52   intptr_t adj = 0;
  53   if (orig_addr != NULL) {
  54     // We just moved this call instruction from orig_addr to addr().
  55     // This means its target will appear to have grown by addr() - orig_addr.
  56     adj = -( addr() - orig_addr );
  57   }
  58   NativeInstruction* ni = nativeInstruction_at(addr());
  59   if (ni->is_call()) {
  60     return nativeCall_at(addr())->destination() + adj;
  61   } else if (ni->is_jump()) {
  62     return nativeJump_at(addr())->jump_destination() + adj;
  63   } else if (ni->is_cond_jump()) {
  64     return nativeGeneralJump_at(addr())->jump_destination() + adj;
  65   } else if (ni->is_mov_literal64()) {
  66     return (address) ((NativeMovConstReg*)ni)->data();
  67   } else {
  68     ShouldNotReachHere();
  69     return NULL;
  70   }
  71 }
  72 
  73 
  74 void Relocation::pd_set_call_destination(address x) {
  75   NativeInstruction* ni = nativeInstruction_at(addr());
  76   if (ni->is_call()) {
  77     nativeCall_at(addr())->set_destination(x);
  78   } else if (ni->is_jump()) {
  79     NativeJump* nj = nativeJump_at(addr());
  80 #ifdef AMD64
  81     if (nj->jump_destination() == (address) -1) {
  82       x = (address) -1; // retain jump to self
  83     }
  84 #endif // AMD64
  85     nj->set_jump_destination(x);
  86   } else if (ni->is_cond_jump()) {
  87     // %%%% kludge this, for now, until we get a jump_destination method
  88     address old_dest = nativeGeneralJump_at(addr())->jump_destination();
  89     address disp = Assembler::locate_operand(addr(), Assembler::call32_operand);
  90     *(jint*)disp += (x - old_dest);
  91   } else if (ni->is_mov_literal64()) {
  92     ((NativeMovConstReg*)ni)->set_data((intptr_t)x);
  93   } else {
  94     ShouldNotReachHere();
  95   }
  96 }
  97 
  98 
  99 address* Relocation::pd_address_in_code() {
 100   // All embedded Intel addresses are stored in 32-bit words.
 101   // Since the addr points at the start of the instruction,
 102   // we must parse the instruction a bit to find the embedded word.
 103   assert(is_data(), "must be a DataRelocation");
 104   typedef Assembler::WhichOperand WhichOperand;
 105   WhichOperand which = (WhichOperand) format(); // that is, disp32 or imm64/imm32
 106 #ifdef AMD64
 107   assert(which == Assembler::disp32_operand ||
 108          which == Assembler::call32_operand ||
 109          which == Assembler::imm64_operand, "format unpacks ok");
 110   if (which != Assembler::imm64_operand) {
 111     // The "address" in the code is a displacement can't return it as
 112     // and address* since it is really a jint*
 113     ShouldNotReachHere();
 114     return NULL;
 115   }
 116 #else
 117   assert(which == Assembler::disp32_operand || which == Assembler::imm32_operand, "format unpacks ok");
 118 #endif // AMD64
 119   return (address*) Assembler::locate_operand(addr(), which);
 120 }
 121 
 122 
 123 address Relocation::pd_get_address_from_code() {
 124 #ifdef AMD64
 125   // All embedded Intel addresses are stored in 32-bit words.
 126   // Since the addr points at the start of the instruction,
 127   // we must parse the instruction a bit to find the embedded word.
 128   assert(is_data(), "must be a DataRelocation");
 129   typedef Assembler::WhichOperand WhichOperand;
 130   WhichOperand which = (WhichOperand) format(); // that is, disp32 or imm64/imm32
 131   assert(which == Assembler::disp32_operand ||
 132          which == Assembler::call32_operand ||
 133          which == Assembler::imm64_operand, "format unpacks ok");
 134   if (which != Assembler::imm64_operand) {
 135     address ip = addr();
 136     address disp = Assembler::locate_operand(ip, which);
 137     address next_ip = Assembler::locate_next_instruction(ip);
 138     address a = next_ip + *(int32_t*) disp;
 139     return a;
 140   }
 141 #endif // AMD64
 142   return *pd_address_in_code();
 143 }
 144 
 145 int Relocation::pd_breakpoint_size() {
 146   // minimum breakpoint size, in short words
 147   return NativeIllegalInstruction::instruction_size / sizeof(short);
 148 }
 149 
 150 void Relocation::pd_swap_in_breakpoint(address x, short* instrs, int instrlen) {
 151   Untested("pd_swap_in_breakpoint");
 152   if (instrs != NULL) {
 153     assert(instrlen * sizeof(short) == NativeIllegalInstruction::instruction_size, "enough instrlen in reloc. data");
 154     for (int i = 0; i < instrlen; i++) {
 155       instrs[i] = ((short*)x)[i];
 156     }
 157   }
 158   NativeIllegalInstruction::insert(x);
 159 }
 160 
 161 
 162 void Relocation::pd_swap_out_breakpoint(address x, short* instrs, int instrlen) {
 163   Untested("pd_swap_out_breakpoint");
 164   assert(NativeIllegalInstruction::instruction_size == sizeof(short), "right address unit for update");
 165   NativeInstruction* ni = nativeInstruction_at(x);
 166   *(short*)ni->addr_at(0) = instrs[0];
 167 }