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 #include "debug/method_debug_info.h" 20 #ifdef ART_ENABLE_CODEGEN_arm 21 #include "linker/arm/relative_patcher_thumb2.h" 22 #endif 23 #ifdef ART_ENABLE_CODEGEN_arm64 24 #include "linker/arm64/relative_patcher_arm64.h" 25 #endif 26 #ifdef ART_ENABLE_CODEGEN_mips 27 #include "linker/mips/relative_patcher_mips.h" 28 #endif 29 #ifdef ART_ENABLE_CODEGEN_mips64 30 #include "linker/mips64/relative_patcher_mips64.h" 31 #endif 32 #ifdef ART_ENABLE_CODEGEN_x86 33 #include "linker/x86/relative_patcher_x86.h" 34 #endif 35 #ifdef ART_ENABLE_CODEGEN_x86_64 36 #include "linker/x86_64/relative_patcher_x86_64.h" 37 #endif 38 #include "stream/output_stream.h" 39 40 namespace art { 41 namespace linker { 42 43 std::unique_ptr<RelativePatcher> RelativePatcher::Create( 44 InstructionSet instruction_set, 45 const InstructionSetFeatures* features, 46 RelativePatcherThunkProvider* thunk_provider, 47 RelativePatcherTargetProvider* target_provider) { 48 class RelativePatcherNone final : public RelativePatcher { 49 public: 50 RelativePatcherNone() { } 51 52 uint32_t ReserveSpace(uint32_t offset, 53 const CompiledMethod* compiled_method ATTRIBUTE_UNUSED, 54 MethodReference method_ref ATTRIBUTE_UNUSED) override { 55 return offset; // No space reserved; no patches expected. 56 } 57 58 uint32_t ReserveSpaceEnd(uint32_t offset) override { 59 return offset; // No space reserved; no patches expected. 60 } 61 62 uint32_t WriteThunks(OutputStream* out ATTRIBUTE_UNUSED, uint32_t offset) override { 63 return offset; // No thunks added; no patches expected. 64 } 65 66 void PatchCall(std::vector<uint8_t>* code ATTRIBUTE_UNUSED, 67 uint32_t literal_offset ATTRIBUTE_UNUSED, 68 uint32_t patch_offset ATTRIBUTE_UNUSED, 69 uint32_t target_offset ATTRIBUTE_UNUSED) override { 70 LOG(FATAL) << "Unexpected relative call patch."; 71 } 72 73 void PatchPcRelativeReference(std::vector<uint8_t>* code ATTRIBUTE_UNUSED, 74 const LinkerPatch& patch ATTRIBUTE_UNUSED, 75 uint32_t patch_offset ATTRIBUTE_UNUSED, 76 uint32_t target_offset ATTRIBUTE_UNUSED) override { 77 LOG(FATAL) << "Unexpected relative dex cache array patch."; 78 } 79 80 void PatchBakerReadBarrierBranch(std::vector<uint8_t>* code ATTRIBUTE_UNUSED, 81 const LinkerPatch& patch ATTRIBUTE_UNUSED, 82 uint32_t patch_offset ATTRIBUTE_UNUSED) override { 83 LOG(FATAL) << "Unexpected baker read barrier branch patch."; 84 } 85 86 std::vector<debug::MethodDebugInfo> GenerateThunkDebugInfo( 87 uint32_t executable_offset ATTRIBUTE_UNUSED) override { 88 return std::vector<debug::MethodDebugInfo>(); // No thunks added. 89 } 90 91 private: 92 DISALLOW_COPY_AND_ASSIGN(RelativePatcherNone); 93 }; 94 95 UNUSED(features); 96 UNUSED(thunk_provider); 97 UNUSED(target_provider); 98 switch (instruction_set) { 99 #ifdef ART_ENABLE_CODEGEN_x86 100 case InstructionSet::kX86: 101 return std::unique_ptr<RelativePatcher>(new X86RelativePatcher()); 102 #endif 103 #ifdef ART_ENABLE_CODEGEN_x86_64 104 case InstructionSet::kX86_64: 105 return std::unique_ptr<RelativePatcher>(new X86_64RelativePatcher()); 106 #endif 107 #ifdef ART_ENABLE_CODEGEN_arm 108 case InstructionSet::kArm: 109 // Fall through: we generate Thumb2 code for "arm". 110 case InstructionSet::kThumb2: 111 return std::unique_ptr<RelativePatcher>( 112 new Thumb2RelativePatcher(thunk_provider, target_provider)); 113 #endif 114 #ifdef ART_ENABLE_CODEGEN_arm64 115 case InstructionSet::kArm64: 116 return std::unique_ptr<RelativePatcher>( 117 new Arm64RelativePatcher(thunk_provider, 118 target_provider, 119 features->AsArm64InstructionSetFeatures())); 120 #endif 121 #ifdef ART_ENABLE_CODEGEN_mips 122 case InstructionSet::kMips: 123 return std::unique_ptr<RelativePatcher>( 124 new MipsRelativePatcher(features->AsMipsInstructionSetFeatures())); 125 #endif 126 #ifdef ART_ENABLE_CODEGEN_mips64 127 case InstructionSet::kMips64: 128 return std::unique_ptr<RelativePatcher>(new Mips64RelativePatcher()); 129 #endif 130 default: 131 return std::unique_ptr<RelativePatcher>(new RelativePatcherNone); 132 } 133 } 134 135 bool RelativePatcher::WriteCodeAlignment(OutputStream* out, uint32_t aligned_code_delta) { 136 static const uint8_t kPadding[] = { 137 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u 138 }; 139 DCHECK_LE(aligned_code_delta, sizeof(kPadding)); 140 if (UNLIKELY(!out->WriteFully(kPadding, aligned_code_delta))) { 141 return false; 142 } 143 size_code_alignment_ += aligned_code_delta; 144 return true; 145 } 146 147 bool RelativePatcher::WriteThunk(OutputStream* out, const ArrayRef<const uint8_t>& thunk) { 148 if (UNLIKELY(!out->WriteFully(thunk.data(), thunk.size()))) { 149 return false; 150 } 151 size_relative_call_thunks_ += thunk.size(); 152 return true; 153 } 154 155 bool RelativePatcher::WriteMiscThunk(OutputStream* out, const ArrayRef<const uint8_t>& thunk) { 156 if (UNLIKELY(!out->WriteFully(thunk.data(), thunk.size()))) { 157 return false; 158 } 159 size_misc_thunks_ += thunk.size(); 160 return true; 161 } 162 163 } // namespace linker 164 } // namespace art 165