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#include "linker/relative_patcher.h" 18b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 19b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko#include "linker/arm/relative_patcher_thumb2.h" 20b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko#include "linker/arm64/relative_patcher_arm64.h" 21b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko#include "linker/x86/relative_patcher_x86.h" 22b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko#include "linker/x86_64/relative_patcher_x86_64.h" 23b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko#include "output_stream.h" 24b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 25b163bb742a099c1808907b513ae39068b63b1692Vladimir Markonamespace art { 26b163bb742a099c1808907b513ae39068b63b1692Vladimir Markonamespace linker { 27b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 28b163bb742a099c1808907b513ae39068b63b1692Vladimir Markostd::unique_ptr<RelativePatcher> RelativePatcher::Create( 29b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko InstructionSet instruction_set, const InstructionSetFeatures* features, 30b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko RelativePatcherTargetProvider* provider) { 31b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko class RelativePatcherNone FINAL : public RelativePatcher { 32b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko public: 33b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko RelativePatcherNone() { } 34b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 35b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko uint32_t ReserveSpace(uint32_t offset, 364d23c9d01b7a609813345eec95167a4dbc4fbae4Vladimir Marko const CompiledMethod* compiled_method ATTRIBUTE_UNUSED, 374d23c9d01b7a609813345eec95167a4dbc4fbae4Vladimir Marko MethodReference method_ref ATTRIBUTE_UNUSED) OVERRIDE { 38b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko return offset; // No space reserved; no patches expected. 39b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko } 40b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 4171b0ddf988208c9f77e7d2c1e75066cc3fe20c61Vladimir Marko uint32_t ReserveSpaceEnd(uint32_t offset) OVERRIDE { 4271b0ddf988208c9f77e7d2c1e75066cc3fe20c61Vladimir Marko return offset; // No space reserved; no patches expected. 4371b0ddf988208c9f77e7d2c1e75066cc3fe20c61Vladimir Marko } 4471b0ddf988208c9f77e7d2c1e75066cc3fe20c61Vladimir Marko 45b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko uint32_t WriteThunks(OutputStream* out ATTRIBUTE_UNUSED, uint32_t offset) OVERRIDE { 46b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko return offset; // No thunks added; no patches expected. 47b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko } 48b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 49b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko void PatchCall(std::vector<uint8_t>* code ATTRIBUTE_UNUSED, 50b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko uint32_t literal_offset ATTRIBUTE_UNUSED, 51b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko uint32_t patch_offset ATTRIBUTE_UNUSED, 52b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko uint32_t target_offset ATTRIBUTE_UNUSED) OVERRIDE { 53b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko LOG(FATAL) << "Unexpected relative call patch."; 54b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko } 55b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 56b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko virtual void PatchDexCacheReference(std::vector<uint8_t>* code ATTRIBUTE_UNUSED, 57b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko const LinkerPatch& patch ATTRIBUTE_UNUSED, 58b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko uint32_t patch_offset ATTRIBUTE_UNUSED, 59b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko uint32_t target_offset ATTRIBUTE_UNUSED) { 60b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko LOG(FATAL) << "Unexpected relative dex cache array patch."; 61b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko } 62b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 63b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko private: 64b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko DISALLOW_COPY_AND_ASSIGN(RelativePatcherNone); 65b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko }; 66b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 67b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko switch (instruction_set) { 68b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko case kX86: 69b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko return std::unique_ptr<RelativePatcher>(new X86RelativePatcher()); 70b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko case kX86_64: 71b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko return std::unique_ptr<RelativePatcher>(new X86_64RelativePatcher()); 72b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko case kArm: 73b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko // Fall through: we generate Thumb2 code for "arm". 74b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko case kThumb2: 75b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko return std::unique_ptr<RelativePatcher>(new Thumb2RelativePatcher(provider)); 76b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko case kArm64: 77b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko return std::unique_ptr<RelativePatcher>( 78b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko new Arm64RelativePatcher(provider, features->AsArm64InstructionSetFeatures())); 79b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko default: 80b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko return std::unique_ptr<RelativePatcher>(new RelativePatcherNone); 81b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko } 82b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko} 83b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 84b163bb742a099c1808907b513ae39068b63b1692Vladimir Markobool RelativePatcher::WriteCodeAlignment(OutputStream* out, uint32_t aligned_code_delta) { 85b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko static const uint8_t kPadding[] = { 86b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u 87b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko }; 88b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko DCHECK_LE(aligned_code_delta, sizeof(kPadding)); 89b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko if (UNLIKELY(!out->WriteFully(kPadding, aligned_code_delta))) { 90b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko return false; 91b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko } 92b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko size_code_alignment_ += aligned_code_delta; 93b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko return true; 94b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko} 95b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 96b163bb742a099c1808907b513ae39068b63b1692Vladimir Markobool RelativePatcher::WriteRelCallThunk(OutputStream* out, const ArrayRef<const uint8_t>& thunk) { 97b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko if (UNLIKELY(!out->WriteFully(thunk.data(), thunk.size()))) { 98b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko return false; 99b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko } 100b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko size_relative_call_thunks_ += thunk.size(); 101b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko return true; 102b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko} 103b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 104b163bb742a099c1808907b513ae39068b63b1692Vladimir Markobool RelativePatcher::WriteMiscThunk(OutputStream* out, const ArrayRef<const uint8_t>& thunk) { 105b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko if (UNLIKELY(!out->WriteFully(thunk.data(), thunk.size()))) { 106b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko return false; 107b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko } 108b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko size_misc_thunks_ += thunk.size(); 109b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko return true; 110b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko} 111b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko 112b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko} // namespace linker 113b163bb742a099c1808907b513ae39068b63b1692Vladimir Marko} // namespace art 114