1b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko/* 2b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * Copyright (C) 2015 The Android Open Source Project 3b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * 4b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * Licensed under the Apache License, Version 2.0 (the "License"); 5b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * you may not use this file except in compliance with the License. 6b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * You may obtain a copy of the License at 7b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * 8b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * http://www.apache.org/licenses/LICENSE-2.0 9b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * 10b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * Unless required by applicable law or agreed to in writing, software 11b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * distributed under the License is distributed on an "AS IS" BASIS, 12b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * See the License for the specific language governing permissions and 14b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * limitations under the License. 15b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko */ 16b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 17b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko#ifndef ART_COMPILER_LINKER_RELATIVE_PATCHER_H_ 18b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko#define ART_COMPILER_LINKER_RELATIVE_PATCHER_H_ 19b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 20b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko#include <vector> 21b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 22b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko#include "arch/instruction_set.h" 23b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko#include "arch/instruction_set_features.h" 24b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko#include "base/macros.h" 25b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko#include "method_reference.h" 26b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko#include "utils/array_ref.h" 27b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 28b163bb742a099c1808907b513ae39068b63b1692Vladimir Markonamespace art { 29b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 30b163bb742a099c1808907b513ae39068b63b1692Vladimir Markoclass CompiledMethod; 31b163bb742a099c1808907b513ae39068b63b1692Vladimir Markoclass LinkerPatch; 32b163bb742a099c1808907b513ae39068b63b1692Vladimir Markoclass OutputStream; 33b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 34b163bb742a099c1808907b513ae39068b63b1692Vladimir Markonamespace linker { 35b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 36b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko/** 37b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * @class RelativePatcherTargetProvider 38b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * @brief Interface for providing method offsets for relative call targets. 39b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko */ 40b163bb742a099c1808907b513ae39068b63b1692Vladimir Markoclass RelativePatcherTargetProvider { 41b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko public: 42b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko /** 43b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * Find the offset of the target method of a relative call if known. 44b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * 45b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * The process of assigning target method offsets includes calls to the relative patcher's 46b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * ReserveSpace() which in turn can use FindMethodOffset() to determine if a method already 47b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * has an offset assigned and, if so, what's that offset. If the offset has not yet been 48b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * assigned or if it's too far for the particular architecture's relative call, 49b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * ReserveSpace() may need to allocate space for a special dispatch thunk. 50b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * 51b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * @param ref the target method of the relative call. 52b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * @return true in the first element of the pair if the method was found, false otherwise; 53b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * if found, the second element specifies the offset. 54b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko */ 55b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko virtual std::pair<bool, uint32_t> FindMethodOffset(MethodReference ref) = 0; 56b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 57b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko protected: 58b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko virtual ~RelativePatcherTargetProvider() { } 59b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko}; 60b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 61b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko/** 62b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * @class RelativePatcher 63b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko * @brief Interface for architecture-specific link-time patching of PC-relative references. 64b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko */ 65b163bb742a099c1808907b513ae39068b63b1692Vladimir Markoclass RelativePatcher { 66b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko public: 67b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko static std::unique_ptr<RelativePatcher> Create( 68b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko InstructionSet instruction_set, const InstructionSetFeatures* features, 69b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko RelativePatcherTargetProvider* provider); 70b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 71b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko virtual ~RelativePatcher() { } 72b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 73b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko uint32_t CodeAlignmentSize() const { 74b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko return size_code_alignment_; 75b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko } 76b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 77b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko uint32_t RelativeCallThunksSize() const { 78b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko return size_relative_call_thunks_; 79b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko } 80b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 81b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko uint32_t MiscThunksSize() const { 82b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko return size_misc_thunks_; 83b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko } 84b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 8571b0ddf988208c9f77e7d2c1e75066cc3fe20c61Vladimir Marko // Reserve space for thunks if needed before a method, return adjusted offset. 86944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko virtual uint32_t ReserveSpace(uint32_t offset, 87944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko const CompiledMethod* compiled_method, 884d23c9d01b7a609813345eec95167a4dbc4fbae4Vladimir Marko MethodReference method_ref) = 0; 89b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 9071b0ddf988208c9f77e7d2c1e75066cc3fe20c61Vladimir Marko // Reserve space for thunks if needed after the last method, return adjusted offset. 91944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko // The caller may use this method to preemptively force thunk space reservation and 92944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko // then resume reservation for more methods. This is useful when there is a gap in 93944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko // the .text segment, for example when going to the next oat file for multi-image. 9471b0ddf988208c9f77e7d2c1e75066cc3fe20c61Vladimir Marko virtual uint32_t ReserveSpaceEnd(uint32_t offset) = 0; 9571b0ddf988208c9f77e7d2c1e75066cc3fe20c61Vladimir Marko 96944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko // Write relative call thunks if needed, return adjusted offset. Returns 0 on write failure. 97b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko virtual uint32_t WriteThunks(OutputStream* out, uint32_t offset) = 0; 98b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 99b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko // Patch method code. The input displacement is relative to the patched location, 100b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko // the patcher may need to adjust it if the correct base is different. 101944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko virtual void PatchCall(std::vector<uint8_t>* code, 102944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t literal_offset, 103944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t patch_offset, 104944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t target_offset) = 0; 105b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 106b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko // Patch a reference to a dex cache location. 107cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko virtual void PatchPcRelativeReference(std::vector<uint8_t>* code, 108cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko const LinkerPatch& patch, 109cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko uint32_t patch_offset, 110cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko uint32_t target_offset) = 0; 111b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 112b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko protected: 113b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko RelativePatcher() 114b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko : size_code_alignment_(0u), 115b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko size_relative_call_thunks_(0u), 116b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko size_misc_thunks_(0u) { 117b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko } 118b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 119b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko bool WriteCodeAlignment(OutputStream* out, uint32_t aligned_code_delta); 120b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko bool WriteRelCallThunk(OutputStream* out, const ArrayRef<const uint8_t>& thunk); 121b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko bool WriteMiscThunk(OutputStream* out, const ArrayRef<const uint8_t>& thunk); 122b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 123b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko private: 124b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko uint32_t size_code_alignment_; 125b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko uint32_t size_relative_call_thunks_; 126b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko uint32_t size_misc_thunks_; 127b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 128b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko DISALLOW_COPY_AND_ASSIGN(RelativePatcher); 129b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko}; 130b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 131b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko} // namespace linker 132b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko} // namespace art 133b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 134b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko#endif // ART_COMPILER_LINKER_RELATIVE_PATCHER_H_ 135