1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "linker/relative_patcher.h" 18 19#ifdef ART_ENABLE_CODEGEN_arm 20#include "linker/arm/relative_patcher_thumb2.h" 21#endif 22#ifdef ART_ENABLE_CODEGEN_arm64 23#include "linker/arm64/relative_patcher_arm64.h" 24#endif 25#ifdef ART_ENABLE_CODEGEN_x86 26#include "linker/x86/relative_patcher_x86.h" 27#endif 28#ifdef ART_ENABLE_CODEGEN_x86_64 29#include "linker/x86_64/relative_patcher_x86_64.h" 30#endif 31#include "output_stream.h" 32 33namespace art { 34namespace linker { 35 36std::unique_ptr<RelativePatcher> RelativePatcher::Create( 37 InstructionSet instruction_set, 38 const InstructionSetFeatures* features, 39 RelativePatcherTargetProvider* provider) { 40 class RelativePatcherNone FINAL : public RelativePatcher { 41 public: 42 RelativePatcherNone() { } 43 44 uint32_t ReserveSpace(uint32_t offset, 45 const CompiledMethod* compiled_method ATTRIBUTE_UNUSED, 46 MethodReference method_ref ATTRIBUTE_UNUSED) OVERRIDE { 47 return offset; // No space reserved; no patches expected. 48 } 49 50 uint32_t ReserveSpaceEnd(uint32_t offset) OVERRIDE { 51 return offset; // No space reserved; no patches expected. 52 } 53 54 uint32_t WriteThunks(OutputStream* out ATTRIBUTE_UNUSED, uint32_t offset) OVERRIDE { 55 return offset; // No thunks added; no patches expected. 56 } 57 58 void PatchCall(std::vector<uint8_t>* code ATTRIBUTE_UNUSED, 59 uint32_t literal_offset ATTRIBUTE_UNUSED, 60 uint32_t patch_offset ATTRIBUTE_UNUSED, 61 uint32_t target_offset ATTRIBUTE_UNUSED) OVERRIDE { 62 LOG(FATAL) << "Unexpected relative call patch."; 63 } 64 65 void PatchPcRelativeReference(std::vector<uint8_t>* code ATTRIBUTE_UNUSED, 66 const LinkerPatch& patch ATTRIBUTE_UNUSED, 67 uint32_t patch_offset ATTRIBUTE_UNUSED, 68 uint32_t target_offset ATTRIBUTE_UNUSED) OVERRIDE { 69 LOG(FATAL) << "Unexpected relative dex cache array patch."; 70 } 71 72 private: 73 DISALLOW_COPY_AND_ASSIGN(RelativePatcherNone); 74 }; 75 76 UNUSED(features); 77 UNUSED(provider); 78 switch (instruction_set) { 79#ifdef ART_ENABLE_CODEGEN_x86 80 case kX86: 81 return std::unique_ptr<RelativePatcher>(new X86RelativePatcher()); 82#endif 83#ifdef ART_ENABLE_CODEGEN_x86_64 84 case kX86_64: 85 return std::unique_ptr<RelativePatcher>(new X86_64RelativePatcher()); 86#endif 87#ifdef ART_ENABLE_CODEGEN_arm 88 case kArm: 89 // Fall through: we generate Thumb2 code for "arm". 90 case kThumb2: 91 return std::unique_ptr<RelativePatcher>(new Thumb2RelativePatcher(provider)); 92#endif 93#ifdef ART_ENABLE_CODEGEN_arm64 94 case kArm64: 95 return std::unique_ptr<RelativePatcher>( 96 new Arm64RelativePatcher(provider, features->AsArm64InstructionSetFeatures())); 97#endif 98 default: 99 return std::unique_ptr<RelativePatcher>(new RelativePatcherNone); 100 } 101} 102 103bool RelativePatcher::WriteCodeAlignment(OutputStream* out, uint32_t aligned_code_delta) { 104 static const uint8_t kPadding[] = { 105 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u 106 }; 107 DCHECK_LE(aligned_code_delta, sizeof(kPadding)); 108 if (UNLIKELY(!out->WriteFully(kPadding, aligned_code_delta))) { 109 return false; 110 } 111 size_code_alignment_ += aligned_code_delta; 112 return true; 113} 114 115bool RelativePatcher::WriteRelCallThunk(OutputStream* out, const ArrayRef<const uint8_t>& thunk) { 116 if (UNLIKELY(!out->WriteFully(thunk.data(), thunk.size()))) { 117 return false; 118 } 119 size_relative_call_thunks_ += thunk.size(); 120 return true; 121} 122 123bool RelativePatcher::WriteMiscThunk(OutputStream* out, const ArrayRef<const uint8_t>& thunk) { 124 if (UNLIKELY(!out->WriteFully(thunk.data(), thunk.size()))) { 125 return false; 126 } 127 size_misc_thunks_ += thunk.size(); 128 return true; 129} 130 131} // namespace linker 132} // namespace art 133