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 33 namespace art { 34 namespace linker { 35 36 std::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 103 bool 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 115 bool 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 123 bool 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