Home | History | Annotate | Download | only in compiler
      1 /*
      2  * Copyright (C) 2014 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 "elf_patcher.h"
     18 
     19 #include <vector>
     20 #include <set>
     21 
     22 #include "elf_file.h"
     23 #include "elf_utils.h"
     24 #include "mirror/art_field-inl.h"
     25 #include "mirror/art_method-inl.h"
     26 #include "mirror/array-inl.h"
     27 #include "mirror/class-inl.h"
     28 #include "mirror/class_loader.h"
     29 #include "mirror/dex_cache-inl.h"
     30 #include "mirror/object-inl.h"
     31 #include "mirror/object_array-inl.h"
     32 #include "mirror/string-inl.h"
     33 #include "oat.h"
     34 #include "os.h"
     35 #include "utils.h"
     36 
     37 namespace art {
     38 
     39 bool ElfPatcher::Patch(const CompilerDriver* driver, ElfFile* elf_file,
     40                        const std::string& oat_location,
     41                        ImageAddressCallback cb, void* cb_data,
     42                        std::string* error_msg) {
     43   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
     44   const OatFile* oat_file = class_linker->FindOpenedOatFileFromOatLocation(oat_location);
     45   if (oat_file == nullptr) {
     46     CHECK(Runtime::Current()->IsCompiler());
     47     oat_file = OatFile::Open(oat_location, oat_location, nullptr, nullptr, false, error_msg);
     48     if (oat_file == nullptr) {
     49       *error_msg = StringPrintf("Unable to find or open oat file at '%s': %s", oat_location.c_str(),
     50                                 error_msg->c_str());
     51       return false;
     52     }
     53     CHECK_EQ(class_linker->RegisterOatFile(oat_file), oat_file);
     54   }
     55   return ElfPatcher::Patch(driver, elf_file, oat_file,
     56                            reinterpret_cast<uintptr_t>(oat_file->Begin()), cb, cb_data, error_msg);
     57 }
     58 
     59 bool ElfPatcher::Patch(const CompilerDriver* driver, ElfFile* elf, const OatFile* oat_file,
     60                        uintptr_t oat_data_start, ImageAddressCallback cb, void* cb_data,
     61                        std::string* error_msg) {
     62   Elf32_Shdr* data_sec = elf->FindSectionByName(".rodata");
     63   if (data_sec == nullptr) {
     64     *error_msg = "Unable to find .rodata section and oat header";
     65     return false;
     66   }
     67   OatHeader* oat_header = reinterpret_cast<OatHeader*>(elf->Begin() + data_sec->sh_offset);
     68   if (!oat_header->IsValid()) {
     69     *error_msg = "Oat header was not valid";
     70     return false;
     71   }
     72 
     73   ElfPatcher p(driver, elf, oat_file, oat_header, oat_data_start, cb, cb_data, error_msg);
     74   return p.PatchElf();
     75 }
     76 
     77 mirror::ArtMethod* ElfPatcher::GetTargetMethod(const CompilerDriver::CallPatchInformation* patch) {
     78   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
     79   StackHandleScope<1> hs(Thread::Current());
     80   Handle<mirror::DexCache> dex_cache(
     81       hs.NewHandle(class_linker->FindDexCache(*patch->GetTargetDexFile())));
     82   mirror::ArtMethod* method = class_linker->ResolveMethod(*patch->GetTargetDexFile(),
     83                                                           patch->GetTargetMethodIdx(),
     84                                                           dex_cache,
     85                                                           NullHandle<mirror::ClassLoader>(),
     86                                                           NullHandle<mirror::ArtMethod>(),
     87                                                           patch->GetTargetInvokeType());
     88   CHECK(method != NULL)
     89     << patch->GetTargetDexFile()->GetLocation() << " " << patch->GetTargetMethodIdx();
     90   CHECK(!method->IsRuntimeMethod())
     91     << patch->GetTargetDexFile()->GetLocation() << " " << patch->GetTargetMethodIdx();
     92   CHECK(dex_cache->GetResolvedMethods()->Get(patch->GetTargetMethodIdx()) == method)
     93     << patch->GetTargetDexFile()->GetLocation() << " " << patch->GetReferrerMethodIdx() << " "
     94     << PrettyMethod(dex_cache->GetResolvedMethods()->Get(patch->GetTargetMethodIdx())) << " "
     95     << PrettyMethod(method);
     96   return method;
     97 }
     98 
     99 mirror::String* ElfPatcher::GetTargetString(const CompilerDriver::StringPatchInformation* patch) {
    100   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
    101   StackHandleScope<1> hs(Thread::Current());
    102   Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(patch->GetDexFile())));
    103   mirror::String* string = class_linker->ResolveString(patch->GetDexFile(), patch->GetStringIdx(),
    104                                                        dex_cache);
    105   CHECK(string != nullptr) << patch->GetDexFile().GetLocation() << " " << patch->GetStringIdx();
    106   return string;
    107 }
    108 
    109 mirror::Class* ElfPatcher::GetTargetType(const CompilerDriver::TypePatchInformation* patch) {
    110   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
    111   StackHandleScope<2> hs(Thread::Current());
    112   Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(patch->GetDexFile())));
    113   mirror::Class* klass = class_linker->ResolveType(patch->GetDexFile(), patch->GetTargetTypeIdx(),
    114                                                    dex_cache, NullHandle<mirror::ClassLoader>());
    115   CHECK(klass != NULL)
    116     << patch->GetDexFile().GetLocation() << " " << patch->GetTargetTypeIdx();
    117   CHECK(dex_cache->GetResolvedTypes()->Get(patch->GetTargetTypeIdx()) == klass)
    118     << patch->GetDexFile().GetLocation() << " " << patch->GetReferrerMethodIdx() << " "
    119     << PrettyClass(dex_cache->GetResolvedTypes()->Get(patch->GetTargetTypeIdx())) << " "
    120     << PrettyClass(klass);
    121   return klass;
    122 }
    123 
    124 void ElfPatcher::AddPatch(uintptr_t p) {
    125   if (write_patches_ && patches_set_.find(p) == patches_set_.end()) {
    126     patches_set_.insert(p);
    127     patches_.push_back(p);
    128   }
    129 }
    130 
    131 uint32_t* ElfPatcher::GetPatchLocation(uintptr_t patch_ptr) {
    132   CHECK_GE(patch_ptr, reinterpret_cast<uintptr_t>(oat_file_->Begin()));
    133   CHECK_LE(patch_ptr, reinterpret_cast<uintptr_t>(oat_file_->End()));
    134   uintptr_t off = patch_ptr - reinterpret_cast<uintptr_t>(oat_file_->Begin());
    135   uintptr_t ret = reinterpret_cast<uintptr_t>(oat_header_) + off;
    136 
    137   CHECK_GE(ret, reinterpret_cast<uintptr_t>(elf_file_->Begin()));
    138   CHECK_LT(ret, reinterpret_cast<uintptr_t>(elf_file_->End()));
    139   return reinterpret_cast<uint32_t*>(ret);
    140 }
    141 
    142 void ElfPatcher::SetPatchLocation(const CompilerDriver::PatchInformation* patch, uint32_t value) {
    143   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
    144   const void* quick_oat_code = class_linker->GetQuickOatCodeFor(patch->GetDexFile(),
    145                                                                 patch->GetReferrerClassDefIdx(),
    146                                                                 patch->GetReferrerMethodIdx());
    147   // TODO: make this Thumb2 specific
    148   uint8_t* base = reinterpret_cast<uint8_t*>(reinterpret_cast<uintptr_t>(quick_oat_code) & ~0x1);
    149   uintptr_t patch_ptr = reinterpret_cast<uintptr_t>(base + patch->GetLiteralOffset());
    150   uint32_t* patch_location = GetPatchLocation(patch_ptr);
    151   if (kIsDebugBuild) {
    152     if (patch->IsCall()) {
    153       const CompilerDriver::CallPatchInformation* cpatch = patch->AsCall();
    154       const DexFile::MethodId& id =
    155           cpatch->GetTargetDexFile()->GetMethodId(cpatch->GetTargetMethodIdx());
    156       uint32_t expected = reinterpret_cast<uintptr_t>(&id) & 0xFFFFFFFF;
    157       uint32_t actual = *patch_location;
    158       CHECK(actual == expected || actual == value) << "Patching call failed: " << std::hex
    159           << " actual=" << actual
    160           << " expected=" << expected
    161           << " value=" << value;
    162     }
    163     if (patch->IsType()) {
    164       const CompilerDriver::TypePatchInformation* tpatch = patch->AsType();
    165       const DexFile::TypeId& id = tpatch->GetDexFile().GetTypeId(tpatch->GetTargetTypeIdx());
    166       uint32_t expected = reinterpret_cast<uintptr_t>(&id) & 0xFFFFFFFF;
    167       uint32_t actual = *patch_location;
    168       CHECK(actual == expected || actual == value) << "Patching type failed: " << std::hex
    169           << " actual=" << actual
    170           << " expected=" << expected
    171           << " value=" << value;
    172     }
    173   }
    174   *patch_location = value;
    175   oat_header_->UpdateChecksum(patch_location, sizeof(value));
    176 
    177   if (patch->IsCall() && patch->AsCall()->IsRelative()) {
    178     // We never record relative patches.
    179     return;
    180   }
    181   uintptr_t loc = patch_ptr - (reinterpret_cast<uintptr_t>(oat_file_->Begin()) +
    182                                oat_header_->GetExecutableOffset());
    183   CHECK_GT(patch_ptr, reinterpret_cast<uintptr_t>(oat_file_->Begin()) +
    184                       oat_header_->GetExecutableOffset());
    185   CHECK_LT(loc, oat_file_->Size() - oat_header_->GetExecutableOffset());
    186   AddPatch(loc);
    187 }
    188 
    189 bool ElfPatcher::PatchElf() {
    190   // TODO if we are adding patches the resulting ELF file might have a
    191   // potentially rather large amount of free space where patches might have been
    192   // placed. We should adjust the ELF file to get rid of this excess space.
    193   if (write_patches_) {
    194     patches_.reserve(compiler_driver_->GetCodeToPatch().size() +
    195                      compiler_driver_->GetMethodsToPatch().size() +
    196                      compiler_driver_->GetClassesToPatch().size() +
    197                      compiler_driver_->GetStringsToPatch().size());
    198   }
    199   Thread* self = Thread::Current();
    200   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
    201   const char* old_cause = self->StartAssertNoThreadSuspension("ElfPatcher");
    202 
    203   typedef std::vector<const CompilerDriver::CallPatchInformation*> CallPatches;
    204   const CallPatches& code_to_patch = compiler_driver_->GetCodeToPatch();
    205   for (size_t i = 0; i < code_to_patch.size(); i++) {
    206     const CompilerDriver::CallPatchInformation* patch = code_to_patch[i];
    207 
    208     mirror::ArtMethod* target = GetTargetMethod(patch);
    209     uintptr_t quick_code = reinterpret_cast<uintptr_t>(class_linker->GetQuickOatCodeFor(target));
    210     DCHECK_NE(quick_code, 0U) << PrettyMethod(target);
    211     const OatFile* target_oat =
    212         class_linker->FindOpenedOatDexFileForDexFile(*patch->GetTargetDexFile())->GetOatFile();
    213     // Get where the data actually starts. if target is this oat_file_ it is oat_data_start_,
    214     // otherwise it is wherever target_oat is loaded.
    215     uintptr_t oat_data_addr = GetBaseAddressFor(target_oat);
    216     uintptr_t code_base = reinterpret_cast<uintptr_t>(target_oat->Begin());
    217     uintptr_t code_offset = quick_code - code_base;
    218     bool is_quick_offset = false;
    219     if (quick_code == reinterpret_cast<uintptr_t>(GetQuickToInterpreterBridge())) {
    220       is_quick_offset = true;
    221       code_offset = oat_header_->GetQuickToInterpreterBridgeOffset();
    222     } else if (quick_code ==
    223         reinterpret_cast<uintptr_t>(class_linker->GetQuickGenericJniTrampoline())) {
    224       CHECK(target->IsNative());
    225       is_quick_offset = true;
    226       code_offset = oat_header_->GetQuickGenericJniTrampolineOffset();
    227     }
    228     uintptr_t value;
    229     if (patch->IsRelative()) {
    230       // value to patch is relative to the location being patched
    231       const void* quick_oat_code =
    232         class_linker->GetQuickOatCodeFor(patch->GetDexFile(),
    233                                          patch->GetReferrerClassDefIdx(),
    234                                          patch->GetReferrerMethodIdx());
    235       if (is_quick_offset) {
    236         // If its a quick offset it means that we are doing a relative patch from the class linker
    237         // oat_file to the elf_patcher oat_file so we need to adjust the quick oat code to be the
    238         // one in the output oat_file (ie where it is actually going to be loaded).
    239         quick_code = PointerToLowMemUInt32(reinterpret_cast<void*>(oat_data_addr + code_offset));
    240         quick_oat_code =
    241             reinterpret_cast<const void*>(reinterpret_cast<uintptr_t>(quick_oat_code) +
    242                 oat_data_addr - code_base);
    243       }
    244       uintptr_t base = reinterpret_cast<uintptr_t>(quick_oat_code);
    245       uintptr_t patch_location = base + patch->GetLiteralOffset();
    246       value = quick_code - patch_location + patch->RelativeOffset();
    247     } else if (code_offset != 0) {
    248       value = PointerToLowMemUInt32(reinterpret_cast<void*>(oat_data_addr + code_offset));
    249     } else {
    250       value = 0;
    251     }
    252     SetPatchLocation(patch, value);
    253   }
    254 
    255   const CallPatches& methods_to_patch = compiler_driver_->GetMethodsToPatch();
    256   for (size_t i = 0; i < methods_to_patch.size(); i++) {
    257     const CompilerDriver::CallPatchInformation* patch = methods_to_patch[i];
    258     mirror::ArtMethod* target = GetTargetMethod(patch);
    259     SetPatchLocation(patch, PointerToLowMemUInt32(get_image_address_(cb_data_, target)));
    260   }
    261 
    262   for (const CompilerDriver::TypePatchInformation* patch : compiler_driver_->GetClassesToPatch()) {
    263     mirror::Class* target = GetTargetType(patch);
    264     SetPatchLocation(patch, PointerToLowMemUInt32(get_image_address_(cb_data_, target)));
    265   }
    266   for (const CompilerDriver::StringPatchInformation* patch :
    267       compiler_driver_->GetStringsToPatch()) {
    268     mirror::String* target = GetTargetString(patch);
    269     SetPatchLocation(patch, PointerToLowMemUInt32(get_image_address_(cb_data_, target)));
    270   }
    271 
    272   self->EndAssertNoThreadSuspension(old_cause);
    273 
    274   if (write_patches_) {
    275     return WriteOutPatchData();
    276   }
    277   return true;
    278 }
    279 
    280 bool ElfPatcher::WriteOutPatchData() {
    281   Elf32_Shdr* shdr = elf_file_->FindSectionByName(".oat_patches");
    282   if (shdr != nullptr) {
    283     CHECK_EQ(shdr, elf_file_->FindSectionByType(SHT_OAT_PATCH))
    284         << "Incorrect type for .oat_patches section";
    285     CHECK_LE(patches_.size() * sizeof(uintptr_t), shdr->sh_size)
    286         << "We got more patches than anticipated";
    287     CHECK_LE(reinterpret_cast<uintptr_t>(elf_file_->Begin()) + shdr->sh_offset + shdr->sh_size,
    288               reinterpret_cast<uintptr_t>(elf_file_->End())) << "section is too large";
    289     CHECK(shdr == elf_file_->GetSectionHeader(elf_file_->GetSectionHeaderNum() - 1) ||
    290           shdr->sh_offset + shdr->sh_size <= (shdr + 1)->sh_offset)
    291         << "Section overlaps onto next section";
    292     // It's mmap'd so we can just memcpy.
    293     memcpy(elf_file_->Begin() + shdr->sh_offset, patches_.data(),
    294            patches_.size() * sizeof(uintptr_t));
    295     // TODO We should fill in the newly empty space between the last patch and
    296     // the start of the next section by moving the following sections down if
    297     // possible.
    298     shdr->sh_size = patches_.size() * sizeof(uintptr_t);
    299     return true;
    300   } else {
    301     LOG(ERROR) << "Unable to find section header for SHT_OAT_PATCH";
    302     *error_msg_ = "Unable to find section to write patch information to in ";
    303     *error_msg_ += elf_file_->GetFile().GetPath();
    304     return false;
    305   }
    306 }
    307 
    308 }  // namespace art
    309