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