1 /*
   2  * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2014, Red Hat Inc. All rights reserved.
   4  * Copyright (c) 2015, Linaro Ltd. All rights reserved.
   5  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   6  *
   7  * This code is free software; you can redistribute it and/or modify it
   8  * under the terms of the GNU General Public License version 2 only, as
   9  * published by the Free Software Foundation.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  *
  25  */
  26 
  27 #include "precompiled.hpp"
  28 #include "asm/macroAssembler.hpp"
  29 #include "code/relocInfo.hpp"
  30 #include "nativeInst_aarch32.hpp"
  31 #include "oops/oop.inline.hpp"
  32 #include "runtime/safepoint.hpp"
  33 
  34 void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) {
  35 
  36   if (NativeFarLdr::is_at(addr())) {
  37     NativeFarLdr *nal = NativeFarLdr::from(addr());
  38     address const_addr = NULL;
  39     switch(type()) {
  40     case relocInfo::oop_type:
  41       const_addr = (address)code()->oop_addr_at(((oop_Relocation *)this)->oop_index());
  42       assert(*(address*)const_addr == x, "error in memory relocation");
  43       break;
  44     case relocInfo::section_word_type:
  45       const_addr = ((section_word_Relocation*)this)->target();
  46       assert(const_addr == x, "error in memory relocation");
  47       break;
  48     default:
  49       ShouldNotReachHere();
  50     }
  51     assert(const_addr, "should not be NULL");
  52     if (verify_only) {
  53       guarantee(nal->data_addr() == (intptr_t*) const_addr, "instructions must match");
  54       return;
  55     }
  56     nal->set_data_addr((intptr_t*) const_addr);
  57   } else {
  58     NativeMovConstReg *nm = NativeMovConstReg::from(addr());
  59     if (verify_only) {
  60       guarantee(nm->data() == (intptr_t) x, "instructions must match");
  61       return;
  62     }
  63     nm->set_data((intptr_t) x);
  64   }
  65 }
  66 
  67 address Relocation::pd_call_destination(address orig_addr) {
  68   intptr_t adj = 0;
  69   if (orig_addr != NULL) {
  70     // We just moved this call instruction from orig_addr to addr().
  71     // This means its target will appear to have grown by addr() - orig_addr.
  72     adj = -( addr() - orig_addr );
  73   }
  74 
  75   NativeInstruction *ni = NativeInstruction::from(addr());
  76 
  77   // Checking from shortest encoding size to longets,
  78   // to avoid access beyond CodeCache boundary
  79   if (NativeImmCall::is_at(addr())) {
  80     return NativeImmCall::from(addr())->destination() + adj;
  81   } else if (NativeImmJump::is_at(addr())) {
  82     return NativeImmJump::from(addr())->destination() + adj;
  83   } else if (NativeCall::is_at(addr())) {
  84     return NativeCall::from(addr())->destination();
  85   } else if (NativeJump::is_at(addr())) {
  86     return NativeJump::from(addr())->jump_destination();
  87   }
  88 
  89   ShouldNotReachHere();
  90   return NULL;
  91 }
  92 
  93 void Relocation::pd_set_call_destination(address x) {
  94   assert(addr() != x, "call instruction in an infinite loop"); // FIXME what's wrong to _generate_ loop?
  95   NativeInstruction *ni = NativeInstruction::from(addr());
  96 
  97   // Checking from shortest encoding size to longets,
  98   // to avoid access beyond CodeCache boundary
  99   if (NativeImmCall::is_at(addr())) {
 100     NativeImmCall::from(addr())->set_destination(x);
 101   } else if (NativeImmJump::is_at(addr())) {
 102     NativeImmJump::from(addr())->set_destination(x);
 103   } else if (NativeCall::is_at(addr())) {
 104     NativeCall::from(addr())->set_destination(x);
 105   } else if (NativeJump::is_at(addr())) {
 106     NativeJump::from(addr())->set_jump_destination(x);
 107   } else {
 108     ShouldNotReachHere();
 109   }
 110 
 111   assert(pd_call_destination(addr()) == x, "fail in reloc");
 112 }
 113 
 114 address* Relocation::pd_address_in_code() {
 115   ShouldNotCallThis();
 116   return NULL;
 117 }
 118 
 119 address Relocation::pd_get_address_from_code() {
 120   ShouldNotCallThis();
 121   return NULL;
 122 }
 123 
 124 void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
 125   NativeInstruction *ni = NativeInstruction::from(addr());
 126   if (ni->is_mov_const_reg()) {
 127     address old_addr = old_addr_for(addr(), src, dest);
 128     NativeMovConstReg *nm2 = NativeMovConstReg::from(old_addr);
 129     NativeMovConstReg::from(addr())->set_data(nm2->data());
 130   } else {
 131 #if 0
 132     warning("TODO: poll_Relocation::fix_relocation_after_move: "
 133       "ensure relocating does nothing on relative instruction");
 134 #endif
 135   }
 136 }
 137 
 138 void metadata_Relocation::pd_fix_value(address x) {
 139   if (NativeFarLdr::is_at(addr())) {
 140     NativeFarLdr *nal = NativeFarLdr::from(addr());
 141     address const_addr = (address)code()->metadata_addr_at(((metadata_Relocation *)this)->metadata_index());
 142     nal->set_data_addr((intptr_t*) const_addr);
 143   }
 144 }