1/*
2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2016 SAP SE. All rights reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26#include "precompiled.hpp"
27#include "asm/assembler.inline.hpp"
28#include "code/relocInfo.hpp"
29#include "nativeInst_s390.hpp"
30#include "oops/oop.inline.hpp"
31#include "runtime/safepoint.hpp"
32
33void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) {
34  // we don't support splitting of relocations, so o must be zero:
35  assert(o == 0, "tried to split relocations");
36  if (!verify_only) {
37    switch (format()) {
38      case relocInfo::uncompressed_format:
39        nativeMovConstReg_at(addr())->set_data_plain(((intptr_t)x) + o, code());
40        break;
41      case relocInfo::compressed_format:
42        if (type() == relocInfo::metadata_type)
43          nativeMovConstReg_at(addr())->set_narrow_klass(((intptr_t)x) + o);
44        else if (type() == relocInfo::oop_type)
45          nativeMovConstReg_at(addr())->set_narrow_oop(((intptr_t)x) + o);
46        else
47          guarantee(false, "bad relocInfo type for relocInfo::narrow_oop_format");
48        break;
49      case relocInfo::pcrel_addr_format:  // patch target location
50        nativeMovConstReg_at(addr())->set_pcrel_addr(((intptr_t)x) + o, code());
51        break;
52      case relocInfo::pcrel_data_format:  // patch data at target location
53        nativeMovConstReg_at(addr())->set_pcrel_data(((intptr_t)x) + o, code());
54        break;
55      default:
56        assert(false, "not a valid relocInfo format");
57        break;
58    }
59  } else {
60    // TODO: Reading of narrow oops out of code stream is not implemented
61    // (see nativeMovConstReg::data()). Implement this if you want to verify.
62    // assert(x == (address) nativeMovConstReg_at(addr())->data(), "Instructions must match");
63    switch (format()) {
64      case relocInfo::uncompressed_format:
65        break;
66      case relocInfo::compressed_format:
67        break;
68      case relocInfo::pcrel_addr_format:
69        break;
70      case relocInfo::pcrel_data_format:
71        break;
72      default:
73        assert(false, "not a valid relocInfo format");
74        break;
75    }
76  }
77}
78
79address Relocation::pd_call_destination(address orig_addr) {
80  address   inst_addr = addr();
81
82  if (NativeFarCall::is_far_call_at(inst_addr)) {
83    if (!ShortenBranches) {
84      if (MacroAssembler::is_call_far_pcrelative(inst_addr)) {
85        address a1 = MacroAssembler::get_target_addr_pcrel(orig_addr+MacroAssembler::nop_size());
86#ifdef ASSERT
87        address a2 = MacroAssembler::get_target_addr_pcrel(inst_addr+MacroAssembler::nop_size());
88        address a3 = nativeFarCall_at(orig_addr)->destination();
89        address a4 = nativeFarCall_at(inst_addr)->destination();
90        if ((a1 != a3) || (a2 != a4)) {
91          unsigned int range = 128;
92          Assembler::dump_code_range(tty, inst_addr, range, "pc-relative call w/o ShortenBranches?");
93          Assembler::dump_code_range(tty, orig_addr, range, "pc-relative call w/o ShortenBranches?");
94          assert(false, "pc-relative call w/o ShortenBranches?");
95        }
96#endif
97        return a1;
98      }
99      return (address)(-1);
100    }
101    NativeFarCall* call;
102    if (orig_addr == NULL) {
103      call = nativeFarCall_at(inst_addr);
104    } else {
105      // must access location (in CP) where destination is stored in unmoved code, because load from CP is pc-relative
106      call = nativeFarCall_at(orig_addr);
107    }
108    return call->destination();
109  }
110
111  if (NativeCall::is_call_at(inst_addr)) {
112    NativeCall* call = nativeCall_at(inst_addr);
113    if (call->is_pcrelative()) {
114      intptr_t off = inst_addr - orig_addr;
115      return (address) (call->destination()-off);
116    }
117  }
118
119  return (address) nativeMovConstReg_at(inst_addr)->data();
120}
121
122void Relocation::pd_set_call_destination(address x) {
123  address inst_addr = addr();
124
125  if (NativeFarCall::is_far_call_at(inst_addr)) {
126    if (!ShortenBranches) {
127      if (MacroAssembler::is_call_far_pcrelative(inst_addr)) {
128        address a1 = MacroAssembler::get_target_addr_pcrel(inst_addr+MacroAssembler::nop_size());
129#ifdef ASSERT
130        address a3 = nativeFarCall_at(inst_addr)->destination();
131        if (a1 != a3) {
132          unsigned int range = 128;
133          Assembler::dump_code_range(tty, inst_addr, range, "pc-relative call w/o ShortenBranches?");
134          assert(false, "pc-relative call w/o ShortenBranches?");
135        }
136#endif
137        nativeFarCall_at(inst_addr)->set_destination(x, 0);
138        return;
139      }
140      assert(x == (address)-1, "consistency check");
141      return;
142    }
143    int toc_offset = -1;
144    if (type() == relocInfo::runtime_call_w_cp_type) {
145      toc_offset = ((runtime_call_w_cp_Relocation *)this)->get_constant_pool_offset();
146    }
147    if (toc_offset>=0) {
148      NativeFarCall* call = nativeFarCall_at(inst_addr);
149      call->set_destination(x, toc_offset);
150      return;
151    }
152  }
153
154  if (NativeCall::is_call_at(inst_addr)) {
155    NativeCall* call = nativeCall_at(inst_addr);
156    if (call->is_pcrelative()) {
157      call->set_destination_mt_safe(x);
158      return;
159    }
160  }
161
162  // constant is absolute, must use x
163  nativeMovConstReg_at(inst_addr)->set_data(((intptr_t)x));
164}
165
166
167// store the new target address into an oop_Relocation cell, if any
168// return indication if update happened.
169bool relocInfo::update_oop_pool(address begin, address end, address newTarget, CodeBlob* cb) {
170
171  //  Try to find the CodeBlob, if not given by caller
172  if (cb == NULL) cb = CodeCache::find_blob(begin);
173#ifdef ASSERT
174  else
175    assert(cb == CodeCache::find_blob(begin), "consistency");
176#endif
177
178  //  'RelocIterator' requires an nmethod
179  nmethod*  nm = cb ? cb->as_nmethod_or_null() : NULL;
180  if (nm != NULL) {
181    RelocIterator iter(nm, begin, end);
182    oop* oop_addr = NULL;
183    Metadata** metadata_addr = NULL;
184    while (iter.next()) {
185      if (iter.type() == relocInfo::oop_type) {
186        oop_Relocation *r = iter.oop_reloc();
187        if (oop_addr == NULL) {
188          oop_addr = r->oop_addr();
189          *oop_addr = (oop)newTarget;
190        } else {
191          assert(oop_addr == r->oop_addr(), "must be only one set-oop here");
192        }
193      }
194      if (iter.type() == relocInfo::metadata_type) {
195        metadata_Relocation *r = iter.metadata_reloc();
196        if (metadata_addr == NULL) {
197          metadata_addr = r->metadata_addr();
198          *metadata_addr = (Metadata*)newTarget;
199        } else {
200          assert(metadata_addr == r->metadata_addr(), "must be only one set-metadata here");
201        }
202      }
203    }
204    return oop_addr || metadata_addr;
205  }
206  return false;
207}
208
209
210address* Relocation::pd_address_in_code() {
211 ShouldNotReachHere();
212 return 0;
213}
214
215address Relocation::pd_get_address_from_code() {
216   return  (address) (nativeMovConstReg_at(addr())->data());
217}
218
219void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
220}
221
222void metadata_Relocation::pd_fix_value(address x) {
223}
224