patchoat.cc revision 1c83cbc4a817acbd7f9abb5b29a2d418a958e6a1
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 27a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light#include "base/scoped_flock.h" 2853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "base/stringpiece.h" 2953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "base/stringprintf.h" 3053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "elf_utils.h" 3153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "elf_file.h" 32e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers#include "gc/space/image_space.h" 3353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "image.h" 3453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "instruction_set.h" 3553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "mirror/art_field.h" 3653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "mirror/art_field-inl.h" 3753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "mirror/art_method.h" 3853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "mirror/art_method-inl.h" 3953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "mirror/object.h" 4053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "mirror/object-inl.h" 4153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "mirror/reference.h" 4253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "noop_compiler_callbacks.h" 4353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "offsets.h" 4453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "os.h" 4553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "runtime.h" 4653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "scoped_thread_state_change.h" 4753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "thread.h" 4853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "utils.h" 4953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 5053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightnamespace art { 5153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 5253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightstatic InstructionSet ElfISAToInstructionSet(Elf32_Word isa) { 5353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light switch (isa) { 5453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light case EM_ARM: 5553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return kArm; 5653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light case EM_AARCH64: 5753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return kArm64; 5853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light case EM_386: 5953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return kX86; 6053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light case EM_X86_64: 6153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return kX86_64; 6253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light case EM_MIPS: 6353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return kMips; 6453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light default: 6553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return kNone; 6653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 6753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 6853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 6953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightbool PatchOat::Patch(const std::string& image_location, off_t delta, 7053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light File* output_image, InstructionSet isa, 71eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light TimingLogger* timings) { 7253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(Runtime::Current() == nullptr); 7353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(output_image != nullptr); 7453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_GE(output_image->Fd(), 0); 7553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(!image_location.empty()) << "image file must have a filename."; 7653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_NE(isa, kNone); 7753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 78eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light TimingLogger::ScopedTiming t("Runtime Setup", timings); 7953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const char *isa_name = GetInstructionSetString(isa); 8053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string image_filename(GetSystemImageFilename(image_location.c_str(), isa)); 8153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::unique_ptr<File> input_image(OS::OpenFileForReading(image_filename.c_str())); 8253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (input_image.get() == nullptr) { 8353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "unable to open input image file."; 8453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 8553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 8653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light int64_t image_len = input_image->GetLength(); 8753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (image_len < 0) { 8853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "Error while getting image length"; 8953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 9053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 9153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light ImageHeader image_header; 9253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (sizeof(image_header) != input_image->Read(reinterpret_cast<char*>(&image_header), 9353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light sizeof(image_header), 0)) { 9453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "Unable to read image header from image file " << input_image->GetPath(); 9553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 9653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 9753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 9853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Set up the runtime 99e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers RuntimeOptions options; 10053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light NoopCompilerCallbacks callbacks; 10153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light options.push_back(std::make_pair("compilercallbacks", &callbacks)); 10253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string img = "-Ximage:" + image_location; 10353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light options.push_back(std::make_pair(img.c_str(), nullptr)); 10453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light options.push_back(std::make_pair("imageinstructionset", reinterpret_cast<const void*>(isa_name))); 10553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!Runtime::Create(options, false)) { 10653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "Unable to initialize runtime"; 10753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 10853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 10953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start, 11053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // give it away now and then switch to a more manageable ScopedObjectAccess. 11153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Thread::Current()->TransitionFromRunnableToSuspended(kNative); 11253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light ScopedObjectAccess soa(Thread::Current()); 11353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 11453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light t.NewTiming("Image and oat Patching setup"); 11553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Create the map where we will write the image patches to. 116eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light std::string error_msg; 11753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::unique_ptr<MemMap> image(MemMap::MapFile(image_len, PROT_READ | PROT_WRITE, MAP_PRIVATE, 11853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light input_image->Fd(), 0, 11953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light input_image->GetPath().c_str(), 12053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light &error_msg)); 12153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (image.get() == nullptr) { 12253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "unable to map image file " << input_image->GetPath() << " : " << error_msg; 12353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 12453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 12553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light gc::space::ImageSpace* ispc = Runtime::Current()->GetHeap()->GetImageSpace(); 12653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 12753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light PatchOat p(image.release(), ispc->GetLiveBitmap(), ispc->GetMemMap(), 12853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light delta, timings); 12953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light t.NewTiming("Patching files"); 13053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!p.PatchImage()) { 131a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light LOG(ERROR) << "Failed to patch image file " << input_image->GetPath(); 13253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 13353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 13453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 13553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light t.NewTiming("Writing files"); 13653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!p.WriteImage(output_image)) { 13753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 13853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 13953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 14053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 14153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 14253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightbool PatchOat::Patch(const File* input_oat, const std::string& image_location, off_t delta, 14353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light File* output_oat, File* output_image, InstructionSet isa, 144eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light TimingLogger* timings) { 14553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(Runtime::Current() == nullptr); 14653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(output_image != nullptr); 14753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_GE(output_image->Fd(), 0); 14853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(input_oat != nullptr); 14953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(output_oat != nullptr); 15053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_GE(input_oat->Fd(), 0); 15153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_GE(output_oat->Fd(), 0); 15253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(!image_location.empty()) << "image file must have a filename."; 15353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 154eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light TimingLogger::ScopedTiming t("Runtime Setup", timings); 15553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 15653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (isa == kNone) { 15753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Elf32_Ehdr elf_hdr; 15853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (sizeof(elf_hdr) != input_oat->Read(reinterpret_cast<char*>(&elf_hdr), sizeof(elf_hdr), 0)) { 15953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "unable to read elf header"; 16053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 16153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 16253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light isa = ElfISAToInstructionSet(elf_hdr.e_machine); 16353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 16453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const char* isa_name = GetInstructionSetString(isa); 16553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string image_filename(GetSystemImageFilename(image_location.c_str(), isa)); 16653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::unique_ptr<File> input_image(OS::OpenFileForReading(image_filename.c_str())); 16753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (input_image.get() == nullptr) { 16853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "unable to open input image file."; 16953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 17053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 17153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light int64_t image_len = input_image->GetLength(); 17253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (image_len < 0) { 17353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "Error while getting image length"; 17453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 17553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 17653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light ImageHeader image_header; 17753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (sizeof(image_header) != input_image->Read(reinterpret_cast<char*>(&image_header), 17853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light sizeof(image_header), 0)) { 17953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "Unable to read image header from image file " << input_image->GetPath(); 18053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 18153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 18253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Set up the runtime 183e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers RuntimeOptions options; 18453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light NoopCompilerCallbacks callbacks; 18553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light options.push_back(std::make_pair("compilercallbacks", &callbacks)); 18653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string img = "-Ximage:" + image_location; 18753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light options.push_back(std::make_pair(img.c_str(), nullptr)); 18853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light options.push_back(std::make_pair("imageinstructionset", reinterpret_cast<const void*>(isa_name))); 18953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!Runtime::Create(options, false)) { 19053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "Unable to initialize runtime"; 19153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 19253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 19353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start, 19453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // give it away now and then switch to a more manageable ScopedObjectAccess. 19553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Thread::Current()->TransitionFromRunnableToSuspended(kNative); 19653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light ScopedObjectAccess soa(Thread::Current()); 19753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 19853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light t.NewTiming("Image and oat Patching setup"); 19953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Create the map where we will write the image patches to. 200eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light std::string error_msg; 20153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::unique_ptr<MemMap> image(MemMap::MapFile(image_len, PROT_READ | PROT_WRITE, MAP_PRIVATE, 20253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light input_image->Fd(), 0, 20353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light input_image->GetPath().c_str(), 20453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light &error_msg)); 20553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (image.get() == nullptr) { 20653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "unable to map image file " << input_image->GetPath() << " : " << error_msg; 20753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 20853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 20953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light gc::space::ImageSpace* ispc = Runtime::Current()->GetHeap()->GetImageSpace(); 21053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 21153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::unique_ptr<ElfFile> elf(ElfFile::Open(const_cast<File*>(input_oat), 21253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light PROT_READ | PROT_WRITE, MAP_PRIVATE, &error_msg)); 21353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (elf.get() == nullptr) { 21453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "unable to open oat file " << input_oat->GetPath() << " : " << error_msg; 21553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 21653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 21753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 21853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light PatchOat p(elf.release(), image.release(), ispc->GetLiveBitmap(), ispc->GetMemMap(), 21953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light delta, timings); 22053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light t.NewTiming("Patching files"); 22153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!p.PatchElf()) { 222a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light LOG(ERROR) << "Failed to patch oat file " << input_oat->GetPath(); 22353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 22453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 22553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!p.PatchImage()) { 226a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light LOG(ERROR) << "Failed to patch image file " << input_image->GetPath(); 22753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 22853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 22953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 23053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light t.NewTiming("Writing files"); 23153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!p.WriteElf(output_oat)) { 23253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 23353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 23453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!p.WriteImage(output_image)) { 23553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 23653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 23753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 23853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 23953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 24053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightbool PatchOat::WriteElf(File* out) { 241eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light TimingLogger::ScopedTiming t("Writing Elf File", timings_); 242a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light std::string error_msg; 243a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light 244a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light // Lock the output file. 245a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light ScopedFlock flock; 246a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light flock.Init(out, &error_msg); 247a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light 24853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(oat_file_.get() != nullptr); 24953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(out != nullptr); 25053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light size_t expect = oat_file_->Size(); 25153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (out->WriteFully(reinterpret_cast<char*>(oat_file_->Begin()), expect) && 25253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light out->SetLength(expect) == 0) { 25353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 25453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 25553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "Writing to oat file " << out->GetPath() << " failed."; 25653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 25753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 25853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 25953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 26053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightbool PatchOat::WriteImage(File* out) { 261eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light TimingLogger::ScopedTiming t("Writing image File", timings_); 262a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light std::string error_msg; 263a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light 264a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light // Lock the output file. 265a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light ScopedFlock flock; 266a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light flock.Init(out, &error_msg); 267a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light 26853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(image_ != nullptr); 26953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(out != nullptr); 27053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light size_t expect = image_->Size(); 27153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (out->WriteFully(reinterpret_cast<char*>(image_->Begin()), expect) && 27253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light out->SetLength(expect) == 0) { 27353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 27453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 27553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "Writing to image file " << out->GetPath() << " failed."; 27653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 27753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 27853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 27953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 28053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightbool PatchOat::PatchImage() { 28153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light ImageHeader* image_header = reinterpret_cast<ImageHeader*>(image_->Begin()); 28253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_GT(image_->Size(), sizeof(ImageHeader)); 28353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // These are the roots from the original file. 28453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light mirror::Object* img_roots = image_header->GetImageRoots(); 28553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light image_header->RelocateImage(delta_); 28653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 28753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light VisitObject(img_roots); 28853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!image_header->IsValid()) { 28953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "reloction renders image header invalid"; 29053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 29153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 29253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 29353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light { 294eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light TimingLogger::ScopedTiming t("Walk Bitmap", timings_); 29553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Walk the bitmap. 29653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_); 29753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bitmap_->Walk(PatchOat::BitmapCallback, this); 29853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 29953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 30053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 30153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 30253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightbool PatchOat::InHeap(mirror::Object* o) { 30353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t begin = reinterpret_cast<uintptr_t>(heap_->Begin()); 30453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t end = reinterpret_cast<uintptr_t>(heap_->End()); 30553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t obj = reinterpret_cast<uintptr_t>(o); 30653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return o == nullptr || (begin <= obj && obj < end); 30753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 30853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 30953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightvoid PatchOat::PatchVisitor::operator() (mirror::Object* obj, MemberOffset off, 31053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool is_static_unused) const { 31153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light mirror::Object* referent = obj->GetFieldObject<mirror::Object, kVerifyNone>(off); 31253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light DCHECK(patcher_->InHeap(referent)) << "Referent is not in the heap."; 31353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light mirror::Object* moved_object = patcher_->RelocatedAddressOf(referent); 31453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(off, moved_object); 31553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 31653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 31753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightvoid PatchOat::PatchVisitor::operator() (mirror::Class* cls, mirror::Reference* ref) const { 31853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light MemberOffset off = mirror::Reference::ReferentOffset(); 31953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light mirror::Object* referent = ref->GetReferent(); 32053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light DCHECK(patcher_->InHeap(referent)) << "Referent is not in the heap."; 32153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light mirror::Object* moved_object = patcher_->RelocatedAddressOf(referent); 32253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(off, moved_object); 32353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 32453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 32553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightmirror::Object* PatchOat::RelocatedCopyOf(mirror::Object* obj) { 32653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (obj == nullptr) { 32753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return nullptr; 32853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 32953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light DCHECK_GT(reinterpret_cast<uintptr_t>(obj), reinterpret_cast<uintptr_t>(heap_->Begin())); 33053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light DCHECK_LT(reinterpret_cast<uintptr_t>(obj), reinterpret_cast<uintptr_t>(heap_->End())); 33153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t heap_off = 33253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light reinterpret_cast<uintptr_t>(obj) - reinterpret_cast<uintptr_t>(heap_->Begin()); 33353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light DCHECK_LT(heap_off, image_->Size()); 33453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return reinterpret_cast<mirror::Object*>(image_->Begin() + heap_off); 33553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 33653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 33753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightmirror::Object* PatchOat::RelocatedAddressOf(mirror::Object* obj) { 33853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (obj == nullptr) { 33953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return nullptr; 34053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 34153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return reinterpret_cast<mirror::Object*>(reinterpret_cast<byte*>(obj) + delta_); 34253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 34353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 34453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 34553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light// Called by BitmapCallback 34653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightvoid PatchOat::VisitObject(mirror::Object* object) { 34753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light mirror::Object* copy = RelocatedCopyOf(object); 34853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(copy != nullptr); 34953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (kUseBakerOrBrooksReadBarrier) { 35053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light object->AssertReadBarrierPointer(); 35153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (kUseBrooksReadBarrier) { 35253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light mirror::Object* moved_to = RelocatedAddressOf(object); 35353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light copy->SetReadBarrierPointer(moved_to); 35453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light DCHECK_EQ(copy->GetReadBarrierPointer(), moved_to); 35553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 35653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 35753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light PatchOat::PatchVisitor visitor(this, copy); 35853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light object->VisitReferences<true, kVerifyNone>(visitor, visitor); 35953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (object->IsArtMethod<kVerifyNone>()) { 36053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light FixupMethod(static_cast<mirror::ArtMethod*>(object), 36153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light static_cast<mirror::ArtMethod*>(copy)); 36253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 36353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 36453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 36553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightvoid PatchOat::FixupMethod(mirror::ArtMethod* object, mirror::ArtMethod* copy) { 36653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Just update the entry points if it looks like we should. 367eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light // TODO: sanity check all the pointers' values 36853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t portable = reinterpret_cast<uintptr_t>( 36953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light object->GetEntryPointFromPortableCompiledCode<kVerifyNone>()); 37053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (portable != 0) { 37153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light copy->SetEntryPointFromPortableCompiledCode(reinterpret_cast<void*>(portable + delta_)); 37253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 37353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t quick= reinterpret_cast<uintptr_t>( 37453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light object->GetEntryPointFromQuickCompiledCode<kVerifyNone>()); 37553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (quick != 0) { 37653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light copy->SetEntryPointFromQuickCompiledCode(reinterpret_cast<void*>(quick + delta_)); 37753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 37853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t interpreter = reinterpret_cast<uintptr_t>( 37953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light object->GetEntryPointFromInterpreter<kVerifyNone>()); 38053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (interpreter != 0) { 38153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light copy->SetEntryPointFromInterpreter( 38253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light reinterpret_cast<mirror::EntryPointFromInterpreter*>(interpreter + delta_)); 38353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 38453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 38553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t native_method = reinterpret_cast<uintptr_t>(object->GetNativeMethod()); 38653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (native_method != 0) { 38753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light copy->SetNativeMethod(reinterpret_cast<void*>(native_method + delta_)); 38853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 38953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 39053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t native_gc_map = reinterpret_cast<uintptr_t>(object->GetNativeGcMap()); 39153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (native_gc_map != 0) { 39253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light copy->SetNativeGcMap(reinterpret_cast<uint8_t*>(native_gc_map + delta_)); 39353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 39453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 39553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 396eefbe39799126afdf7d315a79359b9da23d1cef5Alex Lightbool PatchOat::Patch(File* input_oat, off_t delta, File* output_oat, TimingLogger* timings) { 39753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(input_oat != nullptr); 39853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(output_oat != nullptr); 39953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_GE(input_oat->Fd(), 0); 40053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_GE(output_oat->Fd(), 0); 401eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light TimingLogger::ScopedTiming t("Setup Oat File Patching", timings); 40253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 40353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string error_msg; 40453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::unique_ptr<ElfFile> elf(ElfFile::Open(const_cast<File*>(input_oat), 40553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light PROT_READ | PROT_WRITE, MAP_PRIVATE, &error_msg)); 40653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (elf.get() == nullptr) { 40753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "unable to open oat file " << input_oat->GetPath() << " : " << error_msg; 40853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 40953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 41053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 41153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light PatchOat p(elf.release(), delta, timings); 41253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light t.NewTiming("Patch Oat file"); 41353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!p.PatchElf()) { 41453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 41553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 41653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 41753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light t.NewTiming("Writing oat file"); 41853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!p.WriteElf(output_oat)) { 41953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 42053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 42153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 42253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 42353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 42453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightbool PatchOat::CheckOatFile() { 42553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Elf32_Shdr* patches_sec = oat_file_->FindSectionByName(".oat_patches"); 42653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (patches_sec == nullptr) { 42753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 42853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 42953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (patches_sec->sh_type != SHT_OAT_PATCH) { 43053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 43153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 43253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t* patches = reinterpret_cast<uintptr_t*>(oat_file_->Begin() + patches_sec->sh_offset); 43353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t* patches_end = patches + (patches_sec->sh_size/sizeof(uintptr_t)); 43453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Elf32_Shdr* oat_data_sec = oat_file_->FindSectionByName(".rodata"); 43553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Elf32_Shdr* oat_text_sec = oat_file_->FindSectionByName(".text"); 43653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (oat_data_sec == nullptr) { 43753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 43853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 43953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (oat_text_sec == nullptr) { 44053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 44153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 44253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (oat_text_sec->sh_offset <= oat_data_sec->sh_offset) { 44353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 44453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 44553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 44653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light for (; patches < patches_end; patches++) { 44753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (oat_text_sec->sh_size <= *patches) { 44853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 44953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 45053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 45153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 45253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 45353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 45453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 455a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Lightbool PatchOat::PatchOatHeader() { 456a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light Elf32_Shdr *rodata_sec = oat_file_->FindSectionByName(".rodata"); 457a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light if (rodata_sec == nullptr) { 458a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light return false; 459a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } 460a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light OatHeader* oat_header = reinterpret_cast<OatHeader*>(oat_file_->Begin() + rodata_sec->sh_offset); 461a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light if (!oat_header->IsValid()) { 462a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light LOG(ERROR) << "Elf file " << oat_file_->GetFile().GetPath() << " has an invalid oat header"; 463a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light return false; 464a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } 465a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light oat_header->RelocateOat(delta_); 466a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light return true; 467a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light} 468a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light 46953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightbool PatchOat::PatchElf() { 470a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light TimingLogger::ScopedTiming t("Fixup Elf Text Section", timings_); 471a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light if (!PatchTextSection()) { 472a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light return false; 473a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } 474a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light 475a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light if (!PatchOatHeader()) { 476a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light return false; 477a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } 478a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light 479a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light bool need_fixup = false; 480a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light t.NewTiming("Fixup Elf Headers"); 48153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Fixup Phdr's 48253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light for (unsigned int i = 0; i < oat_file_->GetProgramHeaderNum(); i++) { 48353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Elf32_Phdr& hdr = oat_file_->GetProgramHeader(i); 484a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light if (hdr.p_vaddr != 0 && hdr.p_vaddr != hdr.p_offset) { 485a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light need_fixup = true; 48653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light hdr.p_vaddr += delta_; 48753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 488a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light if (hdr.p_paddr != 0 && hdr.p_paddr != hdr.p_offset) { 489a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light need_fixup = true; 49053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light hdr.p_paddr += delta_; 49153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 49253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 493a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light if (!need_fixup) { 494a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light // This was never passed through ElfFixup so all headers/symbols just have their offset as 495a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light // their addr. Therefore we do not need to update these parts. 496a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light return true; 497a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } 498a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light t.NewTiming("Fixup Section Headers"); 49953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light for (unsigned int i = 0; i < oat_file_->GetSectionHeaderNum(); i++) { 50053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Elf32_Shdr& hdr = oat_file_->GetSectionHeader(i); 50153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (hdr.sh_addr != 0) { 50253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light hdr.sh_addr += delta_; 50353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 50453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 50553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 506a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light t.NewTiming("Fixup Dynamics"); 50753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light for (Elf32_Word i = 0; i < oat_file_->GetDynamicNum(); i++) { 50853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Elf32_Dyn& dyn = oat_file_->GetDynamic(i); 50953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (IsDynamicSectionPointer(dyn.d_tag, oat_file_->GetHeader().e_machine)) { 51053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light dyn.d_un.d_ptr += delta_; 51153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 51253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 51353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 51453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light t.NewTiming("Fixup Elf Symbols"); 51553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Fixup dynsym 51653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Elf32_Shdr* dynsym_sec = oat_file_->FindSectionByName(".dynsym"); 51753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(dynsym_sec != nullptr); 51853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!PatchSymbols(dynsym_sec)) { 51953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 52053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 52153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 52253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Fixup symtab 52353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Elf32_Shdr* symtab_sec = oat_file_->FindSectionByName(".symtab"); 52453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (symtab_sec != nullptr) { 52553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!PatchSymbols(symtab_sec)) { 52653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 52753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 52853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 52953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 53053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 53153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 53253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 53353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightbool PatchOat::PatchSymbols(Elf32_Shdr* section) { 53453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Elf32_Sym* syms = reinterpret_cast<Elf32_Sym*>(oat_file_->Begin() + section->sh_offset); 53553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const Elf32_Sym* last_sym = 53653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light reinterpret_cast<Elf32_Sym*>(oat_file_->Begin() + section->sh_offset + section->sh_size); 53753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_EQ(section->sh_size % sizeof(Elf32_Sym), 0u) 53853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light << "Symtab section size is not multiple of symbol size"; 53953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light for (; syms < last_sym; syms++) { 54053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uint8_t sttype = ELF32_ST_TYPE(syms->st_info); 54153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Elf32_Word shndx = syms->st_shndx; 54253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (shndx != SHN_ABS && shndx != SHN_COMMON && shndx != SHN_UNDEF && 54353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light (sttype == STT_FUNC || sttype == STT_OBJECT)) { 54453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_NE(syms->st_value, 0u); 54553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light syms->st_value += delta_; 54653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 54753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 54853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 54953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 55053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 55153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightbool PatchOat::PatchTextSection() { 55253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Elf32_Shdr* patches_sec = oat_file_->FindSectionByName(".oat_patches"); 55353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (patches_sec == nullptr) { 554a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light LOG(ERROR) << ".oat_patches section not found. Aborting patch"; 55553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 55653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 55753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light DCHECK(CheckOatFile()) << "Oat file invalid"; 55853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_EQ(patches_sec->sh_type, SHT_OAT_PATCH) << "Unexpected type of .oat_patches"; 55953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t* patches = reinterpret_cast<uintptr_t*>(oat_file_->Begin() + patches_sec->sh_offset); 56053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t* patches_end = patches + (patches_sec->sh_size/sizeof(uintptr_t)); 56153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Elf32_Shdr* oat_text_sec = oat_file_->FindSectionByName(".text"); 56253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(oat_text_sec != nullptr); 56353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light byte* to_patch = oat_file_->Begin() + oat_text_sec->sh_offset; 56453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t to_patch_end = reinterpret_cast<uintptr_t>(to_patch) + oat_text_sec->sh_size; 56553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 56653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light for (; patches < patches_end; patches++) { 56753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_LT(*patches, oat_text_sec->sh_size) << "Bad Patch"; 56853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uint32_t* patch_loc = reinterpret_cast<uint32_t*>(to_patch + *patches); 56953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_LT(reinterpret_cast<uintptr_t>(patch_loc), to_patch_end); 57053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light *patch_loc += delta_; 57153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 57253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 57353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 57453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 57553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 57653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightstatic int orig_argc; 57753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightstatic char** orig_argv; 57853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 57953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightstatic std::string CommandLine() { 58053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::vector<std::string> command; 58153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light for (int i = 0; i < orig_argc; ++i) { 58253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light command.push_back(orig_argv[i]); 58353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 58453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return Join(command, ' '); 58553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 58653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 58753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightstatic void UsageErrorV(const char* fmt, va_list ap) { 58853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string error; 58953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light StringAppendV(&error, fmt, ap); 59053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << error; 59153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 59253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 59353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightstatic void UsageError(const char* fmt, ...) { 59453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light va_list ap; 59553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light va_start(ap, fmt); 59653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageErrorV(fmt, ap); 59753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light va_end(ap); 59853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 59953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 60053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightstatic void Usage(const char *fmt, ...) { 60153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light va_list ap; 60253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light va_start(ap, fmt); 60353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageErrorV(fmt, ap); 60453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light va_end(ap); 60553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 60653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError("Command: %s", CommandLine().c_str()); 60753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError("Usage: patchoat [options]..."); 60853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 60953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --instruction-set=<isa>: Specifies the instruction set the patched code is"); 61053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" compiled for. Required if you use --input-oat-location"); 61153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 61253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --input-oat-file=<file.oat>: Specifies the exact filename of the oat file to be"); 61353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" patched."); 61453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 61553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --input-oat-fd=<file-descriptor>: Specifies the file-descriptor of the oat file"); 61653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" to be patched."); 61753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 61853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --input-oat-location=<file.oat>: Specifies the 'location' to read the patched"); 61953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" oat file from. If used one must also supply the --instruction-set"); 62053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 62153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --input-image-location=<file.art>: Specifies the 'location' of the image file to"); 62253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" be patched. If --instruction-set is not given it will use the instruction set"); 62353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" extracted from the --input-oat-file."); 62453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 62553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --output-oat-file=<file.oat>: Specifies the exact file to write the patched oat"); 62653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" file to."); 62753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 62853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --output-oat-location=<file.oat>: Specifies the 'location' to write the patched"); 62953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" oat file to. If used one must also specify the --instruction-set"); 63053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 63153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --output-oat-fd=<file-descriptor>: Specifies the file-descriptor to write the"); 63253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" the patched oat file to."); 63353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 63453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --output-image-file=<file.art>: Specifies the exact file to write the patched"); 63553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" image file to."); 63653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 63753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --output-image-fd=<file-descriptor>: Specifies the file-descriptor to write the"); 63853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" the patched image file to."); 63953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 64053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --output-image-location=<file.art>: Specifies the 'location' to write the patched"); 64153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" image file to. If used one must also specify the --instruction-set"); 64253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 64353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --orig-base-offset=<original-base-offset>: Specify the base offset the input file"); 64453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" was compiled with. This is needed if one is specifying a --base-offset"); 64553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 64653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --base-offset=<new-base-offset>: Specify the base offset we will repatch the"); 64753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" given files to use. This requires that --orig-base-offset is also given."); 64853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 64953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --base-offset-delta=<delta>: Specify the amount to change the old base-offset by."); 65053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" This value may be negative."); 65153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 65253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --patched-image-file=<file.art>: Use the same patch delta as was used to patch"); 65353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" the given image file."); 65453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 65553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --patched-image-location=<file.art>: Use the same patch delta as was used to"); 65653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" patch the given image location. If used one must also specify the"); 657a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light UsageError(" --instruction-set flag. It will search for this image in the same way that"); 658a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light UsageError(" is done when loading one."); 65953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 66053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --dump-timings: dump out patch timing information"); 66153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 66253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --no-dump-timings: do not dump out patch timing information"); 66353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 66453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 66553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light exit(EXIT_FAILURE); 66653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 66753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 668eefbe39799126afdf7d315a79359b9da23d1cef5Alex Lightstatic bool ReadBaseDelta(const char* name, off_t* delta, std::string* error_msg) { 66953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(name != nullptr); 67053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(delta != nullptr); 67153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::unique_ptr<File> file; 67253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (OS::FileExists(name)) { 67353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light file.reset(OS::OpenFileForReading(name)); 67453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (file.get() == nullptr) { 675eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light *error_msg = "Failed to open file %s for reading"; 67653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 67753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 67853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 679eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light *error_msg = "File %s does not exist"; 68053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 68153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 68253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(file.get() != nullptr); 68353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light ImageHeader hdr; 68453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (sizeof(hdr) != file->Read(reinterpret_cast<char*>(&hdr), sizeof(hdr), 0)) { 685eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light *error_msg = "Failed to read file %s"; 68653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 68753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 68853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!hdr.IsValid()) { 689eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light *error_msg = "%s does not contain a valid image header."; 69053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 69153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 69253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light *delta = hdr.GetPatchDelta(); 69353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 69453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 69553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 69653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightstatic File* CreateOrOpen(const char* name, bool* created) { 69753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (OS::FileExists(name)) { 69853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light *created = false; 69953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return OS::OpenFileReadWrite(name); 70053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 70153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light *created = true; 70253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return OS::CreateEmptyFile(name); 70353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 70453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 70553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 706eefbe39799126afdf7d315a79359b9da23d1cef5Alex Lightstatic int patchoat(int argc, char **argv) { 70753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light InitLogging(argv); 70853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const bool debug = kIsDebugBuild; 70953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light orig_argc = argc; 71053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light orig_argv = argv; 71153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light TimingLogger timings("patcher", false, false); 71253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 71353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light InitLogging(argv); 71453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 71553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Skip over the command name. 71653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light argv++; 71753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light argc--; 71853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 71953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (argc == 0) { 72053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("No arguments specified"); 72153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 72253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 72353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light timings.StartTiming("Patchoat"); 72453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 72553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // cmd line args 72653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool isa_set = false; 72753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light InstructionSet isa = kNone; 72853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string input_oat_filename; 72953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string input_oat_location; 73053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light int input_oat_fd = -1; 73153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool have_input_oat = false; 73253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string input_image_location; 73353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string output_oat_filename; 73453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string output_oat_location; 73553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light int output_oat_fd = -1; 73653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool have_output_oat = false; 73753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string output_image_filename; 73853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string output_image_location; 73953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light int output_image_fd = -1; 74053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool have_output_image = false; 74153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t base_offset = 0; 74253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool base_offset_set = false; 74353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t orig_base_offset = 0; 74453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool orig_base_offset_set = false; 74553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light off_t base_delta = 0; 74653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool base_delta_set = false; 74753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string patched_image_filename; 74853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string patched_image_location; 74953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool dump_timings = kIsDebugBuild; 75053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 75153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light for (int i = 0; i < argc; i++) { 75253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const StringPiece option(argv[i]); 75353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const bool log_options = false; 75453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (log_options) { 75553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(INFO) << "patchoat: option[" << i << "]=" << argv[i]; 75653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 757eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light // TODO: GetInstructionSetFromString shouldn't LOG(FATAL). 75853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (option.starts_with("--instruction-set=")) { 75953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light isa_set = true; 76053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const char* isa_str = option.substr(strlen("--instruction-set=")).data(); 76153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!strcmp("arm", isa_str)) { 76253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light isa = kArm; 76353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (!strcmp("arm64", isa_str)) { 76453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light isa = kArm64; 76553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (!strcmp("x86", isa_str)) { 76653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light isa = kX86; 76753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (!strcmp("x86_64", isa_str)) { 76853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light isa = kX86_64; 76953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (!strcmp("mips", isa_str)) { 77053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light isa = kMips; 77153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 77253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Unknown instruction set %s", isa_str); 77353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 77453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--input-oat-location=")) { 77553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (have_input_oat) { 77653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Only one of --input-oat-file, --input-oat-location and --input-oat-fd may be used."); 77753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 77853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light have_input_oat = true; 77953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light input_oat_location = option.substr(strlen("--input-oat-location=")).data(); 78053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--input-oat-file=")) { 78153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (have_input_oat) { 78253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Only one of --input-oat-file, --input-oat-location and --input-oat-fd may be used."); 78353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 78453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light have_input_oat = true; 78553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light input_oat_filename = option.substr(strlen("--input-oat-file=")).data(); 78653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--input-oat-fd=")) { 78753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (have_input_oat) { 78853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Only one of --input-oat-file, --input-oat-location and --input-oat-fd may be used."); 78953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 79053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light have_input_oat = true; 79153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const char* oat_fd_str = option.substr(strlen("--input-oat-fd=")).data(); 79253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!ParseInt(oat_fd_str, &input_oat_fd)) { 79353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Failed to parse --input-oat-fd argument '%s' as an integer", oat_fd_str); 79453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 79553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (input_oat_fd < 0) { 79653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("--input-oat-fd pass a negative value %d", input_oat_fd); 79753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 79853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--input-image-location=")) { 79953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light input_image_location = option.substr(strlen("--input-image-location=")).data(); 80053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--output-oat-location=")) { 80153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (have_output_oat) { 80253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Only one of --output-oat-file, --output-oat-location and --output-oat-fd may " 80353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light "be used."); 80453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 80553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light have_output_oat = true; 80653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light output_oat_location = option.substr(strlen("--output-oat-location=")).data(); 80753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--output-oat-file=")) { 80853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (have_output_oat) { 80953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Only one of --output-oat-file, --output-oat-location and --output-oat-fd may " 81053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light "be used."); 81153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 81253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light have_output_oat = true; 81353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light output_oat_filename = option.substr(strlen("--output-oat-file=")).data(); 81453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--output-oat-fd=")) { 81553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (have_output_oat) { 81653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Only one of --output-oat-file, --output-oat-location and --output-oat-fd may " 81753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light "be used."); 81853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 81953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light have_output_oat = true; 82053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const char* oat_fd_str = option.substr(strlen("--output-oat-fd=")).data(); 82153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!ParseInt(oat_fd_str, &output_oat_fd)) { 82253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Failed to parse --output-oat-fd argument '%s' as an integer", oat_fd_str); 82353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 82453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (output_oat_fd < 0) { 82553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("--output-oat-fd pass a negative value %d", output_oat_fd); 82653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 82753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--output-image-location=")) { 82853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (have_output_image) { 82953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Only one of --output-image-file, --output-image-location and --output-image-fd may " 83053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light "be used."); 83153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 83253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light have_output_image = true; 83353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light output_image_location= option.substr(strlen("--output-image-location=")).data(); 83453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--output-image-file=")) { 83553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (have_output_image) { 83653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Only one of --output-image-file, --output-image-location and --output-image-fd may " 83753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light "be used."); 83853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 83953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light have_output_image = true; 84053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light output_image_filename = option.substr(strlen("--output-image-file=")).data(); 84153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--output-image-fd=")) { 84253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (have_output_image) { 84353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Only one of --output-image-file, --output-image-location and --output-image-fd " 84453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light "may be used."); 84553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 84653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light have_output_image = true; 84753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const char* image_fd_str = option.substr(strlen("--output-image-fd=")).data(); 84853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!ParseInt(image_fd_str, &output_image_fd)) { 84953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Failed to parse --output-image-fd argument '%s' as an integer", image_fd_str); 85053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 85153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (output_image_fd < 0) { 85253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("--output-image-fd pass a negative value %d", output_image_fd); 85353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 85453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--orig-base-offset=")) { 85553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const char* orig_base_offset_str = option.substr(strlen("--orig-base-offset=")).data(); 85653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light orig_base_offset_set = true; 85753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!ParseUint(orig_base_offset_str, &orig_base_offset)) { 85853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Failed to parse --orig-base-offset argument '%s' as an uintptr_t", 85953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light orig_base_offset_str); 86053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 86153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--base-offset=")) { 86253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const char* base_offset_str = option.substr(strlen("--base-offset=")).data(); 86353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light base_offset_set = true; 86453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!ParseUint(base_offset_str, &base_offset)) { 86553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Failed to parse --base-offset argument '%s' as an uintptr_t", base_offset_str); 86653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 86753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--base-offset-delta=")) { 86853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const char* base_delta_str = option.substr(strlen("--base-offset-delta=")).data(); 86953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light base_delta_set = true; 87053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!ParseInt(base_delta_str, &base_delta)) { 87153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Failed to parse --base-offset-delta argument '%s' as an off_t", base_delta_str); 87253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 87353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--patched-image-location=")) { 87453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light patched_image_location = option.substr(strlen("--patched-image-location=")).data(); 87553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--patched-image-file=")) { 87653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light patched_image_filename = option.substr(strlen("--patched-image-file=")).data(); 87753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option == "--dump-timings") { 87853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light dump_timings = true; 87953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option == "--no-dump-timings") { 88053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light dump_timings = false; 88153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 88253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Unknown argument %s", option.data()); 88353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 88453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 88553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 88653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light { 88753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Only 1 of these may be set. 88853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uint32_t cnt = 0; 88953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light cnt += (base_delta_set) ? 1 : 0; 89053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light cnt += (base_offset_set && orig_base_offset_set) ? 1 : 0; 89153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light cnt += (!patched_image_filename.empty()) ? 1 : 0; 89253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light cnt += (!patched_image_location.empty()) ? 1 : 0; 89353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (cnt > 1) { 89453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Only one of --base-offset/--orig-base-offset, --base-offset-delta, " 89553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light "--patched-image-filename or --patched-image-location may be used."); 89653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (cnt == 0) { 89753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Must specify --base-offset-delta, --base-offset and --orig-base-offset, " 89853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light "--patched-image-location or --patched-image-file"); 89953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 90053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 90153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 90253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (have_input_oat != have_output_oat) { 90353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Either both input and output oat must be supplied or niether must be."); 90453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 90553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 90653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if ((!input_image_location.empty()) != have_output_image) { 90753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Either both input and output image must be supplied or niether must be."); 90853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 90953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 91053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // We know we have both the input and output so rename for clarity. 91153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool have_image_files = have_output_image; 91253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool have_oat_files = have_output_oat; 91353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 91453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!have_oat_files && !have_image_files) { 91553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Must be patching either an oat or an image file or both."); 91653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 91753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 91853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!have_oat_files && !isa_set) { 91953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Must include ISA if patching an image file without an oat file."); 92053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 92153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 92253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!input_oat_location.empty()) { 92353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!isa_set) { 92453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("specifying a location requires specifying an instruction set"); 92553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 92653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light input_oat_filename = GetSystemImageFilename(input_oat_location.c_str(), isa); 92753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (debug) { 92853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(INFO) << "Using input-oat-file " << input_oat_filename; 92953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 93053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 93153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!output_oat_location.empty()) { 93253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!isa_set) { 93353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("specifying a location requires specifying an instruction set"); 93453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 93553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light output_oat_filename = GetSystemImageFilename(output_oat_location.c_str(), isa); 93653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (debug) { 93753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(INFO) << "Using output-oat-file " << output_oat_filename; 93853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 93953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 94053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!output_image_location.empty()) { 94153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!isa_set) { 94253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("specifying a location requires specifying an instruction set"); 94353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 94453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light output_image_filename = GetSystemImageFilename(output_image_location.c_str(), isa); 94553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (debug) { 94653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(INFO) << "Using output-image-file " << output_image_filename; 94753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 94853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 94953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!patched_image_location.empty()) { 95053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!isa_set) { 95153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("specifying a location requires specifying an instruction set"); 95253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 953a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light std::string system_filename; 954a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light bool has_system = false; 955a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light std::string cache_filename; 956a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light bool has_cache = false; 957a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light bool has_android_data_unused = false; 958a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light if (!gc::space::ImageSpace::FindImageFilename(patched_image_location.c_str(), isa, 959a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light &system_filename, &has_system, &cache_filename, 960a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light &has_android_data_unused, &has_cache)) { 961a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light Usage("Unable to determine image file for location %s", patched_image_location.c_str()); 962a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } 963a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light if (has_cache) { 964a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light patched_image_filename = cache_filename; 965a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } else if (has_system) { 966a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light LOG(WARNING) << "Only image file found was in /system for image location " 967a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light << patched_image_location; 968a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light patched_image_filename = system_filename; 969a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } else { 970a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light Usage("Unable to determine image file for location %s", patched_image_location.c_str()); 971a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } 97253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (debug) { 97353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(INFO) << "Using patched-image-file " << patched_image_filename; 97453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 97553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 97653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 97753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!base_delta_set) { 97853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (orig_base_offset_set && base_offset_set) { 97953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light base_delta_set = true; 98053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light base_delta = base_offset - orig_base_offset; 98153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (!patched_image_filename.empty()) { 98253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light base_delta_set = true; 98353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string error_msg; 984eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light if (!ReadBaseDelta(patched_image_filename.c_str(), &base_delta, &error_msg)) { 98553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage(error_msg.c_str(), patched_image_filename.c_str()); 98653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 98753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 98853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (base_offset_set) { 98953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Unable to determine original base offset."); 99053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 99153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Must supply a desired new offset or delta."); 99253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 99353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 99453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 99553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 99653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!IsAligned<kPageSize>(base_delta)) { 99753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Base offset/delta must be alligned to a pagesize (0x%08x) boundary.", kPageSize); 99853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 99953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 100053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Do we need to cleanup output files if we fail? 100153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool new_image_out = false; 100253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool new_oat_out = false; 100353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 100453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::unique_ptr<File> input_oat; 100553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::unique_ptr<File> output_oat; 100653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::unique_ptr<File> output_image; 100753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 100853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (have_image_files) { 100953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(!input_image_location.empty()); 101053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 101153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (output_image_fd != -1) { 101253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light output_image.reset(new File(output_image_fd, output_image_filename)); 101353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 101453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(!output_image_filename.empty()); 101553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light output_image.reset(CreateOrOpen(output_image_filename.c_str(), &new_image_out)); 101653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 101753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 101853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(output_image_filename.empty() && output_image_fd == -1 && input_image_location.empty()); 101953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 102053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 102153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (have_oat_files) { 102253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (input_oat_fd != -1) { 102353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light input_oat.reset(new File(input_oat_fd, input_oat_filename)); 102453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 102553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(!input_oat_filename.empty()); 102653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light input_oat.reset(OS::OpenFileForReading(input_oat_filename.c_str())); 10271c83cbc4a817acbd7f9abb5b29a2d418a958e6a1Andreas Gampe if (input_oat.get() == nullptr) { 10281c83cbc4a817acbd7f9abb5b29a2d418a958e6a1Andreas Gampe LOG(ERROR) << "Could not open input oat file: " << strerror(errno); 10291c83cbc4a817acbd7f9abb5b29a2d418a958e6a1Andreas Gampe } 103053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 103153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 103253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (output_oat_fd != -1) { 103353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light output_oat.reset(new File(output_oat_fd, output_oat_filename)); 1034a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } else if (output_oat_filename == input_oat_filename) { 1035a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light // This could be a wierd situation, since we'd be writting from an mmap'd copy of this file. 1036a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light // Lets just unlink it. 1037a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light if (0 != unlink(input_oat_filename.c_str())) { 1038a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light PLOG(ERROR) << "Could not unlink " << input_oat_filename << " to make room for output"; 1039a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light return false; 1040a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } 1041a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light output_oat.reset(OS::CreateEmptyFile(output_oat_filename.c_str())); 104253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 104353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(!output_oat_filename.empty()); 104453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light output_oat.reset(CreateOrOpen(output_oat_filename.c_str(), &new_oat_out)); 104553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 104653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 104753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 104853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light auto cleanup = [&output_image_filename, &output_oat_filename, 104953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light &new_oat_out, &new_image_out, &timings, &dump_timings](bool success) { 105053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light timings.EndTiming(); 105153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!success) { 105253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (new_oat_out) { 105353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(!output_oat_filename.empty()); 105453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light unlink(output_oat_filename.c_str()); 105553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 105653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (new_image_out) { 105753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(!output_image_filename.empty()); 105853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light unlink(output_image_filename.c_str()); 105953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 106053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 106153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (dump_timings) { 106253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(INFO) << Dumpable<TimingLogger>(timings); 106353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 106453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light }; 106553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 106653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (debug) { 1067a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light LOG(INFO) << "moving offset by " << base_delta 1068a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light << " (0x" << std::hex << base_delta << ") bytes or " 1069a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light << std::dec << (base_delta/kPageSize) << " pages."; 107053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 107153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 107253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool ret; 107353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (have_image_files && have_oat_files) { 107453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light TimingLogger::ScopedTiming pt("patch image and oat", &timings); 107553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light ret = PatchOat::Patch(input_oat.get(), input_image_location, base_delta, 1076eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light output_oat.get(), output_image.get(), isa, &timings); 107753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (have_oat_files) { 107853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light TimingLogger::ScopedTiming pt("patch oat", &timings); 1079eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light ret = PatchOat::Patch(input_oat.get(), base_delta, output_oat.get(), &timings); 108053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 108153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light TimingLogger::ScopedTiming pt("patch image", &timings); 108253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(have_image_files); 1083eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light ret = PatchOat::Patch(input_image_location, base_delta, output_image.get(), isa, &timings); 108453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 108553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light cleanup(ret); 1086a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light sync(); 108753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return (ret) ? EXIT_SUCCESS : EXIT_FAILURE; 108853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 108953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 109053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} // namespace art 109153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 109253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightint main(int argc, char **argv) { 109353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return art::patchoat(argc, argv); 109453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 1095