Home | History | Annotate | Download | only in linker
      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