153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light/* 253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light * Copyright (C) 2014 The Android Open Source Project 353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light * 453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light * Licensed under the Apache License, Version 2.0 (the "License"); 553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light * you may not use this file except in compliance with the License. 653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light * You may obtain a copy of the License at 753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light * 853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light * http://www.apache.org/licenses/LICENSE-2.0 953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light * 1053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light * Unless required by applicable law or agreed to in writing, software 1153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light * distributed under the License is distributed on an "AS IS" BASIS, 1253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light * See the License for the specific language governing permissions and 1453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light * limitations under the License. 1553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light */ 1653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "patchoat.h" 1753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 1853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include <stdio.h> 1953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include <stdlib.h> 20a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light#include <sys/file.h> 2153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include <sys/stat.h> 22a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light#include <unistd.h> 2353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 2453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include <string> 2553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include <vector> 2653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 27c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier#include "art_field-inl.h" 28e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier#include "art_method-inl.h" 29c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers#include "base/dumpable.h" 30a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light#include "base/scoped_flock.h" 3153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "base/stringpiece.h" 3253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "base/stringprintf.h" 33d4c4d953035d4418126d36517e402f411d6a87f3Ian Rogers#include "base/unix_file/fd_file.h" 3453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "elf_utils.h" 3553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "elf_file.h" 3662d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen#include "elf_file_impl.h" 37e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers#include "gc/space/image_space.h" 384a26f17b055cadc949c3e9fdfa637fe5656339d9Mathieu Chartier#include "image-inl.h" 39e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier#include "mirror/abstract_method.h" 4053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "mirror/object-inl.h" 41e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier#include "mirror/method.h" 4253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "mirror/reference.h" 4353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "noop_compiler_callbacks.h" 4453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "offsets.h" 4553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "os.h" 4653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "runtime.h" 4753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "scoped_thread_state_change.h" 4853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "thread.h" 4953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "utils.h" 5053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 5153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightnamespace art { 5253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 53cf4bf386ef3f527825c70e01130b9276da4f786aAlex Lightstatic bool LocationToFilename(const std::string& location, InstructionSet isa, 54cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light std::string* filename) { 55cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light bool has_system = false; 56cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light bool has_cache = false; 57cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light // image_location = /system/framework/boot.art 5846774767fcf7780d1455e755729198648d08742eIgor Murashkin // system_image_filename = /system/framework/<image_isa>/boot.art 59cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light std::string system_filename(GetSystemImageFilename(location.c_str(), isa)); 60cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light if (OS::FileExists(system_filename.c_str())) { 61cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light has_system = true; 62cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } 63cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light 64cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light bool have_android_data = false; 65cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light bool dalvik_cache_exists = false; 663c13a794845e0cf7887e33b2ec20de7e6ba85f8fAndreas Gampe bool is_global_cache = false; 67cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light std::string dalvik_cache; 68cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light GetDalvikCache(GetInstructionSetString(isa), false, &dalvik_cache, 693c13a794845e0cf7887e33b2ec20de7e6ba85f8fAndreas Gampe &have_android_data, &dalvik_cache_exists, &is_global_cache); 70cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light 71cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light std::string cache_filename; 72cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light if (have_android_data && dalvik_cache_exists) { 73cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light // Always set output location even if it does not exist, 74cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light // so that the caller knows where to create the image. 75cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light // 76cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light // image_location = /system/framework/boot.art 77cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light // *image_filename = /data/dalvik-cache/<image_isa>/boot.art 78cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light std::string error_msg; 79cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light if (GetDalvikCacheFilename(location.c_str(), dalvik_cache.c_str(), 80cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light &cache_filename, &error_msg)) { 81cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light has_cache = true; 82cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } 83cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } 84cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light if (has_system) { 85cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light *filename = system_filename; 86cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light return true; 87cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } else if (has_cache) { 88cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light *filename = cache_filename; 89cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light return true; 90cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } else { 91cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light return false; 92cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } 93cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light} 94cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light 950eb76d2603a52d3e8759fcf480586886d70433d1Alex Lightstatic const OatHeader* GetOatHeader(const ElfFile* elf_file) { 960eb76d2603a52d3e8759fcf480586886d70433d1Alex Light uint64_t off = 0; 970eb76d2603a52d3e8759fcf480586886d70433d1Alex Light if (!elf_file->GetSectionOffsetAndSize(".rodata", &off, nullptr)) { 980eb76d2603a52d3e8759fcf480586886d70433d1Alex Light return nullptr; 990eb76d2603a52d3e8759fcf480586886d70433d1Alex Light } 1000eb76d2603a52d3e8759fcf480586886d70433d1Alex Light 1010eb76d2603a52d3e8759fcf480586886d70433d1Alex Light OatHeader* oat_header = reinterpret_cast<OatHeader*>(elf_file->Begin() + off); 1020eb76d2603a52d3e8759fcf480586886d70433d1Alex Light return oat_header; 1030eb76d2603a52d3e8759fcf480586886d70433d1Alex Light} 1040eb76d2603a52d3e8759fcf480586886d70433d1Alex Light 1050eb76d2603a52d3e8759fcf480586886d70433d1Alex Light// This function takes an elf file and reads the current patch delta value 1060eb76d2603a52d3e8759fcf480586886d70433d1Alex Light// encoded in its oat header value 1070eb76d2603a52d3e8759fcf480586886d70433d1Alex Lightstatic bool ReadOatPatchDelta(const ElfFile* elf_file, off_t* delta, std::string* error_msg) { 1080eb76d2603a52d3e8759fcf480586886d70433d1Alex Light const OatHeader* oat_header = GetOatHeader(elf_file); 1090eb76d2603a52d3e8759fcf480586886d70433d1Alex Light if (oat_header == nullptr) { 1100eb76d2603a52d3e8759fcf480586886d70433d1Alex Light *error_msg = "Unable to get oat header from elf file."; 1110eb76d2603a52d3e8759fcf480586886d70433d1Alex Light return false; 1120eb76d2603a52d3e8759fcf480586886d70433d1Alex Light } 1130eb76d2603a52d3e8759fcf480586886d70433d1Alex Light if (!oat_header->IsValid()) { 1140eb76d2603a52d3e8759fcf480586886d70433d1Alex Light *error_msg = "Elf file has an invalid oat header"; 1150eb76d2603a52d3e8759fcf480586886d70433d1Alex Light return false; 1160eb76d2603a52d3e8759fcf480586886d70433d1Alex Light } 1170eb76d2603a52d3e8759fcf480586886d70433d1Alex Light *delta = oat_header->GetImagePatchDelta(); 1180eb76d2603a52d3e8759fcf480586886d70433d1Alex Light return true; 1190eb76d2603a52d3e8759fcf480586886d70433d1Alex Light} 1200eb76d2603a52d3e8759fcf480586886d70433d1Alex Light 121dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Haostatic File* CreateOrOpen(const char* name, bool* created) { 122dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao if (OS::FileExists(name)) { 123dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao *created = false; 124dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao return OS::OpenFileReadWrite(name); 125dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } else { 126dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao *created = true; 127dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::unique_ptr<File> f(OS::CreateEmptyFile(name)); 128dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao if (f.get() != nullptr) { 129dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao if (fchmod(f->Fd(), 0644) != 0) { 130dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao PLOG(ERROR) << "Unable to make " << name << " world readable"; 1317a1c0148a9bfbd15132c949f7758719027e9deb4Dimitry Ivanov unlink(name); 132dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao return nullptr; 133dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } 134dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } 135dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao return f.release(); 136dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } 137dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao} 138dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao 139dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao// Either try to close the file (close=true), or erase it. 140dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Haostatic bool FinishFile(File* file, bool close) { 141dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao if (close) { 142dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao if (file->FlushCloseOrErase() != 0) { 143dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao PLOG(ERROR) << "Failed to flush and close file."; 144dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao return false; 145dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } 146dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao return true; 147dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } else { 148dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao file->Erase(); 149dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao return false; 150dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } 151dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao} 152dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao 1536eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampebool PatchOat::Patch(const std::string& image_location, 1546eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe off_t delta, 1556eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe const std::string& output_directory, 1566eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe InstructionSet isa, 1576eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe TimingLogger* timings) { 15853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(Runtime::Current() == nullptr); 15953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(!image_location.empty()) << "image file must have a filename."; 16053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 161eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light TimingLogger::ScopedTiming t("Runtime Setup", timings); 16253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 1636eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe CHECK_NE(isa, kNone); 16453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const char* isa_name = GetInstructionSetString(isa); 16546774767fcf7780d1455e755729198648d08742eIgor Murashkin 16653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Set up the runtime 167e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers RuntimeOptions options; 16853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light NoopCompilerCallbacks callbacks; 16953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light options.push_back(std::make_pair("compilercallbacks", &callbacks)); 17053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string img = "-Ximage:" + image_location; 17153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light options.push_back(std::make_pair(img.c_str(), nullptr)); 17253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light options.push_back(std::make_pair("imageinstructionset", reinterpret_cast<const void*>(isa_name))); 17301aaf6ef3e3e35cc8e41cf3fe899a7bf337042f4Calin Juravle options.push_back(std::make_pair("-Xno-sig-chain", nullptr)); 17453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!Runtime::Create(options, false)) { 17553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "Unable to initialize runtime"; 17653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 17753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 17853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start, 17953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // give it away now and then switch to a more manageable ScopedObjectAccess. 18053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Thread::Current()->TransitionFromRunnableToSuspended(kNative); 18153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light ScopedObjectAccess soa(Thread::Current()); 18253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 18353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light t.NewTiming("Image and oat Patching setup"); 184dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::vector<gc::space::ImageSpace*> spaces = Runtime::Current()->GetHeap()->GetBootImageSpaces(); 185dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::map<gc::space::ImageSpace*, std::unique_ptr<File>> space_to_file_map; 186dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::map<gc::space::ImageSpace*, std::unique_ptr<MemMap>> space_to_memmap_map; 187dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::map<gc::space::ImageSpace*, PatchOat> space_to_patchoat_map; 188dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::map<gc::space::ImageSpace*, bool> space_to_skip_patching_map; 189dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao 190dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao for (size_t i = 0; i < spaces.size(); ++i) { 191dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao gc::space::ImageSpace* space = spaces[i]; 192dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::string input_image_filename = space->GetImageFilename(); 193dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::unique_ptr<File> input_image(OS::OpenFileForReading(input_image_filename.c_str())); 194dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao if (input_image.get() == nullptr) { 195dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao LOG(ERROR) << "Unable to open input image file at " << input_image_filename; 196dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao return false; 197dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } 19853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 199dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao int64_t image_len = input_image->GetLength(); 200dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao if (image_len < 0) { 201dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao LOG(ERROR) << "Error while getting image length"; 202dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao return false; 203dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } 204dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao ImageHeader image_header; 205dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao if (sizeof(image_header) != input_image->Read(reinterpret_cast<char*>(&image_header), 206dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao sizeof(image_header), 0)) { 207dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao LOG(ERROR) << "Unable to read image header from image file " << input_image->GetPath(); 208dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } 20953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 210dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao /*bool is_image_pic = */IsImagePic(image_header, input_image->GetPath()); 211dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao // Nothing special to do right now since the image always needs to get patched. 212dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao // Perhaps in some far-off future we may have images with relative addresses that are true-PIC. 213dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao 214dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao // Create the map where we will write the image patches to. 215dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::string error_msg; 216dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::unique_ptr<MemMap> image(MemMap::MapFile(image_len, 217dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao PROT_READ | PROT_WRITE, 218dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao MAP_PRIVATE, 219dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao input_image->Fd(), 220dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao 0, 221dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao /*low_4gb*/false, 222dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao input_image->GetPath().c_str(), 223dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao &error_msg)); 224dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao if (image.get() == nullptr) { 225dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao LOG(ERROR) << "Unable to map image file " << input_image->GetPath() << " : " << error_msg; 226dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao return false; 227dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } 228dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao space_to_file_map.emplace(space, std::move(input_image)); 229dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao space_to_memmap_map.emplace(space, std::move(image)); 230dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } 231dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao 232dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao for (size_t i = 0; i < spaces.size(); ++i) { 233dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao gc::space::ImageSpace* space = spaces[i]; 234dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::string input_image_filename = space->GetImageFilename(); 235dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::string input_oat_filename = 236dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao ImageHeader::GetOatLocationFromImageLocation(input_image_filename); 237dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::unique_ptr<File> input_oat_file(OS::OpenFileForReading(input_oat_filename.c_str())); 238dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao if (input_oat_file.get() == nullptr) { 239dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao LOG(ERROR) << "Unable to open input oat file at " << input_oat_filename; 240dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao return false; 241dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } 242dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::string error_msg; 243dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::unique_ptr<ElfFile> elf(ElfFile::Open(input_oat_file.get(), 244dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao PROT_READ | PROT_WRITE, MAP_PRIVATE, &error_msg)); 245dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao if (elf.get() == nullptr) { 246dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao LOG(ERROR) << "Unable to open oat file " << input_oat_file->GetPath() << " : " << error_msg; 24746774767fcf7780d1455e755729198648d08742eIgor Murashkin return false; 24846774767fcf7780d1455e755729198648d08742eIgor Murashkin } 24946774767fcf7780d1455e755729198648d08742eIgor Murashkin 250dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao bool skip_patching_oat = false; 251dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao MaybePic is_oat_pic = IsOatPic(elf.get()); 252dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao if (is_oat_pic >= ERROR_FIRST) { 253dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao // Error logged by IsOatPic 254dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao return false; 255dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } else if (is_oat_pic == PIC) { 256dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao // Do not need to do ELF-file patching. Create a symlink and skip the ELF patching. 257dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao 258dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::string converted_image_filename = space->GetImageLocation(); 259dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::replace(converted_image_filename.begin() + 1, converted_image_filename.end(), '/', '@'); 260dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::string output_image_filename = output_directory + 261dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao (StartsWith(converted_image_filename, "/") ? "" : "/") + 262dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao converted_image_filename; 263dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::string output_oat_filename = 264dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao ImageHeader::GetOatLocationFromImageLocation(output_image_filename); 265dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao 266dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao if (!ReplaceOatFileWithSymlink(input_oat_file->GetPath(), 267dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao output_oat_filename, 268dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao false, 269dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao true)) { 270dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao // Errors already logged by above call. 271dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao return false; 272dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } 273dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao // Don't patch the OAT, since we just symlinked it. Image still needs patching. 274dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao skip_patching_oat = true; 275dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } else { 276dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao CHECK(is_oat_pic == NOT_PIC); 277dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } 27853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 279dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao PatchOat& p = space_to_patchoat_map.emplace(space, 280dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao PatchOat( 281dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao isa, 282dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao elf.release(), 283dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao space_to_memmap_map.find(space)->second.get(), 284dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao space->GetLiveBitmap(), 285dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao space->GetMemMap(), 286dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao delta, 287dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao &space_to_memmap_map, 288dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao timings)).first->second; 289dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao 290dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao t.NewTiming("Patching files"); 291dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao if (!skip_patching_oat && !p.PatchElf()) { 292dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao LOG(ERROR) << "Failed to patch oat file " << input_oat_file->GetPath(); 293dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao return false; 294dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } 295dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao if (!p.PatchImage(i == 0)) { 296dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao LOG(ERROR) << "Failed to patch image file " << input_image_filename; 297dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao return false; 298dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } 299dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao 300dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao space_to_skip_patching_map.emplace(space, skip_patching_oat); 30153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 302dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao 303dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao for (size_t i = 0; i < spaces.size(); ++i) { 304dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao gc::space::ImageSpace* space = spaces[i]; 305dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::string input_image_filename = space->GetImageFilename(); 306dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao 307dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao t.NewTiming("Writing files"); 308dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::string converted_image_filename = space->GetImageLocation(); 309dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::replace(converted_image_filename.begin() + 1, converted_image_filename.end(), '/', '@'); 310dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::string output_image_filename = output_directory + 311dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao (StartsWith(converted_image_filename, "/") ? "" : "/") + 312dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao converted_image_filename; 3136eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe bool new_oat_out; 314dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::unique_ptr<File> 315dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao output_image_file(CreateOrOpen(output_image_filename.c_str(), &new_oat_out)); 316dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao if (output_image_file.get() == nullptr) { 317dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao LOG(ERROR) << "Failed to open output image file at " << output_image_filename; 318dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao return false; 319dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } 320dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao 321dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao PatchOat& p = space_to_patchoat_map.find(space)->second; 322dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao 323d12f9c13599a6b5893cffd02c9b8d35b4db93bf3Serdjuk, Nikolay Y bool success = p.WriteImage(output_image_file.get()); 324d12f9c13599a6b5893cffd02c9b8d35b4db93bf3Serdjuk, Nikolay Y success = FinishFile(output_image_file.get(), success); 325d12f9c13599a6b5893cffd02c9b8d35b4db93bf3Serdjuk, Nikolay Y if (!success) { 326dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao return false; 327dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } 328dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao 329dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao bool skip_patching_oat = space_to_skip_patching_map.find(space)->second; 330dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao if (!skip_patching_oat) { 331dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::string output_oat_filename = 332dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao ImageHeader::GetOatLocationFromImageLocation(output_image_filename); 333dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao std::unique_ptr<File> 334dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao output_oat_file(CreateOrOpen(output_oat_filename.c_str(), &new_oat_out)); 335dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao if (output_oat_file.get() == nullptr) { 336dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao LOG(ERROR) << "Failed to open output oat file at " << output_oat_filename; 337dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao return false; 338dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } 339d12f9c13599a6b5893cffd02c9b8d35b4db93bf3Serdjuk, Nikolay Y success = p.WriteElf(output_oat_file.get()); 340d12f9c13599a6b5893cffd02c9b8d35b4db93bf3Serdjuk, Nikolay Y success = FinishFile(output_oat_file.get(), success); 341d12f9c13599a6b5893cffd02c9b8d35b4db93bf3Serdjuk, Nikolay Y if (!success) { 342dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao return false; 343dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } 344dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } 34553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 34653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 34753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 34853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 34953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightbool PatchOat::WriteElf(File* out) { 350eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light TimingLogger::ScopedTiming t("Writing Elf File", timings_); 351a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light 35253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(oat_file_.get() != nullptr); 35353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(out != nullptr); 35453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light size_t expect = oat_file_->Size(); 35553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (out->WriteFully(reinterpret_cast<char*>(oat_file_->Begin()), expect) && 35653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light out->SetLength(expect) == 0) { 35753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 35853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 35953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "Writing to oat file " << out->GetPath() << " failed."; 36053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 36153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 36253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 36353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 36453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightbool PatchOat::WriteImage(File* out) { 365eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light TimingLogger::ScopedTiming t("Writing image File", timings_); 366a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light std::string error_msg; 367a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light 368cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light ScopedFlock img_flock; 369cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light img_flock.Init(out, &error_msg); 370a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light 37153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(image_ != nullptr); 37253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(out != nullptr); 37353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light size_t expect = image_->Size(); 37453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (out->WriteFully(reinterpret_cast<char*>(image_->Begin()), expect) && 37553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light out->SetLength(expect) == 0) { 37653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 37753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 37853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "Writing to image file " << out->GetPath() << " failed."; 37953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 38053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 38153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 38253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 38346774767fcf7780d1455e755729198648d08742eIgor Murashkinbool PatchOat::IsImagePic(const ImageHeader& image_header, const std::string& image_path) { 38446774767fcf7780d1455e755729198648d08742eIgor Murashkin if (!image_header.CompilePic()) { 38546774767fcf7780d1455e755729198648d08742eIgor Murashkin if (kIsDebugBuild) { 38646774767fcf7780d1455e755729198648d08742eIgor Murashkin LOG(INFO) << "image at location " << image_path << " was *not* compiled pic"; 38746774767fcf7780d1455e755729198648d08742eIgor Murashkin } 38846774767fcf7780d1455e755729198648d08742eIgor Murashkin return false; 38946774767fcf7780d1455e755729198648d08742eIgor Murashkin } 39046774767fcf7780d1455e755729198648d08742eIgor Murashkin 39146774767fcf7780d1455e755729198648d08742eIgor Murashkin if (kIsDebugBuild) { 39246774767fcf7780d1455e755729198648d08742eIgor Murashkin LOG(INFO) << "image at location " << image_path << " was compiled PIC"; 39346774767fcf7780d1455e755729198648d08742eIgor Murashkin } 39446774767fcf7780d1455e755729198648d08742eIgor Murashkin 39546774767fcf7780d1455e755729198648d08742eIgor Murashkin return true; 39646774767fcf7780d1455e755729198648d08742eIgor Murashkin} 39746774767fcf7780d1455e755729198648d08742eIgor Murashkin 39846774767fcf7780d1455e755729198648d08742eIgor MurashkinPatchOat::MaybePic PatchOat::IsOatPic(const ElfFile* oat_in) { 39946774767fcf7780d1455e755729198648d08742eIgor Murashkin if (oat_in == nullptr) { 40046774767fcf7780d1455e755729198648d08742eIgor Murashkin LOG(ERROR) << "No ELF input oat fie available"; 40146774767fcf7780d1455e755729198648d08742eIgor Murashkin return ERROR_OAT_FILE; 40246774767fcf7780d1455e755729198648d08742eIgor Murashkin } 40346774767fcf7780d1455e755729198648d08742eIgor Murashkin 404645e477c2ce7a59ac98bc86463826cf082a13ad8Brian Carlstrom const std::string& file_path = oat_in->GetFilePath(); 40546774767fcf7780d1455e755729198648d08742eIgor Murashkin 40646774767fcf7780d1455e755729198648d08742eIgor Murashkin const OatHeader* oat_header = GetOatHeader(oat_in); 40746774767fcf7780d1455e755729198648d08742eIgor Murashkin if (oat_header == nullptr) { 40846774767fcf7780d1455e755729198648d08742eIgor Murashkin LOG(ERROR) << "Failed to find oat header in oat file " << file_path; 40946774767fcf7780d1455e755729198648d08742eIgor Murashkin return ERROR_OAT_FILE; 41046774767fcf7780d1455e755729198648d08742eIgor Murashkin } 41146774767fcf7780d1455e755729198648d08742eIgor Murashkin 41246774767fcf7780d1455e755729198648d08742eIgor Murashkin if (!oat_header->IsValid()) { 41346774767fcf7780d1455e755729198648d08742eIgor Murashkin LOG(ERROR) << "Elf file " << file_path << " has an invalid oat header"; 41446774767fcf7780d1455e755729198648d08742eIgor Murashkin return ERROR_OAT_FILE; 41546774767fcf7780d1455e755729198648d08742eIgor Murashkin } 41646774767fcf7780d1455e755729198648d08742eIgor Murashkin 41746774767fcf7780d1455e755729198648d08742eIgor Murashkin bool is_pic = oat_header->IsPic(); 41846774767fcf7780d1455e755729198648d08742eIgor Murashkin if (kIsDebugBuild) { 41946774767fcf7780d1455e755729198648d08742eIgor Murashkin LOG(INFO) << "Oat file at " << file_path << " is " << (is_pic ? "PIC" : "not pic"); 42046774767fcf7780d1455e755729198648d08742eIgor Murashkin } 42146774767fcf7780d1455e755729198648d08742eIgor Murashkin 42246774767fcf7780d1455e755729198648d08742eIgor Murashkin return is_pic ? PIC : NOT_PIC; 42346774767fcf7780d1455e755729198648d08742eIgor Murashkin} 42446774767fcf7780d1455e755729198648d08742eIgor Murashkin 42546774767fcf7780d1455e755729198648d08742eIgor Murashkinbool PatchOat::ReplaceOatFileWithSymlink(const std::string& input_oat_filename, 42646774767fcf7780d1455e755729198648d08742eIgor Murashkin const std::string& output_oat_filename, 42746774767fcf7780d1455e755729198648d08742eIgor Murashkin bool output_oat_opened_from_fd, 42846774767fcf7780d1455e755729198648d08742eIgor Murashkin bool new_oat_out) { 42946774767fcf7780d1455e755729198648d08742eIgor Murashkin // Need a file when we are PIC, since we symlink over it. Refusing to symlink into FD. 43046774767fcf7780d1455e755729198648d08742eIgor Murashkin if (output_oat_opened_from_fd) { 43146774767fcf7780d1455e755729198648d08742eIgor Murashkin // TODO: installd uses --output-oat-fd. Should we change class linking logic for PIC? 43246774767fcf7780d1455e755729198648d08742eIgor Murashkin LOG(ERROR) << "No output oat filename specified, needs filename for when we are PIC"; 43346774767fcf7780d1455e755729198648d08742eIgor Murashkin return false; 43446774767fcf7780d1455e755729198648d08742eIgor Murashkin } 43546774767fcf7780d1455e755729198648d08742eIgor Murashkin 43646774767fcf7780d1455e755729198648d08742eIgor Murashkin // Image was PIC. Create symlink where the oat is supposed to go. 43746774767fcf7780d1455e755729198648d08742eIgor Murashkin if (!new_oat_out) { 43846774767fcf7780d1455e755729198648d08742eIgor Murashkin LOG(ERROR) << "Oat file " << output_oat_filename << " already exists, refusing to overwrite"; 43946774767fcf7780d1455e755729198648d08742eIgor Murashkin return false; 44046774767fcf7780d1455e755729198648d08742eIgor Murashkin } 44146774767fcf7780d1455e755729198648d08742eIgor Murashkin 44246774767fcf7780d1455e755729198648d08742eIgor Murashkin // Delete the original file, since we won't need it. 4437a1c0148a9bfbd15132c949f7758719027e9deb4Dimitry Ivanov unlink(output_oat_filename.c_str()); 44446774767fcf7780d1455e755729198648d08742eIgor Murashkin 44546774767fcf7780d1455e755729198648d08742eIgor Murashkin // Create a symlink from the old oat to the new oat 44646774767fcf7780d1455e755729198648d08742eIgor Murashkin if (symlink(input_oat_filename.c_str(), output_oat_filename.c_str()) < 0) { 44746774767fcf7780d1455e755729198648d08742eIgor Murashkin int err = errno; 44846774767fcf7780d1455e755729198648d08742eIgor Murashkin LOG(ERROR) << "Failed to create symlink at " << output_oat_filename 44946774767fcf7780d1455e755729198648d08742eIgor Murashkin << " error(" << err << "): " << strerror(err); 45046774767fcf7780d1455e755729198648d08742eIgor Murashkin return false; 45146774767fcf7780d1455e755729198648d08742eIgor Murashkin } 45246774767fcf7780d1455e755729198648d08742eIgor Murashkin 45346774767fcf7780d1455e755729198648d08742eIgor Murashkin if (kIsDebugBuild) { 45446774767fcf7780d1455e755729198648d08742eIgor Murashkin LOG(INFO) << "Created symlink " << output_oat_filename << " -> " << input_oat_filename; 45546774767fcf7780d1455e755729198648d08742eIgor Murashkin } 45646774767fcf7780d1455e755729198648d08742eIgor Murashkin 45746774767fcf7780d1455e755729198648d08742eIgor Murashkin return true; 45846774767fcf7780d1455e755729198648d08742eIgor Murashkin} 45946774767fcf7780d1455e755729198648d08742eIgor Murashkin 46054d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartierclass PatchOatArtFieldVisitor : public ArtFieldVisitor { 46154d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier public: 46254d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier explicit PatchOatArtFieldVisitor(PatchOat* patch_oat) : patch_oat_(patch_oat) {} 46354d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier 46454d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier void Visit(ArtField* field) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) { 46554d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier ArtField* const dest = patch_oat_->RelocatedCopyOf(field); 46654d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier dest->SetDeclaringClass(patch_oat_->RelocatedAddressOfPointer(field->GetDeclaringClass())); 46754d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier } 46854d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier 46954d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier private: 47054d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier PatchOat* const patch_oat_; 47154d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier}; 47254d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier 473c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartiervoid PatchOat::PatchArtFields(const ImageHeader* image_header) { 47454d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier PatchOatArtFieldVisitor visitor(this); 475cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier image_header->VisitPackedArtFields(&visitor, heap_->Begin()); 476e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier} 477e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier 47854d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartierclass PatchOatArtMethodVisitor : public ArtMethodVisitor { 47954d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier public: 48054d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier explicit PatchOatArtMethodVisitor(PatchOat* patch_oat) : patch_oat_(patch_oat) {} 48154d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier 48254d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier void Visit(ArtMethod* method) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) { 48354d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier ArtMethod* const dest = patch_oat_->RelocatedCopyOf(method); 48454d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier patch_oat_->FixupMethod(method, dest); 48554d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier } 48654d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier 48754d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier private: 48854d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier PatchOat* const patch_oat_; 48954d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier}; 49054d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier 491e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartiervoid PatchOat::PatchArtMethods(const ImageHeader* image_header) { 492e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier const size_t pointer_size = InstructionSetPointerSize(isa_); 49354d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier PatchOatArtMethodVisitor visitor(this); 494cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier image_header->VisitPackedArtMethods(&visitor, heap_->Begin(), pointer_size); 495cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier} 496cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier 497df2d4f22d5e89692c90b443da82fe2930518418bArtem Udovichenkovoid PatchOat::PatchImTables(const ImageHeader* image_header) { 498df2d4f22d5e89692c90b443da82fe2930518418bArtem Udovichenko const size_t pointer_size = InstructionSetPointerSize(isa_); 499df2d4f22d5e89692c90b443da82fe2930518418bArtem Udovichenko // We can safely walk target image since the conflict tables are independent. 500df2d4f22d5e89692c90b443da82fe2930518418bArtem Udovichenko image_header->VisitPackedImTables( 501df2d4f22d5e89692c90b443da82fe2930518418bArtem Udovichenko [this](ArtMethod* method) { 502df2d4f22d5e89692c90b443da82fe2930518418bArtem Udovichenko return RelocatedAddressOfPointer(method); 503df2d4f22d5e89692c90b443da82fe2930518418bArtem Udovichenko }, 504df2d4f22d5e89692c90b443da82fe2930518418bArtem Udovichenko image_->Begin(), 505df2d4f22d5e89692c90b443da82fe2930518418bArtem Udovichenko pointer_size); 506df2d4f22d5e89692c90b443da82fe2930518418bArtem Udovichenko} 507df2d4f22d5e89692c90b443da82fe2930518418bArtem Udovichenko 508cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartiervoid PatchOat::PatchImtConflictTables(const ImageHeader* image_header) { 509cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier const size_t pointer_size = InstructionSetPointerSize(isa_); 510cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier // We can safely walk target image since the conflict tables are independent. 511cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier image_header->VisitPackedImtConflictTables( 512cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier [this](ArtMethod* method) { 513cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier return RelocatedAddressOfPointer(method); 514cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier }, 515cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier image_->Begin(), 516cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier pointer_size); 517c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier} 518c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier 519d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartierclass FixupRootVisitor : public RootVisitor { 520d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier public: 521d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier explicit FixupRootVisitor(const PatchOat* patch_oat) : patch_oat_(patch_oat) { 522d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier } 523d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier 524d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier void VisitRoots(mirror::Object*** roots, size_t count, const RootInfo& info ATTRIBUTE_UNUSED) 52590443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) { 526d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier for (size_t i = 0; i < count; ++i) { 527d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier *roots[i] = patch_oat_->RelocatedAddressOfPointer(*roots[i]); 528d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier } 529d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier } 530d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier 531d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier void VisitRoots(mirror::CompressedReference<mirror::Object>** roots, size_t count, 532d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier const RootInfo& info ATTRIBUTE_UNUSED) 53390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) { 534d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier for (size_t i = 0; i < count; ++i) { 535d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier roots[i]->Assign(patch_oat_->RelocatedAddressOfPointer(roots[i]->AsMirrorPtr())); 536d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier } 537d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier } 538d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier 539d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier private: 540d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier const PatchOat* const patch_oat_; 541d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier}; 542d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier 543d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartiervoid PatchOat::PatchInternedStrings(const ImageHeader* image_header) { 544d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier const auto& section = image_header->GetImageSection(ImageHeader::kSectionInternedStrings); 545d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier InternTable temp_table; 546d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier // Note that we require that ReadFromMemory does not make an internal copy of the elements. 547d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier // This also relies on visit roots not doing any verification which could fail after we update 548d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier // the roots to be the image addresses. 549ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier temp_table.AddTableFromMemory(image_->Begin() + section.Offset()); 550d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier FixupRootVisitor visitor(this); 551d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier temp_table.VisitRoots(&visitor, kVisitRootFlagAllRoots); 552d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier} 553d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier 554208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartiervoid PatchOat::PatchClassTable(const ImageHeader* image_header) { 555208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier const auto& section = image_header->GetImageSection(ImageHeader::kSectionClassTable); 556fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier if (section.Size() == 0) { 557fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier return; 558fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier } 559208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier // Note that we require that ReadFromMemory does not make an internal copy of the elements. 560208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier // This also relies on visit roots not doing any verification which could fail after we update 561208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier // the roots to be the image addresses. 562208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); 563208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier ClassTable temp_table; 564208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier temp_table.ReadFromMemory(image_->Begin() + section.Offset()); 565208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier FixupRootVisitor visitor(this); 566208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier BufferedRootVisitor<kDefaultBufferedRootCount> buffered_visitor(&visitor, RootInfo(kRootUnknown)); 567208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier temp_table.VisitRoots(buffered_visitor); 568208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier} 569208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier 570208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier 5714b00d3415beb7a816a3b5948f43f3b2e4b856ea8Mathieu Chartierclass RelocatedPointerVisitor { 5724b00d3415beb7a816a3b5948f43f3b2e4b856ea8Mathieu Chartier public: 5734b00d3415beb7a816a3b5948f43f3b2e4b856ea8Mathieu Chartier explicit RelocatedPointerVisitor(PatchOat* patch_oat) : patch_oat_(patch_oat) {} 5744b00d3415beb7a816a3b5948f43f3b2e4b856ea8Mathieu Chartier 5754b00d3415beb7a816a3b5948f43f3b2e4b856ea8Mathieu Chartier template <typename T> 5764b00d3415beb7a816a3b5948f43f3b2e4b856ea8Mathieu Chartier T* operator()(T* ptr) const { 5774b00d3415beb7a816a3b5948f43f3b2e4b856ea8Mathieu Chartier return patch_oat_->RelocatedAddressOfPointer(ptr); 5784b00d3415beb7a816a3b5948f43f3b2e4b856ea8Mathieu Chartier } 5794b00d3415beb7a816a3b5948f43f3b2e4b856ea8Mathieu Chartier 5804b00d3415beb7a816a3b5948f43f3b2e4b856ea8Mathieu Chartier private: 5814b00d3415beb7a816a3b5948f43f3b2e4b856ea8Mathieu Chartier PatchOat* const patch_oat_; 5824b00d3415beb7a816a3b5948f43f3b2e4b856ea8Mathieu Chartier}; 5834b00d3415beb7a816a3b5948f43f3b2e4b856ea8Mathieu Chartier 584c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartiervoid PatchOat::PatchDexFileArrays(mirror::ObjectArray<mirror::Object>* img_roots) { 585c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier auto* dex_caches = down_cast<mirror::ObjectArray<mirror::DexCache>*>( 586c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier img_roots->Get(ImageHeader::kDexCaches)); 5874b00d3415beb7a816a3b5948f43f3b2e4b856ea8Mathieu Chartier const size_t pointer_size = InstructionSetPointerSize(isa_); 588c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier for (size_t i = 0, count = dex_caches->GetLength(); i < count; ++i) { 58905792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko auto* orig_dex_cache = dex_caches->GetWithoutChecks(i); 59005792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko auto* copy_dex_cache = RelocatedCopyOf(orig_dex_cache); 59105792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko // Though the DexCache array fields are usually treated as native pointers, we set the full 59205792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko // 64-bit values here, clearing the top 32 bits for 32-bit targets. The zero-extension is 59305792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko // done by casting to the unsigned type uintptr_t before casting to int64_t, i.e. 59405792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko // static_cast<int64_t>(reinterpret_cast<uintptr_t>(image_begin_ + offset))). 59505792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko GcRoot<mirror::String>* orig_strings = orig_dex_cache->GetStrings(); 59605792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko GcRoot<mirror::String>* relocated_strings = RelocatedAddressOfPointer(orig_strings); 59705792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko copy_dex_cache->SetField64<false>( 59805792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko mirror::DexCache::StringsOffset(), 59905792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_strings))); 60005792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko if (orig_strings != nullptr) { 6014b00d3415beb7a816a3b5948f43f3b2e4b856ea8Mathieu Chartier orig_dex_cache->FixupStrings(RelocatedCopyOf(orig_strings), RelocatedPointerVisitor(this)); 60205792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko } 60305792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko GcRoot<mirror::Class>* orig_types = orig_dex_cache->GetResolvedTypes(); 60405792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko GcRoot<mirror::Class>* relocated_types = RelocatedAddressOfPointer(orig_types); 60505792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko copy_dex_cache->SetField64<false>( 60605792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko mirror::DexCache::ResolvedTypesOffset(), 60705792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_types))); 60805792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko if (orig_types != nullptr) { 6094b00d3415beb7a816a3b5948f43f3b2e4b856ea8Mathieu Chartier orig_dex_cache->FixupResolvedTypes(RelocatedCopyOf(orig_types), 6104b00d3415beb7a816a3b5948f43f3b2e4b856ea8Mathieu Chartier RelocatedPointerVisitor(this)); 611c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier } 61205792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko ArtMethod** orig_methods = orig_dex_cache->GetResolvedMethods(); 61305792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko ArtMethod** relocated_methods = RelocatedAddressOfPointer(orig_methods); 61405792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko copy_dex_cache->SetField64<false>( 61505792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko mirror::DexCache::ResolvedMethodsOffset(), 61605792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_methods))); 61705792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko if (orig_methods != nullptr) { 61805792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko ArtMethod** copy_methods = RelocatedCopyOf(orig_methods); 61905792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko for (size_t j = 0, num = orig_dex_cache->NumResolvedMethods(); j != num; ++j) { 62005792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko ArtMethod* orig = mirror::DexCache::GetElementPtrSize(orig_methods, j, pointer_size); 62105792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko ArtMethod* copy = RelocatedAddressOfPointer(orig); 62205792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko mirror::DexCache::SetElementPtrSize(copy_methods, j, copy, pointer_size); 62305792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko } 62405792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko } 62505792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko ArtField** orig_fields = orig_dex_cache->GetResolvedFields(); 62605792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko ArtField** relocated_fields = RelocatedAddressOfPointer(orig_fields); 62705792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko copy_dex_cache->SetField64<false>( 62805792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko mirror::DexCache::ResolvedFieldsOffset(), 62905792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_fields))); 63005792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko if (orig_fields != nullptr) { 63105792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko ArtField** copy_fields = RelocatedCopyOf(orig_fields); 63205792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko for (size_t j = 0, num = orig_dex_cache->NumResolvedFields(); j != num; ++j) { 63305792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko ArtField* orig = mirror::DexCache::GetElementPtrSize(orig_fields, j, pointer_size); 63405792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko ArtField* copy = RelocatedAddressOfPointer(orig); 63505792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko mirror::DexCache::SetElementPtrSize(copy_fields, j, copy, pointer_size); 63605792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko } 637e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier } 638e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier } 639e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier} 640e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier 641dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Haobool PatchOat::PatchImage(bool primary_image) { 64253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light ImageHeader* image_header = reinterpret_cast<ImageHeader*>(image_->Begin()); 64353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_GT(image_->Size(), sizeof(ImageHeader)); 64453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // These are the roots from the original file. 645c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier auto* img_roots = image_header->GetImageRoots(); 64653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light image_header->RelocateImage(delta_); 64753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 648c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier PatchArtFields(image_header); 649e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier PatchArtMethods(image_header); 650df2d4f22d5e89692c90b443da82fe2930518418bArtem Udovichenko PatchImTables(image_header); 651cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier PatchImtConflictTables(image_header); 652d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier PatchInternedStrings(image_header); 653208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier PatchClassTable(image_header); 654c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier // Patch dex file int/long arrays which point to ArtFields. 655c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier PatchDexFileArrays(img_roots); 656c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier 657dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao if (primary_image) { 658dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao VisitObject(img_roots); 659dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao } 660dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao 66153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!image_header->IsValid()) { 662dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao LOG(ERROR) << "relocation renders image header invalid"; 66353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 66453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 66553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 66653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light { 667eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light TimingLogger::ScopedTiming t("Walk Bitmap", timings_); 66853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Walk the bitmap. 66953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_); 67053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bitmap_->Walk(PatchOat::BitmapCallback, this); 67153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 67253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 67353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 67453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 67553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 67653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightvoid PatchOat::PatchVisitor::operator() (mirror::Object* obj, MemberOffset off, 6776a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers bool is_static_unused ATTRIBUTE_UNUSED) const { 67853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light mirror::Object* referent = obj->GetFieldObject<mirror::Object, kVerifyNone>(off); 679c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier mirror::Object* moved_object = patcher_->RelocatedAddressOfPointer(referent); 68053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(off, moved_object); 68153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 68253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 6836a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid PatchOat::PatchVisitor::operator() (mirror::Class* cls ATTRIBUTE_UNUSED, 6846a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers mirror::Reference* ref) const { 68553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light MemberOffset off = mirror::Reference::ReferentOffset(); 68653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light mirror::Object* referent = ref->GetReferent(); 687488849c584337a1aae8413a1d1e0fad8043bf672Mathieu Chartier DCHECK(referent == nullptr || 688488849c584337a1aae8413a1d1e0fad8043bf672Mathieu Chartier Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(referent)) << referent; 689c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier mirror::Object* moved_object = patcher_->RelocatedAddressOfPointer(referent); 69053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(off, moved_object); 69153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 69253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 69353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light// Called by BitmapCallback 69453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightvoid PatchOat::VisitObject(mirror::Object* object) { 69553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light mirror::Object* copy = RelocatedCopyOf(object); 69653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(copy != nullptr); 69753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (kUseBakerOrBrooksReadBarrier) { 69853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light object->AssertReadBarrierPointer(); 69953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (kUseBrooksReadBarrier) { 700c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier mirror::Object* moved_to = RelocatedAddressOfPointer(object); 70153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light copy->SetReadBarrierPointer(moved_to); 70253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light DCHECK_EQ(copy->GetReadBarrierPointer(), moved_to); 70353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 70453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 70553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light PatchOat::PatchVisitor visitor(this, copy); 706059ef3ddb2088f926ac452889e0953fdcd646a5eMathieu Chartier object->VisitReferences<kVerifyNone>(visitor, visitor); 707e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier if (object->IsClass<kVerifyNone>()) { 7084b00d3415beb7a816a3b5948f43f3b2e4b856ea8Mathieu Chartier const size_t pointer_size = InstructionSetPointerSize(isa_); 7094b00d3415beb7a816a3b5948f43f3b2e4b856ea8Mathieu Chartier mirror::Class* klass = object->AsClass(); 7104b00d3415beb7a816a3b5948f43f3b2e4b856ea8Mathieu Chartier mirror::Class* copy_klass = down_cast<mirror::Class*>(copy); 7114b00d3415beb7a816a3b5948f43f3b2e4b856ea8Mathieu Chartier RelocatedPointerVisitor native_visitor(this); 7124b00d3415beb7a816a3b5948f43f3b2e4b856ea8Mathieu Chartier klass->FixupNativePointers(copy_klass, pointer_size, native_visitor); 713e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier auto* vtable = klass->GetVTable(); 714e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier if (vtable != nullptr) { 715dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao vtable->Fixup(RelocatedCopyOfFollowImages(vtable), pointer_size, native_visitor); 716e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier } 717e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier auto* iftable = klass->GetIfTable(); 718e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier if (iftable != nullptr) { 719e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier for (int32_t i = 0; i < klass->GetIfTableCount(); ++i) { 720e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier if (iftable->GetMethodArrayCount(i) > 0) { 721e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier auto* method_array = iftable->GetMethodArray(i); 722e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier CHECK(method_array != nullptr); 723dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao method_array->Fixup(RelocatedCopyOfFollowImages(method_array), 724dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao pointer_size, 725dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao native_visitor); 726e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier } 727e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier } 728e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier } 7294b00d3415beb7a816a3b5948f43f3b2e4b856ea8Mathieu Chartier } else if (object->GetClass() == mirror::Method::StaticClass() || 7304b00d3415beb7a816a3b5948f43f3b2e4b856ea8Mathieu Chartier object->GetClass() == mirror::Constructor::StaticClass()) { 731e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier // Need to go update the ArtMethod. 732e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier auto* dest = down_cast<mirror::AbstractMethod*>(copy); 733e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier auto* src = down_cast<mirror::AbstractMethod*>(object); 734e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier dest->SetArtMethod(RelocatedAddressOfPointer(src->GetArtMethod())); 73553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 73653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 73753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 738e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartiervoid PatchOat::FixupMethod(ArtMethod* object, ArtMethod* copy) { 7392d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier const size_t pointer_size = InstructionSetPointerSize(isa_); 740e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier copy->CopyFrom(object, pointer_size); 74153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Just update the entry points if it looks like we should. 742eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light // TODO: sanity check all the pointers' values 743e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier copy->SetDeclaringClass(RelocatedAddressOfPointer(object->GetDeclaringClass())); 74405792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko copy->SetDexCacheResolvedMethods( 74505792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko RelocatedAddressOfPointer(object->GetDexCacheResolvedMethods(pointer_size)), pointer_size); 74605792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko copy->SetDexCacheResolvedTypes( 74705792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko RelocatedAddressOfPointer(object->GetDexCacheResolvedTypes(pointer_size)), pointer_size); 748e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier copy->SetEntryPointFromQuickCompiledCodePtrSize(RelocatedAddressOfPointer( 749e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier object->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size)), pointer_size); 750cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier // No special handling for IMT conflict table since all pointers are moved by the same offset. 751e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier copy->SetEntryPointFromJniPtrSize(RelocatedAddressOfPointer( 752e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier object->GetEntryPointFromJniPtrSize(pointer_size)), pointer_size); 75353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 75453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 75546774767fcf7780d1455e755729198648d08742eIgor Murashkinbool PatchOat::Patch(File* input_oat, off_t delta, File* output_oat, TimingLogger* timings, 75646774767fcf7780d1455e755729198648d08742eIgor Murashkin bool output_oat_opened_from_fd, bool new_oat_out) { 75753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(input_oat != nullptr); 75853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(output_oat != nullptr); 75953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_GE(input_oat->Fd(), 0); 76053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_GE(output_oat->Fd(), 0); 761eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light TimingLogger::ScopedTiming t("Setup Oat File Patching", timings); 76253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 76353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string error_msg; 76446774767fcf7780d1455e755729198648d08742eIgor Murashkin std::unique_ptr<ElfFile> elf(ElfFile::Open(input_oat, 76553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light PROT_READ | PROT_WRITE, MAP_PRIVATE, &error_msg)); 76653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (elf.get() == nullptr) { 76753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "unable to open oat file " << input_oat->GetPath() << " : " << error_msg; 76853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 76953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 77053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 77146774767fcf7780d1455e755729198648d08742eIgor Murashkin MaybePic is_oat_pic = IsOatPic(elf.get()); 77246774767fcf7780d1455e755729198648d08742eIgor Murashkin if (is_oat_pic >= ERROR_FIRST) { 77346774767fcf7780d1455e755729198648d08742eIgor Murashkin // Error logged by IsOatPic 77446774767fcf7780d1455e755729198648d08742eIgor Murashkin return false; 77546774767fcf7780d1455e755729198648d08742eIgor Murashkin } else if (is_oat_pic == PIC) { 77646774767fcf7780d1455e755729198648d08742eIgor Murashkin // Do not need to do ELF-file patching. Create a symlink and skip the rest. 77746774767fcf7780d1455e755729198648d08742eIgor Murashkin // Any errors will be logged by the function call. 77846774767fcf7780d1455e755729198648d08742eIgor Murashkin return ReplaceOatFileWithSymlink(input_oat->GetPath(), 77946774767fcf7780d1455e755729198648d08742eIgor Murashkin output_oat->GetPath(), 78046774767fcf7780d1455e755729198648d08742eIgor Murashkin output_oat_opened_from_fd, 78146774767fcf7780d1455e755729198648d08742eIgor Murashkin new_oat_out); 78246774767fcf7780d1455e755729198648d08742eIgor Murashkin } else { 78346774767fcf7780d1455e755729198648d08742eIgor Murashkin CHECK(is_oat_pic == NOT_PIC); 78446774767fcf7780d1455e755729198648d08742eIgor Murashkin } 78546774767fcf7780d1455e755729198648d08742eIgor Murashkin 78653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light PatchOat p(elf.release(), delta, timings); 78753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light t.NewTiming("Patch Oat file"); 78853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!p.PatchElf()) { 78953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 79053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 79153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 79253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light t.NewTiming("Writing oat file"); 79353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!p.WriteElf(output_oat)) { 79453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 79553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 79653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 79753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 79853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 79962d1ca3182a6cbb921799825f43ad36821233fd7Tong Shentemplate <typename ElfFileImpl> 80062d1ca3182a6cbb921799825f43ad36821233fd7Tong Shenbool PatchOat::PatchOatHeader(ElfFileImpl* oat_file) { 80162d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen auto rodata_sec = oat_file->FindSectionByName(".rodata"); 802a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light if (rodata_sec == nullptr) { 803a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light return false; 804a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } 80562d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen OatHeader* oat_header = reinterpret_cast<OatHeader*>(oat_file->Begin() + rodata_sec->sh_offset); 806a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light if (!oat_header->IsValid()) { 807645e477c2ce7a59ac98bc86463826cf082a13ad8Brian Carlstrom LOG(ERROR) << "Elf file " << oat_file->GetFilePath() << " has an invalid oat header"; 808a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light return false; 809a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } 810a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light oat_header->RelocateOat(delta_); 811a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light return true; 812a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light} 813a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light 81453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightbool PatchOat::PatchElf() { 815645e477c2ce7a59ac98bc86463826cf082a13ad8Brian Carlstrom if (oat_file_->Is64Bit()) { 81662d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen return PatchElf<ElfFileImpl64>(oat_file_->GetImpl64()); 817645e477c2ce7a59ac98bc86463826cf082a13ad8Brian Carlstrom } else { 81862d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen return PatchElf<ElfFileImpl32>(oat_file_->GetImpl32()); 819645e477c2ce7a59ac98bc86463826cf082a13ad8Brian Carlstrom } 82062d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen} 82162d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen 82262d1ca3182a6cbb921799825f43ad36821233fd7Tong Shentemplate <typename ElfFileImpl> 82362d1ca3182a6cbb921799825f43ad36821233fd7Tong Shenbool PatchOat::PatchElf(ElfFileImpl* oat_file) { 824a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light TimingLogger::ScopedTiming t("Fixup Elf Text Section", timings_); 8253fc9903407c6e89ffbbc92ded9e272d9de58e9b6Vladimir Marko 8263fc9903407c6e89ffbbc92ded9e272d9de58e9b6Vladimir Marko // Fix up absolute references to locations within the boot image. 8272f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky if (!oat_file->ApplyOatPatchesTo(".text", delta_)) { 828a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light return false; 829a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } 830a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light 8313fc9903407c6e89ffbbc92ded9e272d9de58e9b6Vladimir Marko // Update the OatHeader fields referencing the boot image. 83262d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen if (!PatchOatHeader<ElfFileImpl>(oat_file)) { 833a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light return false; 834a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } 835a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light 8363fc9903407c6e89ffbbc92ded9e272d9de58e9b6Vladimir Marko bool need_boot_oat_fixup = true; 837d4c4d953035d4418126d36517e402f411d6a87f3Ian Rogers for (unsigned int i = 0; i < oat_file->GetProgramHeaderNum(); ++i) { 83862d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen auto hdr = oat_file->GetProgramHeader(i); 8393fc9903407c6e89ffbbc92ded9e272d9de58e9b6Vladimir Marko if (hdr->p_type == PT_LOAD && hdr->p_vaddr == 0u) { 8403fc9903407c6e89ffbbc92ded9e272d9de58e9b6Vladimir Marko need_boot_oat_fixup = false; 841d4c4d953035d4418126d36517e402f411d6a87f3Ian Rogers break; 84253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 84353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 8443fc9903407c6e89ffbbc92ded9e272d9de58e9b6Vladimir Marko if (!need_boot_oat_fixup) { 8453fc9903407c6e89ffbbc92ded9e272d9de58e9b6Vladimir Marko // This is an app oat file that can be loaded at an arbitrary address in memory. 8463fc9903407c6e89ffbbc92ded9e272d9de58e9b6Vladimir Marko // Boot image references were patched above and there's nothing else to do. 847a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light return true; 848a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } 84962d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen 8503fc9903407c6e89ffbbc92ded9e272d9de58e9b6Vladimir Marko // This is a boot oat file that's loaded at a particular address and we need 8513fc9903407c6e89ffbbc92ded9e272d9de58e9b6Vladimir Marko // to patch all absolute addresses, starting with ELF program headers. 8523fc9903407c6e89ffbbc92ded9e272d9de58e9b6Vladimir Marko 85362d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen t.NewTiming("Fixup Elf Headers"); 85462d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen // Fixup Phdr's 85562d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen oat_file->FixupProgramHeaders(delta_); 85662d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen 857a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light t.NewTiming("Fixup Section Headers"); 85862d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen // Fixup Shdr's 85962d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen oat_file->FixupSectionHeaders(delta_); 86053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 861a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light t.NewTiming("Fixup Dynamics"); 86262d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen oat_file->FixupDynamic(delta_); 86353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 86453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light t.NewTiming("Fixup Elf Symbols"); 86553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Fixup dynsym 86662d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen if (!oat_file->FixupSymbols(delta_, true)) { 86753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 86853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 86953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Fixup symtab 87062d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen if (!oat_file->FixupSymbols(delta_, false)) { 87162d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen return false; 87253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 87353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 874e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban t.NewTiming("Fixup Debug Sections"); 87562d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen if (!oat_file->FixupDebugSections(delta_)) { 876e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban return false; 877e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 878e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 87953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 88053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 88153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 88253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightstatic int orig_argc; 88353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightstatic char** orig_argv; 88453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 88553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightstatic std::string CommandLine() { 88653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::vector<std::string> command; 88753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light for (int i = 0; i < orig_argc; ++i) { 88853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light command.push_back(orig_argv[i]); 88953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 89053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return Join(command, ' '); 89153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 89253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 89353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightstatic void UsageErrorV(const char* fmt, va_list ap) { 89453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string error; 89553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light StringAppendV(&error, fmt, ap); 89653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << error; 89753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 89853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 89953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightstatic void UsageError(const char* fmt, ...) { 90053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light va_list ap; 90153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light va_start(ap, fmt); 90253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageErrorV(fmt, ap); 90353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light va_end(ap); 90453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 90553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 906794ad76e8d5b5b9132819d5b08a0570e27615644Andreas GampeNO_RETURN static void Usage(const char *fmt, ...) { 90753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light va_list ap; 90853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light va_start(ap, fmt); 90953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageErrorV(fmt, ap); 91053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light va_end(ap); 91153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 91253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError("Command: %s", CommandLine().c_str()); 91353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError("Usage: patchoat [options]..."); 91453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 91553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --instruction-set=<isa>: Specifies the instruction set the patched code is"); 91653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" compiled for. Required if you use --input-oat-location"); 91753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 91853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --input-oat-file=<file.oat>: Specifies the exact filename of the oat file to be"); 91953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" patched."); 92053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 92153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --input-oat-fd=<file-descriptor>: Specifies the file-descriptor of the oat file"); 92253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" to be patched."); 92353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 92453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --input-oat-location=<file.oat>: Specifies the 'location' to read the patched"); 92553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" oat file from. If used one must also supply the --instruction-set"); 92653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 92753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --input-image-location=<file.art>: Specifies the 'location' of the image file to"); 92853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" be patched. If --instruction-set is not given it will use the instruction set"); 92953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" extracted from the --input-oat-file."); 93053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 93153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --output-oat-file=<file.oat>: Specifies the exact file to write the patched oat"); 93253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" file to."); 93353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 93453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --output-oat-fd=<file-descriptor>: Specifies the file-descriptor to write the"); 93553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" the patched oat file to."); 93653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 93753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --output-image-file=<file.art>: Specifies the exact file to write the patched"); 93853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" image file to."); 93953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 94053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --base-offset-delta=<delta>: Specify the amount to change the old base-offset by."); 94153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" This value may be negative."); 94253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 9430eb76d2603a52d3e8759fcf480586886d70433d1Alex Light UsageError(" --patched-image-location=<file.art>: Relocate the oat file to be the same as the"); 9440eb76d2603a52d3e8759fcf480586886d70433d1Alex Light UsageError(" image at the given location. If used one must also specify the"); 945a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light UsageError(" --instruction-set flag. It will search for this image in the same way that"); 946a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light UsageError(" is done when loading one."); 94753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 948cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light UsageError(" --lock-output: Obtain a flock on output oat file before starting."); 949cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light UsageError(""); 950cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light UsageError(" --no-lock-output: Do not attempt to obtain a flock on output oat file."); 951cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light UsageError(""); 95253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --dump-timings: dump out patch timing information"); 95353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 95453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --no-dump-timings: do not dump out patch timing information"); 95553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 95653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 95753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light exit(EXIT_FAILURE); 95853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 95953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 960eefbe39799126afdf7d315a79359b9da23d1cef5Alex Lightstatic bool ReadBaseDelta(const char* name, off_t* delta, std::string* error_msg) { 96153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(name != nullptr); 96253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(delta != nullptr); 96353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::unique_ptr<File> file; 96453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (OS::FileExists(name)) { 96553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light file.reset(OS::OpenFileForReading(name)); 96653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (file.get() == nullptr) { 967eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light *error_msg = "Failed to open file %s for reading"; 96853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 96953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 97053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 971eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light *error_msg = "File %s does not exist"; 97253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 97353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 97453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(file.get() != nullptr); 97553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light ImageHeader hdr; 97653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (sizeof(hdr) != file->Read(reinterpret_cast<char*>(&hdr), sizeof(hdr), 0)) { 977eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light *error_msg = "Failed to read file %s"; 97853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 97953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 98053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!hdr.IsValid()) { 981eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light *error_msg = "%s does not contain a valid image header."; 98253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 98353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 98453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light *delta = hdr.GetPatchDelta(); 98553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 98653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 98753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 9886eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampestatic int patchoat_image(TimingLogger& timings, 9896eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe InstructionSet isa, 9906eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe const std::string& input_image_location, 9916eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe const std::string& output_image_filename, 9926eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe off_t base_delta, 9936eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe bool base_delta_set, 9946eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe bool debug) { 9956eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe CHECK(!input_image_location.empty()); 9966eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (output_image_filename.empty()) { 9976eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe Usage("Image patching requires --output-image-file"); 9986eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 99953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 10006eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (!base_delta_set) { 10016eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe Usage("Must supply a desired new offset or delta."); 10026eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 100353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 10046eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (!IsAligned<kPageSize>(base_delta)) { 10056eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe Usage("Base offset/delta must be aligned to a pagesize (0x%08x) boundary.", kPageSize); 10066eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 100753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 10086eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (debug) { 10096eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe LOG(INFO) << "moving offset by " << base_delta 10106eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe << " (0x" << std::hex << base_delta << ") bytes or " 10116eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe << std::dec << (base_delta/kPageSize) << " pages."; 101253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 101353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 10146eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe TimingLogger::ScopedTiming pt("patch image and oat", &timings); 101553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 10166eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe std::string output_directory = 10176eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe output_image_filename.substr(0, output_image_filename.find_last_of("/")); 10186eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe bool ret = PatchOat::Patch(input_image_location, base_delta, output_directory, isa, &timings); 101953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 10206eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (kIsDebugBuild) { 10216eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe LOG(INFO) << "Exiting with return ... " << ret; 102253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 10236eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe return ret ? EXIT_SUCCESS : EXIT_FAILURE; 10246eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe} 102553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 10266eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampestatic int patchoat_oat(TimingLogger& timings, 10276eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe InstructionSet isa, 10286eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe const std::string& patched_image_location, 10296eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe off_t base_delta, 10306eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe bool base_delta_set, 10316eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe int input_oat_fd, 10326eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe const std::string& input_oat_location, 10336eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe std::string input_oat_filename, 10346eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe bool have_input_oat, 10356eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe int output_oat_fd, 10366eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe std::string output_oat_filename, 10376eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe bool have_output_oat, 10386eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe bool lock_output, 10396eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe bool debug) { 104053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light { 104153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Only 1 of these may be set. 104253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uint32_t cnt = 0; 104353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light cnt += (base_delta_set) ? 1 : 0; 104453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light cnt += (!patched_image_location.empty()) ? 1 : 0; 104553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (cnt > 1) { 10466eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe Usage("Only one of --base-offset-delta or --patched-image-location may be used."); 104753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (cnt == 0) { 10486eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe Usage("Must specify --base-offset-delta or --patched-image-location."); 104953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 105053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 105153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 10526eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (!have_input_oat || !have_output_oat) { 10536eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe Usage("Both input and output oat must be supplied to patch an app odex."); 105453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 105553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 105653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!input_oat_location.empty()) { 1057cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light if (!LocationToFilename(input_oat_location, isa, &input_oat_filename)) { 1058cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light Usage("Unable to find filename for input oat location %s", input_oat_location.c_str()); 105953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 106053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (debug) { 1061cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light LOG(INFO) << "Using input-oat-file " << input_oat_filename; 106253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 106353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 10646eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe 10656eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe bool match_delta = false; 106653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!patched_image_location.empty()) { 1067a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light std::string system_filename; 1068a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light bool has_system = false; 1069a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light std::string cache_filename; 1070a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light bool has_cache = false; 1071a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light bool has_android_data_unused = false; 10723c13a794845e0cf7887e33b2ec20de7e6ba85f8fAndreas Gampe bool is_global_cache = false; 1073a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light if (!gc::space::ImageSpace::FindImageFilename(patched_image_location.c_str(), isa, 1074a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light &system_filename, &has_system, &cache_filename, 10753c13a794845e0cf7887e33b2ec20de7e6ba85f8fAndreas Gampe &has_android_data_unused, &has_cache, 10763c13a794845e0cf7887e33b2ec20de7e6ba85f8fAndreas Gampe &is_global_cache)) { 1077a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light Usage("Unable to determine image file for location %s", patched_image_location.c_str()); 1078a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } 10796eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe std::string patched_image_filename; 1080a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light if (has_cache) { 1081a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light patched_image_filename = cache_filename; 1082a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } else if (has_system) { 1083a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light LOG(WARNING) << "Only image file found was in /system for image location " 10846eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe << patched_image_location; 1085a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light patched_image_filename = system_filename; 1086a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } else { 1087a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light Usage("Unable to determine image file for location %s", patched_image_location.c_str()); 1088a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } 108953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (debug) { 109053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(INFO) << "Using patched-image-file " << patched_image_filename; 109153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 109253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 10936eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe base_delta_set = true; 10946eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe match_delta = true; 10956eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe std::string error_msg; 10966eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (!ReadBaseDelta(patched_image_filename.c_str(), &base_delta, &error_msg)) { 10976eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe Usage(error_msg.c_str(), patched_image_filename.c_str()); 109853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 109953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 110053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 110153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!IsAligned<kPageSize>(base_delta)) { 110253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Base offset/delta must be alligned to a pagesize (0x%08x) boundary.", kPageSize); 110353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 110453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 110553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Do we need to cleanup output files if we fail? 110653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool new_oat_out = false; 110753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 110853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::unique_ptr<File> input_oat; 110953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::unique_ptr<File> output_oat; 111053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 11116eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (input_oat_fd != -1) { 11126eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (input_oat_filename.empty()) { 11136eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe input_oat_filename = "input-oat-file"; 11146eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 11156eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe input_oat.reset(new File(input_oat_fd, input_oat_filename, false)); 11166eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (input_oat_fd == output_oat_fd) { 11176eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe input_oat.get()->DisableAutoClose(); 11186eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 11196eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (input_oat == nullptr) { 11206eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe // Unlikely, but ensure exhaustive logging in non-0 exit code case 11216eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe LOG(ERROR) << "Failed to open input oat file by its FD" << input_oat_fd; 1122ec1514a91a34586aca3fd75d1565ad5992c54929Jeff Hao return EXIT_FAILURE; 112353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 112453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 11256eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe CHECK(!input_oat_filename.empty()); 11266eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe input_oat.reset(OS::OpenFileForReading(input_oat_filename.c_str())); 11276eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (input_oat == nullptr) { 11286eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe int err = errno; 11296eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe LOG(ERROR) << "Failed to open input oat file " << input_oat_filename 11306eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe << ": " << strerror(err) << "(" << err << ")"; 1131ec1514a91a34586aca3fd75d1565ad5992c54929Jeff Hao return EXIT_FAILURE; 11326eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 113353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 113453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 1135ec1514a91a34586aca3fd75d1565ad5992c54929Jeff Hao std::string error_msg; 1136ec1514a91a34586aca3fd75d1565ad5992c54929Jeff Hao std::unique_ptr<ElfFile> elf(ElfFile::Open(input_oat.get(), PROT_READ, MAP_PRIVATE, &error_msg)); 1137ec1514a91a34586aca3fd75d1565ad5992c54929Jeff Hao if (elf.get() == nullptr) { 1138ec1514a91a34586aca3fd75d1565ad5992c54929Jeff Hao LOG(ERROR) << "unable to open oat file " << input_oat->GetPath() << " : " << error_msg; 1139ec1514a91a34586aca3fd75d1565ad5992c54929Jeff Hao return EXIT_FAILURE; 1140ec1514a91a34586aca3fd75d1565ad5992c54929Jeff Hao } 1141ec1514a91a34586aca3fd75d1565ad5992c54929Jeff Hao if (!elf->HasSection(".text.oat_patches")) { 1142ec1514a91a34586aca3fd75d1565ad5992c54929Jeff Hao LOG(ERROR) << "missing oat patch section in input oat file " << input_oat->GetPath(); 1143ec1514a91a34586aca3fd75d1565ad5992c54929Jeff Hao return EXIT_FAILURE; 1144ec1514a91a34586aca3fd75d1565ad5992c54929Jeff Hao } 1145ec1514a91a34586aca3fd75d1565ad5992c54929Jeff Hao 11466eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (output_oat_fd != -1) { 11476eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (output_oat_filename.empty()) { 11486eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe output_oat_filename = "output-oat-file"; 114953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 11506eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe output_oat.reset(new File(output_oat_fd, output_oat_filename, true)); 11516eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (output_oat == nullptr) { 11526eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe // Unlikely, but ensure exhaustive logging in non-0 exit code case 11536eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe LOG(ERROR) << "Failed to open output oat file by its FD" << output_oat_fd; 11546eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 11556eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } else { 11566eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe CHECK(!output_oat_filename.empty()); 11576eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe output_oat.reset(CreateOrOpen(output_oat_filename.c_str(), &new_oat_out)); 11586eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (output_oat == nullptr) { 11596eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe int err = errno; 11606eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe LOG(ERROR) << "Failed to open output oat file " << output_oat_filename 11616eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe << ": " << strerror(err) << "(" << err << ")"; 116253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 116353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 116453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 116546774767fcf7780d1455e755729198648d08742eIgor Murashkin // TODO: get rid of this. 11666eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe auto cleanup = [&output_oat_filename, &new_oat_out](bool success) { 116753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!success) { 116853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (new_oat_out) { 116953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(!output_oat_filename.empty()); 11707a1c0148a9bfbd15132c949f7758719027e9deb4Dimitry Ivanov unlink(output_oat_filename.c_str()); 117153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 117253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 117346774767fcf7780d1455e755729198648d08742eIgor Murashkin 117446774767fcf7780d1455e755729198648d08742eIgor Murashkin if (kIsDebugBuild) { 117546774767fcf7780d1455e755729198648d08742eIgor Murashkin LOG(INFO) << "Cleaning up.. success? " << success; 117646774767fcf7780d1455e755729198648d08742eIgor Murashkin } 117753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light }; 117853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 1179ec1514a91a34586aca3fd75d1565ad5992c54929Jeff Hao if (output_oat.get() == nullptr) { 1180cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light cleanup(false); 1181cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light return EXIT_FAILURE; 118246774767fcf7780d1455e755729198648d08742eIgor Murashkin } 118346774767fcf7780d1455e755729198648d08742eIgor Murashkin 11840eb76d2603a52d3e8759fcf480586886d70433d1Alex Light if (match_delta) { 11850eb76d2603a52d3e8759fcf480586886d70433d1Alex Light // Figure out what the current delta is so we can match it to the desired delta. 11860eb76d2603a52d3e8759fcf480586886d70433d1Alex Light off_t current_delta = 0; 1187ec1514a91a34586aca3fd75d1565ad5992c54929Jeff Hao if (!ReadOatPatchDelta(elf.get(), ¤t_delta, &error_msg)) { 11880eb76d2603a52d3e8759fcf480586886d70433d1Alex Light LOG(ERROR) << "Unable to get current delta: " << error_msg; 11890eb76d2603a52d3e8759fcf480586886d70433d1Alex Light cleanup(false); 11900eb76d2603a52d3e8759fcf480586886d70433d1Alex Light return EXIT_FAILURE; 11910eb76d2603a52d3e8759fcf480586886d70433d1Alex Light } 11920eb76d2603a52d3e8759fcf480586886d70433d1Alex Light // Before this line base_delta is the desired final delta. We need it to be the actual amount to 11930eb76d2603a52d3e8759fcf480586886d70433d1Alex Light // change everything by. We subtract the current delta from it to make it this. 11940eb76d2603a52d3e8759fcf480586886d70433d1Alex Light base_delta -= current_delta; 11950eb76d2603a52d3e8759fcf480586886d70433d1Alex Light if (!IsAligned<kPageSize>(base_delta)) { 11960eb76d2603a52d3e8759fcf480586886d70433d1Alex Light LOG(ERROR) << "Given image file was relocated by an illegal delta"; 11970eb76d2603a52d3e8759fcf480586886d70433d1Alex Light cleanup(false); 11980eb76d2603a52d3e8759fcf480586886d70433d1Alex Light return false; 11990eb76d2603a52d3e8759fcf480586886d70433d1Alex Light } 12000eb76d2603a52d3e8759fcf480586886d70433d1Alex Light } 12010eb76d2603a52d3e8759fcf480586886d70433d1Alex Light 120246774767fcf7780d1455e755729198648d08742eIgor Murashkin if (debug) { 120346774767fcf7780d1455e755729198648d08742eIgor Murashkin LOG(INFO) << "moving offset by " << base_delta 12046eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe << " (0x" << std::hex << base_delta << ") bytes or " 12056eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe << std::dec << (base_delta/kPageSize) << " pages."; 1206cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } 1207cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light 1208cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light ScopedFlock output_oat_lock; 1209cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light if (lock_output) { 12106eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (!output_oat_lock.Init(output_oat.get(), &error_msg)) { 12116eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe LOG(ERROR) << "Unable to lock output oat " << output_oat->GetPath() << ": " << error_msg; 1212cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light cleanup(false); 1213cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light return EXIT_FAILURE; 1214cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } 1215cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } 1216cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light 12176eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe TimingLogger::ScopedTiming pt("patch oat", &timings); 12186eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe bool ret = PatchOat::Patch(input_oat.get(), base_delta, output_oat.get(), &timings, 12196eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe output_oat_fd >= 0, // was it opened from FD? 12206eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe new_oat_out); 12216eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe ret = FinishFile(output_oat.get(), ret); 122246774767fcf7780d1455e755729198648d08742eIgor Murashkin 122346774767fcf7780d1455e755729198648d08742eIgor Murashkin if (kIsDebugBuild) { 122446774767fcf7780d1455e755729198648d08742eIgor Murashkin LOG(INFO) << "Exiting with return ... " << ret; 122553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 122653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light cleanup(ret); 12276eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe return ret ? EXIT_SUCCESS : EXIT_FAILURE; 12286eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe} 12296eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe 12306eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampestatic int patchoat(int argc, char **argv) { 12316eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe InitLogging(argv); 12326eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe MemMap::Init(); 12336eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe const bool debug = kIsDebugBuild; 12346eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe orig_argc = argc; 12356eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe orig_argv = argv; 12366eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe TimingLogger timings("patcher", false, false); 12376eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe 12386eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe InitLogging(argv); 12396eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe 12406eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe // Skip over the command name. 12416eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe argv++; 12426eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe argc--; 12436eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe 12446eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (argc == 0) { 12456eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe Usage("No arguments specified"); 12466eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 12476eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe 12486eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe timings.StartTiming("Patchoat"); 12496eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe 12506eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe // cmd line args 12516eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe bool isa_set = false; 12526eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe InstructionSet isa = kNone; 12536eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe std::string input_oat_filename; 12546eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe std::string input_oat_location; 12556eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe int input_oat_fd = -1; 12566eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe bool have_input_oat = false; 12576eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe std::string input_image_location; 12586eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe std::string output_oat_filename; 12596eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe int output_oat_fd = -1; 12606eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe bool have_output_oat = false; 12616eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe std::string output_image_filename; 12626eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe off_t base_delta = 0; 12636eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe bool base_delta_set = false; 12646eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe std::string patched_image_filename; 12656eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe std::string patched_image_location; 12666eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe bool dump_timings = kIsDebugBuild; 12676eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe bool lock_output = true; 12686eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe 12696eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe for (int i = 0; i < argc; ++i) { 12706eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe const StringPiece option(argv[i]); 12716eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe const bool log_options = false; 12726eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (log_options) { 12736eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe LOG(INFO) << "patchoat: option[" << i << "]=" << argv[i]; 12746eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 12756eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (option.starts_with("--instruction-set=")) { 12766eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe isa_set = true; 12776eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe const char* isa_str = option.substr(strlen("--instruction-set=")).data(); 12786eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe isa = GetInstructionSetFromString(isa_str); 12796eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (isa == kNone) { 12806eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe Usage("Unknown or invalid instruction set %s", isa_str); 12816eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 12826eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } else if (option.starts_with("--input-oat-location=")) { 12836eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (have_input_oat) { 12846eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe Usage("Only one of --input-oat-file, --input-oat-location and --input-oat-fd may be used."); 12856eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 12866eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe have_input_oat = true; 12876eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe input_oat_location = option.substr(strlen("--input-oat-location=")).data(); 12886eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } else if (option.starts_with("--input-oat-file=")) { 12896eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (have_input_oat) { 12906eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe Usage("Only one of --input-oat-file, --input-oat-location and --input-oat-fd may be used."); 12916eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 12926eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe have_input_oat = true; 12936eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe input_oat_filename = option.substr(strlen("--input-oat-file=")).data(); 12946eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } else if (option.starts_with("--input-oat-fd=")) { 12956eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (have_input_oat) { 12966eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe Usage("Only one of --input-oat-file, --input-oat-location and --input-oat-fd may be used."); 12976eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 12986eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe have_input_oat = true; 12996eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe const char* oat_fd_str = option.substr(strlen("--input-oat-fd=")).data(); 13006eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (!ParseInt(oat_fd_str, &input_oat_fd)) { 13016eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe Usage("Failed to parse --input-oat-fd argument '%s' as an integer", oat_fd_str); 13026eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 13036eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (input_oat_fd < 0) { 13046eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe Usage("--input-oat-fd pass a negative value %d", input_oat_fd); 13056eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 13066eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } else if (option.starts_with("--input-image-location=")) { 13076eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe input_image_location = option.substr(strlen("--input-image-location=")).data(); 13086eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } else if (option.starts_with("--output-oat-file=")) { 13096eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (have_output_oat) { 13106eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe Usage("Only one of --output-oat-file, and --output-oat-fd may be used."); 13116eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 13126eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe have_output_oat = true; 13136eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe output_oat_filename = option.substr(strlen("--output-oat-file=")).data(); 13146eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } else if (option.starts_with("--output-oat-fd=")) { 13156eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (have_output_oat) { 13166eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe Usage("Only one of --output-oat-file, --output-oat-fd may be used."); 13176eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 13186eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe have_output_oat = true; 13196eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe const char* oat_fd_str = option.substr(strlen("--output-oat-fd=")).data(); 13206eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (!ParseInt(oat_fd_str, &output_oat_fd)) { 13216eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe Usage("Failed to parse --output-oat-fd argument '%s' as an integer", oat_fd_str); 13226eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 13236eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (output_oat_fd < 0) { 13246eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe Usage("--output-oat-fd pass a negative value %d", output_oat_fd); 13256eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 13266eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } else if (option.starts_with("--output-image-file=")) { 13276eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe output_image_filename = option.substr(strlen("--output-image-file=")).data(); 13286eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } else if (option.starts_with("--base-offset-delta=")) { 13296eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe const char* base_delta_str = option.substr(strlen("--base-offset-delta=")).data(); 13306eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe base_delta_set = true; 13316eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (!ParseInt(base_delta_str, &base_delta)) { 13326eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe Usage("Failed to parse --base-offset-delta argument '%s' as an off_t", base_delta_str); 13336eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 13346eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } else if (option.starts_with("--patched-image-location=")) { 13356eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe patched_image_location = option.substr(strlen("--patched-image-location=")).data(); 13366eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } else if (option == "--lock-output") { 13376eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe lock_output = true; 13386eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } else if (option == "--no-lock-output") { 13396eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe lock_output = false; 13406eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } else if (option == "--dump-timings") { 13416eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe dump_timings = true; 13426eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } else if (option == "--no-dump-timings") { 13436eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe dump_timings = false; 13446eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } else { 13456eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe Usage("Unknown argument %s", option.data()); 13466eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 13476eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 13486eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe 13496eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe // The instruction set is mandatory. This simplifies things... 13506eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (!isa_set) { 13516eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe Usage("Instruction set must be set."); 13526eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 13536eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe 13546eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe int ret; 13556eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (!input_image_location.empty()) { 13566eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe ret = patchoat_image(timings, 13576eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe isa, 13586eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe input_image_location, 13596eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe output_image_filename, 13606eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe base_delta, 13616eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe base_delta_set, 13626eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe debug); 13636eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } else { 13646eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe ret = patchoat_oat(timings, 13656eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe isa, 13666eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe patched_image_location, 13676eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe base_delta, 13686eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe base_delta_set, 13696eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe input_oat_fd, 13706eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe input_oat_location, 13716eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe input_oat_filename, 13726eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe have_input_oat, 13736eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe output_oat_fd, 13746eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe output_oat_filename, 13756eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe have_output_oat, 13766eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe lock_output, 13776eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe debug); 13786eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 13796eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe 13806eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe timings.EndTiming(); 13816eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe if (dump_timings) { 13826eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe LOG(INFO) << Dumpable<TimingLogger>(timings); 13836eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe } 13846eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe 13856eb6a39bdcf669655190d40d20f8d2e663b262f4Andreas Gampe return ret; 138653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 138753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 138853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} // namespace art 138953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 139053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightint main(int argc, char **argv) { 139153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return art::patchoat(argc, argv); 139253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 1393