patchoat.cc revision 3c13a794845e0cf7887e33b2ec20de7e6ba85f8f
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 69cf4bf386ef3f527825c70e01130b9276da4f786aAlex Lightstatic bool LocationToFilename(const std::string& location, InstructionSet isa, 70cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light std::string* filename) { 71cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light bool has_system = false; 72cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light bool has_cache = false; 73cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light // image_location = /system/framework/boot.art 74cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light // system_image_location = /system/framework/<image_isa>/boot.art 75cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light std::string system_filename(GetSystemImageFilename(location.c_str(), isa)); 76cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light if (OS::FileExists(system_filename.c_str())) { 77cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light has_system = true; 78cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } 79cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light 80cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light bool have_android_data = false; 81cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light bool dalvik_cache_exists = false; 823c13a794845e0cf7887e33b2ec20de7e6ba85f8fAndreas Gampe bool is_global_cache = false; 83cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light std::string dalvik_cache; 84cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light GetDalvikCache(GetInstructionSetString(isa), false, &dalvik_cache, 853c13a794845e0cf7887e33b2ec20de7e6ba85f8fAndreas Gampe &have_android_data, &dalvik_cache_exists, &is_global_cache); 86cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light 87cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light std::string cache_filename; 88cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light if (have_android_data && dalvik_cache_exists) { 89cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light // Always set output location even if it does not exist, 90cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light // so that the caller knows where to create the image. 91cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light // 92cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light // image_location = /system/framework/boot.art 93cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light // *image_filename = /data/dalvik-cache/<image_isa>/boot.art 94cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light std::string error_msg; 95cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light if (GetDalvikCacheFilename(location.c_str(), dalvik_cache.c_str(), 96cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light &cache_filename, &error_msg)) { 97cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light has_cache = true; 98cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } 99cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } 100cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light if (has_system) { 101cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light *filename = system_filename; 102cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light return true; 103cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } else if (has_cache) { 104cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light *filename = cache_filename; 105cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light return true; 106cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } else { 107cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light return false; 108cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } 109cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light} 110cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light 11153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightbool PatchOat::Patch(const std::string& image_location, off_t delta, 11253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light File* output_image, InstructionSet isa, 113eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light TimingLogger* timings) { 11453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(Runtime::Current() == nullptr); 11553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(output_image != nullptr); 11653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_GE(output_image->Fd(), 0); 11753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(!image_location.empty()) << "image file must have a filename."; 11853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_NE(isa, kNone); 11953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 120eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light TimingLogger::ScopedTiming t("Runtime Setup", timings); 12153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const char *isa_name = GetInstructionSetString(isa); 122cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light std::string image_filename; 123cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light if (!LocationToFilename(image_location, isa, &image_filename)) { 124cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light LOG(ERROR) << "Unable to find image at location " << image_location; 125cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light return false; 126cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } 12753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::unique_ptr<File> input_image(OS::OpenFileForReading(image_filename.c_str())); 12853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (input_image.get() == nullptr) { 129cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light LOG(ERROR) << "unable to open input image file at " << image_filename 130cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light << " for location " << image_location; 13153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 13253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 13353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light int64_t image_len = input_image->GetLength(); 13453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (image_len < 0) { 13553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "Error while getting image length"; 13653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 13753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 13853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light ImageHeader image_header; 13953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (sizeof(image_header) != input_image->Read(reinterpret_cast<char*>(&image_header), 14053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light sizeof(image_header), 0)) { 14153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "Unable to read image header from image file " << input_image->GetPath(); 14253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 14353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 14453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 14553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Set up the runtime 146e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers RuntimeOptions options; 14753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light NoopCompilerCallbacks callbacks; 14853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light options.push_back(std::make_pair("compilercallbacks", &callbacks)); 14953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string img = "-Ximage:" + image_location; 15053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light options.push_back(std::make_pair(img.c_str(), nullptr)); 15153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light options.push_back(std::make_pair("imageinstructionset", reinterpret_cast<const void*>(isa_name))); 15253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!Runtime::Create(options, false)) { 15353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "Unable to initialize runtime"; 15453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 15553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 15653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start, 15753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // give it away now and then switch to a more manageable ScopedObjectAccess. 15853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Thread::Current()->TransitionFromRunnableToSuspended(kNative); 15953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light ScopedObjectAccess soa(Thread::Current()); 16053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 16153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light t.NewTiming("Image and oat Patching setup"); 16253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Create the map where we will write the image patches to. 163eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light std::string error_msg; 16453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::unique_ptr<MemMap> image(MemMap::MapFile(image_len, PROT_READ | PROT_WRITE, MAP_PRIVATE, 16553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light input_image->Fd(), 0, 16653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light input_image->GetPath().c_str(), 16753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light &error_msg)); 16853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (image.get() == nullptr) { 16953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "unable to map image file " << input_image->GetPath() << " : " << error_msg; 17053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 17153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 17253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light gc::space::ImageSpace* ispc = Runtime::Current()->GetHeap()->GetImageSpace(); 17353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 17453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light PatchOat p(image.release(), ispc->GetLiveBitmap(), ispc->GetMemMap(), 17553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light delta, timings); 17653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light t.NewTiming("Patching files"); 17753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!p.PatchImage()) { 178a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light LOG(ERROR) << "Failed to patch image file " << input_image->GetPath(); 17953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 18053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 18153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 18253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light t.NewTiming("Writing files"); 18353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!p.WriteImage(output_image)) { 18453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 18553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 18653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 18753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 18853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 18953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightbool PatchOat::Patch(const File* input_oat, const std::string& image_location, off_t delta, 19053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light File* output_oat, File* output_image, InstructionSet isa, 191eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light TimingLogger* timings) { 19253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(Runtime::Current() == nullptr); 19353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(output_image != nullptr); 19453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_GE(output_image->Fd(), 0); 19553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(input_oat != nullptr); 19653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(output_oat != nullptr); 19753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_GE(input_oat->Fd(), 0); 19853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_GE(output_oat->Fd(), 0); 19953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(!image_location.empty()) << "image file must have a filename."; 20053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 201eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light TimingLogger::ScopedTiming t("Runtime Setup", timings); 20253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 20353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (isa == kNone) { 20453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Elf32_Ehdr elf_hdr; 20553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (sizeof(elf_hdr) != input_oat->Read(reinterpret_cast<char*>(&elf_hdr), sizeof(elf_hdr), 0)) { 20653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "unable to read elf header"; 20753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 20853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 20953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light isa = ElfISAToInstructionSet(elf_hdr.e_machine); 21053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 21153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const char* isa_name = GetInstructionSetString(isa); 212cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light std::string image_filename; 213cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light if (!LocationToFilename(image_location, isa, &image_filename)) { 214cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light LOG(ERROR) << "Unable to find image at location " << image_location; 215cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light return false; 216cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } 21753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::unique_ptr<File> input_image(OS::OpenFileForReading(image_filename.c_str())); 21853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (input_image.get() == nullptr) { 219cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light LOG(ERROR) << "unable to open input image file at " << image_filename 220cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light << " for location " << image_location; 22153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 22253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 22353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light int64_t image_len = input_image->GetLength(); 22453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (image_len < 0) { 22553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "Error while getting image length"; 22653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 22753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 22853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light ImageHeader image_header; 22953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (sizeof(image_header) != input_image->Read(reinterpret_cast<char*>(&image_header), 23053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light sizeof(image_header), 0)) { 23153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "Unable to read image header from image file " << input_image->GetPath(); 23253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 23353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 23453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Set up the runtime 235e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers RuntimeOptions options; 23653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light NoopCompilerCallbacks callbacks; 23753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light options.push_back(std::make_pair("compilercallbacks", &callbacks)); 23853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string img = "-Ximage:" + image_location; 23953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light options.push_back(std::make_pair(img.c_str(), nullptr)); 24053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light options.push_back(std::make_pair("imageinstructionset", reinterpret_cast<const void*>(isa_name))); 24153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!Runtime::Create(options, false)) { 24253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "Unable to initialize runtime"; 24353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 24453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 24553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start, 24653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // give it away now and then switch to a more manageable ScopedObjectAccess. 24753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Thread::Current()->TransitionFromRunnableToSuspended(kNative); 24853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light ScopedObjectAccess soa(Thread::Current()); 24953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 25053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light t.NewTiming("Image and oat Patching setup"); 25153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Create the map where we will write the image patches to. 252eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light std::string error_msg; 25353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::unique_ptr<MemMap> image(MemMap::MapFile(image_len, PROT_READ | PROT_WRITE, MAP_PRIVATE, 25453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light input_image->Fd(), 0, 25553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light input_image->GetPath().c_str(), 25653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light &error_msg)); 25753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (image.get() == nullptr) { 25853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "unable to map image file " << input_image->GetPath() << " : " << error_msg; 25953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 26053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 26153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light gc::space::ImageSpace* ispc = Runtime::Current()->GetHeap()->GetImageSpace(); 26253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 26353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::unique_ptr<ElfFile> elf(ElfFile::Open(const_cast<File*>(input_oat), 26453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light PROT_READ | PROT_WRITE, MAP_PRIVATE, &error_msg)); 26553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (elf.get() == nullptr) { 26653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "unable to open oat file " << input_oat->GetPath() << " : " << error_msg; 26753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 26853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 26953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 27053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light PatchOat p(elf.release(), image.release(), ispc->GetLiveBitmap(), ispc->GetMemMap(), 27153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light delta, timings); 27253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light t.NewTiming("Patching files"); 27353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!p.PatchElf()) { 274a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light LOG(ERROR) << "Failed to patch oat file " << input_oat->GetPath(); 27553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 27653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 27753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!p.PatchImage()) { 278a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light LOG(ERROR) << "Failed to patch image file " << input_image->GetPath(); 27953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 28053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 28153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 28253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light t.NewTiming("Writing files"); 28353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!p.WriteElf(output_oat)) { 28453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 28553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 28653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!p.WriteImage(output_image)) { 28753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 28853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 28953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 29053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 29153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 29253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightbool PatchOat::WriteElf(File* out) { 293eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light TimingLogger::ScopedTiming t("Writing Elf File", timings_); 294a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light 29553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(oat_file_.get() != nullptr); 29653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(out != nullptr); 29753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light size_t expect = oat_file_->Size(); 29853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (out->WriteFully(reinterpret_cast<char*>(oat_file_->Begin()), expect) && 29953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light out->SetLength(expect) == 0) { 30053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 30153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 30253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "Writing to oat file " << out->GetPath() << " failed."; 30353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 30453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 30553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 30653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 30753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightbool PatchOat::WriteImage(File* out) { 308eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light TimingLogger::ScopedTiming t("Writing image File", timings_); 309a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light std::string error_msg; 310a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light 311cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light ScopedFlock img_flock; 312cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light img_flock.Init(out, &error_msg); 313a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light 31453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(image_ != nullptr); 31553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(out != nullptr); 31653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light size_t expect = image_->Size(); 31753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (out->WriteFully(reinterpret_cast<char*>(image_->Begin()), expect) && 31853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light out->SetLength(expect) == 0) { 31953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 32053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 32153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "Writing to image file " << out->GetPath() << " failed."; 32253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 32353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 32453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 32553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 32653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightbool PatchOat::PatchImage() { 32753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light ImageHeader* image_header = reinterpret_cast<ImageHeader*>(image_->Begin()); 32853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_GT(image_->Size(), sizeof(ImageHeader)); 32953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // These are the roots from the original file. 33053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light mirror::Object* img_roots = image_header->GetImageRoots(); 33153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light image_header->RelocateImage(delta_); 33253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 33353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light VisitObject(img_roots); 33453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!image_header->IsValid()) { 33553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "reloction renders image header invalid"; 33653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 33753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 33853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 33953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light { 340eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light TimingLogger::ScopedTiming t("Walk Bitmap", timings_); 34153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Walk the bitmap. 34253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_); 34353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bitmap_->Walk(PatchOat::BitmapCallback, this); 34453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 34553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 34653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 34753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 34853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightbool PatchOat::InHeap(mirror::Object* o) { 34953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t begin = reinterpret_cast<uintptr_t>(heap_->Begin()); 35053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t end = reinterpret_cast<uintptr_t>(heap_->End()); 35153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t obj = reinterpret_cast<uintptr_t>(o); 35253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return o == nullptr || (begin <= obj && obj < end); 35353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 35453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 35553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightvoid PatchOat::PatchVisitor::operator() (mirror::Object* obj, MemberOffset off, 35653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool is_static_unused) const { 35753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light mirror::Object* referent = obj->GetFieldObject<mirror::Object, kVerifyNone>(off); 35853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light DCHECK(patcher_->InHeap(referent)) << "Referent is not in the heap."; 35953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light mirror::Object* moved_object = patcher_->RelocatedAddressOf(referent); 36053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(off, moved_object); 36153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 36253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 36353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightvoid PatchOat::PatchVisitor::operator() (mirror::Class* cls, mirror::Reference* ref) const { 36453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light MemberOffset off = mirror::Reference::ReferentOffset(); 36553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light mirror::Object* referent = ref->GetReferent(); 36653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light DCHECK(patcher_->InHeap(referent)) << "Referent is not in the heap."; 36753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light mirror::Object* moved_object = patcher_->RelocatedAddressOf(referent); 36853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(off, moved_object); 36953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 37053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 37153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightmirror::Object* PatchOat::RelocatedCopyOf(mirror::Object* obj) { 37253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (obj == nullptr) { 37353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return nullptr; 37453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 37553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light DCHECK_GT(reinterpret_cast<uintptr_t>(obj), reinterpret_cast<uintptr_t>(heap_->Begin())); 37653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light DCHECK_LT(reinterpret_cast<uintptr_t>(obj), reinterpret_cast<uintptr_t>(heap_->End())); 37753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t heap_off = 37853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light reinterpret_cast<uintptr_t>(obj) - reinterpret_cast<uintptr_t>(heap_->Begin()); 37953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light DCHECK_LT(heap_off, image_->Size()); 38053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return reinterpret_cast<mirror::Object*>(image_->Begin() + heap_off); 38153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 38253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 38353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightmirror::Object* PatchOat::RelocatedAddressOf(mirror::Object* obj) { 38453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (obj == nullptr) { 38553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return nullptr; 38653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 38753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return reinterpret_cast<mirror::Object*>(reinterpret_cast<byte*>(obj) + delta_); 38853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 38953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 39053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 39153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light// Called by BitmapCallback 39253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightvoid PatchOat::VisitObject(mirror::Object* object) { 39353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light mirror::Object* copy = RelocatedCopyOf(object); 39453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(copy != nullptr); 39553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (kUseBakerOrBrooksReadBarrier) { 39653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light object->AssertReadBarrierPointer(); 39753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (kUseBrooksReadBarrier) { 39853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light mirror::Object* moved_to = RelocatedAddressOf(object); 39953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light copy->SetReadBarrierPointer(moved_to); 40053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light DCHECK_EQ(copy->GetReadBarrierPointer(), moved_to); 40153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 40253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 40353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light PatchOat::PatchVisitor visitor(this, copy); 40453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light object->VisitReferences<true, kVerifyNone>(visitor, visitor); 40553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (object->IsArtMethod<kVerifyNone>()) { 40653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light FixupMethod(static_cast<mirror::ArtMethod*>(object), 40753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light static_cast<mirror::ArtMethod*>(copy)); 40853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 40953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 41053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 41153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightvoid PatchOat::FixupMethod(mirror::ArtMethod* object, mirror::ArtMethod* copy) { 41253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Just update the entry points if it looks like we should. 413eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light // TODO: sanity check all the pointers' values 41453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t portable = reinterpret_cast<uintptr_t>( 41553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light object->GetEntryPointFromPortableCompiledCode<kVerifyNone>()); 41653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (portable != 0) { 41753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light copy->SetEntryPointFromPortableCompiledCode(reinterpret_cast<void*>(portable + delta_)); 41853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 41953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t quick= reinterpret_cast<uintptr_t>( 42053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light object->GetEntryPointFromQuickCompiledCode<kVerifyNone>()); 42153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (quick != 0) { 42253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light copy->SetEntryPointFromQuickCompiledCode(reinterpret_cast<void*>(quick + delta_)); 42353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 42453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t interpreter = reinterpret_cast<uintptr_t>( 42553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light object->GetEntryPointFromInterpreter<kVerifyNone>()); 42653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (interpreter != 0) { 42753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light copy->SetEntryPointFromInterpreter( 42853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light reinterpret_cast<mirror::EntryPointFromInterpreter*>(interpreter + delta_)); 42953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 43053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 43153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t native_method = reinterpret_cast<uintptr_t>(object->GetNativeMethod()); 43253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (native_method != 0) { 43353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light copy->SetNativeMethod(reinterpret_cast<void*>(native_method + delta_)); 43453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 43553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 43653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t native_gc_map = reinterpret_cast<uintptr_t>(object->GetNativeGcMap()); 43753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (native_gc_map != 0) { 43853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light copy->SetNativeGcMap(reinterpret_cast<uint8_t*>(native_gc_map + delta_)); 43953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 44053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 44153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 442eefbe39799126afdf7d315a79359b9da23d1cef5Alex Lightbool PatchOat::Patch(File* input_oat, off_t delta, File* output_oat, TimingLogger* timings) { 44353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(input_oat != nullptr); 44453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(output_oat != nullptr); 44553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_GE(input_oat->Fd(), 0); 44653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_GE(output_oat->Fd(), 0); 447eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light TimingLogger::ScopedTiming t("Setup Oat File Patching", timings); 44853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 44953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string error_msg; 45053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::unique_ptr<ElfFile> elf(ElfFile::Open(const_cast<File*>(input_oat), 45153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light PROT_READ | PROT_WRITE, MAP_PRIVATE, &error_msg)); 45253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (elf.get() == nullptr) { 45353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << "unable to open oat file " << input_oat->GetPath() << " : " << error_msg; 45453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 45553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 45653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 45753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light PatchOat p(elf.release(), delta, timings); 45853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light t.NewTiming("Patch Oat file"); 45953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!p.PatchElf()) { 46053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 46153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 46253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 46353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light t.NewTiming("Writing oat file"); 46453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!p.WriteElf(output_oat)) { 46553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 46653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 46753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 46853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 46953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 4704b0d2d99b596eebd6da45679896d3af54bc5a935Alex Lighttemplate <typename ptr_t> 4714b0d2d99b596eebd6da45679896d3af54bc5a935Alex Lightbool PatchOat::CheckOatFile(const Elf32_Shdr& patches_sec) { 4724b0d2d99b596eebd6da45679896d3af54bc5a935Alex Light if (patches_sec.sh_type != SHT_OAT_PATCH) { 47353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 47453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 4754b0d2d99b596eebd6da45679896d3af54bc5a935Alex Light ptr_t* patches = reinterpret_cast<ptr_t*>(oat_file_->Begin() + patches_sec.sh_offset); 4764b0d2d99b596eebd6da45679896d3af54bc5a935Alex Light ptr_t* patches_end = patches + (patches_sec.sh_size / sizeof(ptr_t)); 47753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Elf32_Shdr* oat_data_sec = oat_file_->FindSectionByName(".rodata"); 47853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Elf32_Shdr* oat_text_sec = oat_file_->FindSectionByName(".text"); 47953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (oat_data_sec == nullptr) { 48053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 48153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 48253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (oat_text_sec == nullptr) { 48353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 48453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 48553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (oat_text_sec->sh_offset <= oat_data_sec->sh_offset) { 48653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 48753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 48853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 48953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light for (; patches < patches_end; patches++) { 49053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (oat_text_sec->sh_size <= *patches) { 49153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 49253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 49353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 49453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 49553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 49653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 49753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 498a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Lightbool PatchOat::PatchOatHeader() { 499a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light Elf32_Shdr *rodata_sec = oat_file_->FindSectionByName(".rodata"); 500a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light if (rodata_sec == nullptr) { 501a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light return false; 502a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } 503a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light OatHeader* oat_header = reinterpret_cast<OatHeader*>(oat_file_->Begin() + rodata_sec->sh_offset); 504a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light if (!oat_header->IsValid()) { 505a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light LOG(ERROR) << "Elf file " << oat_file_->GetFile().GetPath() << " has an invalid oat header"; 506a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light return false; 507a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } 508a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light oat_header->RelocateOat(delta_); 509a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light return true; 510a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light} 511a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light 51253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightbool PatchOat::PatchElf() { 513a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light TimingLogger::ScopedTiming t("Fixup Elf Text Section", timings_); 514a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light if (!PatchTextSection()) { 515a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light return false; 516a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } 517a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light 518a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light if (!PatchOatHeader()) { 519a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light return false; 520a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } 521a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light 522a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light bool need_fixup = false; 523a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light t.NewTiming("Fixup Elf Headers"); 52453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Fixup Phdr's 52553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light for (unsigned int i = 0; i < oat_file_->GetProgramHeaderNum(); i++) { 526daab38ca60c5b91787e29c87a161a2bb8c1b6f11Andreas Gampe Elf32_Phdr* hdr = oat_file_->GetProgramHeader(i); 527daab38ca60c5b91787e29c87a161a2bb8c1b6f11Andreas Gampe CHECK(hdr != nullptr); 528daab38ca60c5b91787e29c87a161a2bb8c1b6f11Andreas Gampe if (hdr->p_vaddr != 0 && hdr->p_vaddr != hdr->p_offset) { 529a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light need_fixup = true; 530daab38ca60c5b91787e29c87a161a2bb8c1b6f11Andreas Gampe hdr->p_vaddr += delta_; 53153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 532daab38ca60c5b91787e29c87a161a2bb8c1b6f11Andreas Gampe if (hdr->p_paddr != 0 && hdr->p_paddr != hdr->p_offset) { 533a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light need_fixup = true; 534daab38ca60c5b91787e29c87a161a2bb8c1b6f11Andreas Gampe hdr->p_paddr += delta_; 53553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 53653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 537a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light if (!need_fixup) { 538a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light // This was never passed through ElfFixup so all headers/symbols just have their offset as 539a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light // their addr. Therefore we do not need to update these parts. 540a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light return true; 541a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } 542a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light t.NewTiming("Fixup Section Headers"); 54353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light for (unsigned int i = 0; i < oat_file_->GetSectionHeaderNum(); i++) { 544daab38ca60c5b91787e29c87a161a2bb8c1b6f11Andreas Gampe Elf32_Shdr* hdr = oat_file_->GetSectionHeader(i); 545daab38ca60c5b91787e29c87a161a2bb8c1b6f11Andreas Gampe CHECK(hdr != nullptr); 546daab38ca60c5b91787e29c87a161a2bb8c1b6f11Andreas Gampe if (hdr->sh_addr != 0) { 547daab38ca60c5b91787e29c87a161a2bb8c1b6f11Andreas Gampe hdr->sh_addr += delta_; 54853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 54953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 55053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 551a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light t.NewTiming("Fixup Dynamics"); 55253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light for (Elf32_Word i = 0; i < oat_file_->GetDynamicNum(); i++) { 55353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Elf32_Dyn& dyn = oat_file_->GetDynamic(i); 55453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (IsDynamicSectionPointer(dyn.d_tag, oat_file_->GetHeader().e_machine)) { 55553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light dyn.d_un.d_ptr += delta_; 55653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 55753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 55853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 55953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light t.NewTiming("Fixup Elf Symbols"); 56053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Fixup dynsym 56153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Elf32_Shdr* dynsym_sec = oat_file_->FindSectionByName(".dynsym"); 56253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(dynsym_sec != nullptr); 56353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!PatchSymbols(dynsym_sec)) { 56453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 56553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 56653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 56753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Fixup symtab 56853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Elf32_Shdr* symtab_sec = oat_file_->FindSectionByName(".symtab"); 56953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (symtab_sec != nullptr) { 57053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!PatchSymbols(symtab_sec)) { 57153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 57253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 57353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 57453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 575e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban t.NewTiming("Fixup Debug Sections"); 576e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban if (!oat_file_->FixupDebugSections(delta_)) { 577e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban return false; 578e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 579e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 58053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 58153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 58253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 58353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightbool PatchOat::PatchSymbols(Elf32_Shdr* section) { 58453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Elf32_Sym* syms = reinterpret_cast<Elf32_Sym*>(oat_file_->Begin() + section->sh_offset); 58553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const Elf32_Sym* last_sym = 58653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light reinterpret_cast<Elf32_Sym*>(oat_file_->Begin() + section->sh_offset + section->sh_size); 58753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_EQ(section->sh_size % sizeof(Elf32_Sym), 0u) 58853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light << "Symtab section size is not multiple of symbol size"; 58953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light for (; syms < last_sym; syms++) { 59053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uint8_t sttype = ELF32_ST_TYPE(syms->st_info); 59153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Elf32_Word shndx = syms->st_shndx; 59253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (shndx != SHN_ABS && shndx != SHN_COMMON && shndx != SHN_UNDEF && 59353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light (sttype == STT_FUNC || sttype == STT_OBJECT)) { 59453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_NE(syms->st_value, 0u); 59553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light syms->st_value += delta_; 59653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 59753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 59853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 59953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 60053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 60153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightbool PatchOat::PatchTextSection() { 60253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Elf32_Shdr* patches_sec = oat_file_->FindSectionByName(".oat_patches"); 60353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (patches_sec == nullptr) { 604a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light LOG(ERROR) << ".oat_patches section not found. Aborting patch"; 60553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 60653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 6074b0d2d99b596eebd6da45679896d3af54bc5a935Alex Light if (patches_sec->sh_type != SHT_OAT_PATCH) { 6084b0d2d99b596eebd6da45679896d3af54bc5a935Alex Light LOG(ERROR) << "Unexpected type of .oat_patches"; 6094b0d2d99b596eebd6da45679896d3af54bc5a935Alex Light return false; 6104b0d2d99b596eebd6da45679896d3af54bc5a935Alex Light } 6114b0d2d99b596eebd6da45679896d3af54bc5a935Alex Light 6124b0d2d99b596eebd6da45679896d3af54bc5a935Alex Light switch (patches_sec->sh_entsize) { 6134b0d2d99b596eebd6da45679896d3af54bc5a935Alex Light case sizeof(uint32_t): 6144b0d2d99b596eebd6da45679896d3af54bc5a935Alex Light return PatchTextSection<uint32_t>(*patches_sec); 6154b0d2d99b596eebd6da45679896d3af54bc5a935Alex Light case sizeof(uint64_t): 6164b0d2d99b596eebd6da45679896d3af54bc5a935Alex Light return PatchTextSection<uint64_t>(*patches_sec); 6174b0d2d99b596eebd6da45679896d3af54bc5a935Alex Light default: 6184b0d2d99b596eebd6da45679896d3af54bc5a935Alex Light LOG(ERROR) << ".oat_patches Entsize of " << patches_sec->sh_entsize << "bits " 6194b0d2d99b596eebd6da45679896d3af54bc5a935Alex Light << "is not valid"; 6204b0d2d99b596eebd6da45679896d3af54bc5a935Alex Light return false; 6214b0d2d99b596eebd6da45679896d3af54bc5a935Alex Light } 6224b0d2d99b596eebd6da45679896d3af54bc5a935Alex Light} 6234b0d2d99b596eebd6da45679896d3af54bc5a935Alex Light 6244b0d2d99b596eebd6da45679896d3af54bc5a935Alex Lighttemplate <typename ptr_t> 6254b0d2d99b596eebd6da45679896d3af54bc5a935Alex Lightbool PatchOat::PatchTextSection(const Elf32_Shdr& patches_sec) { 6264b0d2d99b596eebd6da45679896d3af54bc5a935Alex Light DCHECK(CheckOatFile<ptr_t>(patches_sec)) << "Oat file invalid"; 6274b0d2d99b596eebd6da45679896d3af54bc5a935Alex Light ptr_t* patches = reinterpret_cast<ptr_t*>(oat_file_->Begin() + patches_sec.sh_offset); 6284b0d2d99b596eebd6da45679896d3af54bc5a935Alex Light ptr_t* patches_end = patches + (patches_sec.sh_size / sizeof(ptr_t)); 62953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Elf32_Shdr* oat_text_sec = oat_file_->FindSectionByName(".text"); 63053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(oat_text_sec != nullptr); 63153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light byte* to_patch = oat_file_->Begin() + oat_text_sec->sh_offset; 63253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t to_patch_end = reinterpret_cast<uintptr_t>(to_patch) + oat_text_sec->sh_size; 63353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 63453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light for (; patches < patches_end; patches++) { 63553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_LT(*patches, oat_text_sec->sh_size) << "Bad Patch"; 63653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uint32_t* patch_loc = reinterpret_cast<uint32_t*>(to_patch + *patches); 63753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_LT(reinterpret_cast<uintptr_t>(patch_loc), to_patch_end); 63853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light *patch_loc += delta_; 63953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 64053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 64153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 64253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 64353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightstatic int orig_argc; 64453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightstatic char** orig_argv; 64553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 64653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightstatic std::string CommandLine() { 64753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::vector<std::string> command; 64853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light for (int i = 0; i < orig_argc; ++i) { 64953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light command.push_back(orig_argv[i]); 65053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 65153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return Join(command, ' '); 65253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 65353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 65453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightstatic void UsageErrorV(const char* fmt, va_list ap) { 65553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string error; 65653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light StringAppendV(&error, fmt, ap); 65753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(ERROR) << error; 65853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 65953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 66053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightstatic void UsageError(const char* fmt, ...) { 66153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light va_list ap; 66253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light va_start(ap, fmt); 66353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageErrorV(fmt, ap); 66453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light va_end(ap); 66553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 66653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 66753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightstatic void Usage(const char *fmt, ...) { 66853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light va_list ap; 66953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light va_start(ap, fmt); 67053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageErrorV(fmt, ap); 67153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light va_end(ap); 67253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 67353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError("Command: %s", CommandLine().c_str()); 67453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError("Usage: patchoat [options]..."); 67553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 67653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --instruction-set=<isa>: Specifies the instruction set the patched code is"); 67753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" compiled for. Required if you use --input-oat-location"); 67853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 67953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --input-oat-file=<file.oat>: Specifies the exact filename of the oat file to be"); 68053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" patched."); 68153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 68253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --input-oat-fd=<file-descriptor>: Specifies the file-descriptor of the oat file"); 68353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" to be patched."); 68453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 68553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --input-oat-location=<file.oat>: Specifies the 'location' to read the patched"); 68653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" oat file from. If used one must also supply the --instruction-set"); 68753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 68853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --input-image-location=<file.art>: Specifies the 'location' of the image file to"); 68953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" be patched. If --instruction-set is not given it will use the instruction set"); 69053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" extracted from the --input-oat-file."); 69153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 69253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --output-oat-file=<file.oat>: Specifies the exact file to write the patched oat"); 69353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" file to."); 69453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 69553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --output-oat-fd=<file-descriptor>: Specifies the file-descriptor to write the"); 69653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" the patched oat file to."); 69753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 69853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --output-image-file=<file.art>: Specifies the exact file to write the patched"); 69953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" image file to."); 70053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 70153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --output-image-fd=<file-descriptor>: Specifies the file-descriptor to write the"); 70253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" the patched image file to."); 70353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 70453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --orig-base-offset=<original-base-offset>: Specify the base offset the input file"); 70553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" was compiled with. This is needed if one is specifying a --base-offset"); 70653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 70753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --base-offset=<new-base-offset>: Specify the base offset we will repatch the"); 70853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" given files to use. This requires that --orig-base-offset is also given."); 70953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 71053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --base-offset-delta=<delta>: Specify the amount to change the old base-offset by."); 71153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" This value may be negative."); 71253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 71353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --patched-image-file=<file.art>: Use the same patch delta as was used to patch"); 71453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" the given image file."); 71553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 71653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --patched-image-location=<file.art>: Use the same patch delta as was used to"); 71753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" patch the given image location. If used one must also specify the"); 718a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light UsageError(" --instruction-set flag. It will search for this image in the same way that"); 719a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light UsageError(" is done when loading one."); 72053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 721cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light UsageError(" --lock-output: Obtain a flock on output oat file before starting."); 722cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light UsageError(""); 723cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light UsageError(" --no-lock-output: Do not attempt to obtain a flock on output oat file."); 724cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light UsageError(""); 72553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --dump-timings: dump out patch timing information"); 72653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 72753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(" --no-dump-timings: do not dump out patch timing information"); 72853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light UsageError(""); 72953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 73053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light exit(EXIT_FAILURE); 73153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 73253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 733eefbe39799126afdf7d315a79359b9da23d1cef5Alex Lightstatic bool ReadBaseDelta(const char* name, off_t* delta, std::string* error_msg) { 73453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(name != nullptr); 73553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(delta != nullptr); 73653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::unique_ptr<File> file; 73753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (OS::FileExists(name)) { 73853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light file.reset(OS::OpenFileForReading(name)); 73953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (file.get() == nullptr) { 740eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light *error_msg = "Failed to open file %s for reading"; 74153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 74253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 74353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 744eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light *error_msg = "File %s does not exist"; 74553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 74653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 74753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(file.get() != nullptr); 74853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light ImageHeader hdr; 74953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (sizeof(hdr) != file->Read(reinterpret_cast<char*>(&hdr), sizeof(hdr), 0)) { 750eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light *error_msg = "Failed to read file %s"; 75153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 75253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 75353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!hdr.IsValid()) { 754eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light *error_msg = "%s does not contain a valid image header."; 75553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return false; 75653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 75753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light *delta = hdr.GetPatchDelta(); 75853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return true; 75953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 76053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 76153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightstatic File* CreateOrOpen(const char* name, bool* created) { 76253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (OS::FileExists(name)) { 76353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light *created = false; 76453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return OS::OpenFileReadWrite(name); 76553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 76653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light *created = true; 767cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light std::unique_ptr<File> f(OS::CreateEmptyFile(name)); 768cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light if (f.get() != nullptr) { 769cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light if (fchmod(f->Fd(), 0644) != 0) { 770cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light PLOG(ERROR) << "Unable to make " << name << " world readable"; 771cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light unlink(name); 772cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light return nullptr; 773cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } 774cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } 775cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light return f.release(); 77653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 77753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 77853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 779eefbe39799126afdf7d315a79359b9da23d1cef5Alex Lightstatic int patchoat(int argc, char **argv) { 78053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light InitLogging(argv); 78153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const bool debug = kIsDebugBuild; 78253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light orig_argc = argc; 78353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light orig_argv = argv; 78453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light TimingLogger timings("patcher", false, false); 78553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 78653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light InitLogging(argv); 78753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 78853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Skip over the command name. 78953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light argv++; 79053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light argc--; 79153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 79253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (argc == 0) { 79353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("No arguments specified"); 79453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 79553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 79653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light timings.StartTiming("Patchoat"); 79753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 79853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // cmd line args 79953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool isa_set = false; 80053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light InstructionSet isa = kNone; 80153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string input_oat_filename; 80253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string input_oat_location; 80353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light int input_oat_fd = -1; 80453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool have_input_oat = false; 80553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string input_image_location; 80653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string output_oat_filename; 80753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light int output_oat_fd = -1; 80853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool have_output_oat = false; 80953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string output_image_filename; 81053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light int output_image_fd = -1; 81153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool have_output_image = false; 81253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t base_offset = 0; 81353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool base_offset_set = false; 81453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uintptr_t orig_base_offset = 0; 81553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool orig_base_offset_set = false; 81653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light off_t base_delta = 0; 81753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool base_delta_set = false; 81853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string patched_image_filename; 81953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string patched_image_location; 82053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool dump_timings = kIsDebugBuild; 821cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light bool lock_output = true; 82253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 82353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light for (int i = 0; i < argc; i++) { 82453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const StringPiece option(argv[i]); 82553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const bool log_options = false; 82653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (log_options) { 82753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(INFO) << "patchoat: option[" << i << "]=" << argv[i]; 82853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 82953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (option.starts_with("--instruction-set=")) { 83053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light isa_set = true; 83153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const char* isa_str = option.substr(strlen("--instruction-set=")).data(); 83220c89303a9d89ba857bf969ad14a31f12c3be878Andreas Gampe isa = GetInstructionSetFromString(isa_str); 83320c89303a9d89ba857bf969ad14a31f12c3be878Andreas Gampe if (isa == kNone) { 83420c89303a9d89ba857bf969ad14a31f12c3be878Andreas Gampe Usage("Unknown or invalid instruction set %s", isa_str); 83553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 83653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--input-oat-location=")) { 83753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (have_input_oat) { 83853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Only one of --input-oat-file, --input-oat-location and --input-oat-fd may be used."); 83953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 84053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light have_input_oat = true; 84153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light input_oat_location = option.substr(strlen("--input-oat-location=")).data(); 84253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--input-oat-file=")) { 84353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (have_input_oat) { 84453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Only one of --input-oat-file, --input-oat-location and --input-oat-fd may be used."); 84553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 84653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light have_input_oat = true; 84753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light input_oat_filename = option.substr(strlen("--input-oat-file=")).data(); 84853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--input-oat-fd=")) { 84953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (have_input_oat) { 85053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Only one of --input-oat-file, --input-oat-location and --input-oat-fd may be used."); 85153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 85253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light have_input_oat = true; 85353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const char* oat_fd_str = option.substr(strlen("--input-oat-fd=")).data(); 85453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!ParseInt(oat_fd_str, &input_oat_fd)) { 85553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Failed to parse --input-oat-fd argument '%s' as an integer", oat_fd_str); 85653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 85753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (input_oat_fd < 0) { 85853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("--input-oat-fd pass a negative value %d", input_oat_fd); 85953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 86053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--input-image-location=")) { 86153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light input_image_location = option.substr(strlen("--input-image-location=")).data(); 86253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--output-oat-file=")) { 86353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (have_output_oat) { 864cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light Usage("Only one of --output-oat-file, and --output-oat-fd may be used."); 86553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 86653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light have_output_oat = true; 86753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light output_oat_filename = option.substr(strlen("--output-oat-file=")).data(); 86853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--output-oat-fd=")) { 86953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (have_output_oat) { 870cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light Usage("Only one of --output-oat-file, --output-oat-fd may be used."); 87153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 87253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light have_output_oat = true; 87353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const char* oat_fd_str = option.substr(strlen("--output-oat-fd=")).data(); 87453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!ParseInt(oat_fd_str, &output_oat_fd)) { 87553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Failed to parse --output-oat-fd argument '%s' as an integer", oat_fd_str); 87653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 87753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (output_oat_fd < 0) { 87853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("--output-oat-fd pass a negative value %d", output_oat_fd); 87953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 88053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--output-image-file=")) { 88153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (have_output_image) { 882cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light Usage("Only one of --output-image-file, and --output-image-fd may be used."); 88353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 88453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light have_output_image = true; 88553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light output_image_filename = option.substr(strlen("--output-image-file=")).data(); 88653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--output-image-fd=")) { 88753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (have_output_image) { 888cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light Usage("Only one of --output-image-file, and --output-image-fd may be used."); 88953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 89053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light have_output_image = true; 89153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const char* image_fd_str = option.substr(strlen("--output-image-fd=")).data(); 89253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!ParseInt(image_fd_str, &output_image_fd)) { 89353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Failed to parse --output-image-fd argument '%s' as an integer", image_fd_str); 89453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 89553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (output_image_fd < 0) { 89653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("--output-image-fd pass a negative value %d", output_image_fd); 89753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 89853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--orig-base-offset=")) { 89953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const char* orig_base_offset_str = option.substr(strlen("--orig-base-offset=")).data(); 90053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light orig_base_offset_set = true; 90153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!ParseUint(orig_base_offset_str, &orig_base_offset)) { 90253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Failed to parse --orig-base-offset argument '%s' as an uintptr_t", 90353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light orig_base_offset_str); 90453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 90553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--base-offset=")) { 90653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const char* base_offset_str = option.substr(strlen("--base-offset=")).data(); 90753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light base_offset_set = true; 90853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!ParseUint(base_offset_str, &base_offset)) { 90953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Failed to parse --base-offset argument '%s' as an uintptr_t", base_offset_str); 91053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 91153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--base-offset-delta=")) { 91253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light const char* base_delta_str = option.substr(strlen("--base-offset-delta=")).data(); 91353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light base_delta_set = true; 91453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!ParseInt(base_delta_str, &base_delta)) { 91553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Failed to parse --base-offset-delta argument '%s' as an off_t", base_delta_str); 91653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 91753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--patched-image-location=")) { 91853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light patched_image_location = option.substr(strlen("--patched-image-location=")).data(); 91953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option.starts_with("--patched-image-file=")) { 92053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light patched_image_filename = option.substr(strlen("--patched-image-file=")).data(); 921cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } else if (option == "--lock-output") { 922cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light lock_output = true; 923cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } else if (option == "--no-lock-output") { 924cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light lock_output = false; 92553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option == "--dump-timings") { 92653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light dump_timings = true; 92753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (option == "--no-dump-timings") { 92853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light dump_timings = false; 92953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 93053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Unknown argument %s", option.data()); 93153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 93253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 93353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 93453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light { 93553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Only 1 of these may be set. 93653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light uint32_t cnt = 0; 93753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light cnt += (base_delta_set) ? 1 : 0; 93853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light cnt += (base_offset_set && orig_base_offset_set) ? 1 : 0; 93953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light cnt += (!patched_image_filename.empty()) ? 1 : 0; 94053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light cnt += (!patched_image_location.empty()) ? 1 : 0; 94153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (cnt > 1) { 94253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Only one of --base-offset/--orig-base-offset, --base-offset-delta, " 94353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light "--patched-image-filename or --patched-image-location may be used."); 94453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (cnt == 0) { 94553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Must specify --base-offset-delta, --base-offset and --orig-base-offset, " 94653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light "--patched-image-location or --patched-image-file"); 94753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 94853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 94953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 95053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (have_input_oat != have_output_oat) { 95153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Either both input and output oat must be supplied or niether must be."); 95253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 95353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 95453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if ((!input_image_location.empty()) != have_output_image) { 95553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Either both input and output image must be supplied or niether must be."); 95653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 95753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 95853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // We know we have both the input and output so rename for clarity. 95953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool have_image_files = have_output_image; 96053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool have_oat_files = have_output_oat; 96153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 96253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!have_oat_files && !have_image_files) { 96353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Must be patching either an oat or an image file or both."); 96453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 96553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 96653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!have_oat_files && !isa_set) { 96753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Must include ISA if patching an image file without an oat file."); 96853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 96953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 97053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!input_oat_location.empty()) { 97153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!isa_set) { 97253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("specifying a location requires specifying an instruction set"); 97353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 974cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light if (!LocationToFilename(input_oat_location, isa, &input_oat_filename)) { 975cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light Usage("Unable to find filename for input oat location %s", input_oat_location.c_str()); 97653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 97753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (debug) { 978cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light LOG(INFO) << "Using input-oat-file " << input_oat_filename; 97953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 98053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 98153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!patched_image_location.empty()) { 98253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!isa_set) { 98353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("specifying a location requires specifying an instruction set"); 98453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 985a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light std::string system_filename; 986a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light bool has_system = false; 987a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light std::string cache_filename; 988a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light bool has_cache = false; 989a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light bool has_android_data_unused = false; 9903c13a794845e0cf7887e33b2ec20de7e6ba85f8fAndreas Gampe bool is_global_cache = false; 991a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light if (!gc::space::ImageSpace::FindImageFilename(patched_image_location.c_str(), isa, 992a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light &system_filename, &has_system, &cache_filename, 9933c13a794845e0cf7887e33b2ec20de7e6ba85f8fAndreas Gampe &has_android_data_unused, &has_cache, 9943c13a794845e0cf7887e33b2ec20de7e6ba85f8fAndreas Gampe &is_global_cache)) { 995a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light Usage("Unable to determine image file for location %s", patched_image_location.c_str()); 996a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } 997a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light if (has_cache) { 998a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light patched_image_filename = cache_filename; 999a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } else if (has_system) { 1000a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light LOG(WARNING) << "Only image file found was in /system for image location " 1001a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light << patched_image_location; 1002a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light patched_image_filename = system_filename; 1003a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } else { 1004a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light Usage("Unable to determine image file for location %s", patched_image_location.c_str()); 1005a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } 100653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (debug) { 100753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(INFO) << "Using patched-image-file " << patched_image_filename; 100853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 100953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 101053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 101153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!base_delta_set) { 101253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (orig_base_offset_set && base_offset_set) { 101353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light base_delta_set = true; 101453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light base_delta = base_offset - orig_base_offset; 101553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (!patched_image_filename.empty()) { 101653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light base_delta_set = true; 101753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::string error_msg; 1018eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light if (!ReadBaseDelta(patched_image_filename.c_str(), &base_delta, &error_msg)) { 101953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage(error_msg.c_str(), patched_image_filename.c_str()); 102053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 102153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 102253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (base_offset_set) { 102353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Unable to determine original base offset."); 102453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 102553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Must supply a desired new offset or delta."); 102653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 102753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 102853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 102953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 103053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!IsAligned<kPageSize>(base_delta)) { 103153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light Usage("Base offset/delta must be alligned to a pagesize (0x%08x) boundary.", kPageSize); 103253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 103353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 103453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light // Do we need to cleanup output files if we fail? 103553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool new_image_out = false; 103653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool new_oat_out = false; 103753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 103853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::unique_ptr<File> input_oat; 103953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::unique_ptr<File> output_oat; 104053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light std::unique_ptr<File> output_image; 104153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 104253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (have_image_files) { 104353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(!input_image_location.empty()); 104453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 104553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (output_image_fd != -1) { 1046cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light if (output_image_filename.empty()) { 1047cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light output_image_filename = "output-image-file"; 1048cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } 104953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light output_image.reset(new File(output_image_fd, output_image_filename)); 105053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 105153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(!output_image_filename.empty()); 105253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light output_image.reset(CreateOrOpen(output_image_filename.c_str(), &new_image_out)); 105353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 105453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 105553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(output_image_filename.empty() && output_image_fd == -1 && input_image_location.empty()); 105653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 105753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 105853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (have_oat_files) { 105953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (input_oat_fd != -1) { 1060cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light if (input_oat_filename.empty()) { 1061cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light input_oat_filename = "input-oat-file"; 1062cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } 106353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light input_oat.reset(new File(input_oat_fd, input_oat_filename)); 106453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 106553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(!input_oat_filename.empty()); 106653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light input_oat.reset(OS::OpenFileForReading(input_oat_filename.c_str())); 10671c83cbc4a817acbd7f9abb5b29a2d418a958e6a1Andreas Gampe if (input_oat.get() == nullptr) { 10681c83cbc4a817acbd7f9abb5b29a2d418a958e6a1Andreas Gampe LOG(ERROR) << "Could not open input oat file: " << strerror(errno); 10691c83cbc4a817acbd7f9abb5b29a2d418a958e6a1Andreas Gampe } 107053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 107153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 107253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (output_oat_fd != -1) { 1073cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light if (output_oat_filename.empty()) { 1074cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light output_oat_filename = "output-oat-file"; 1075a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light } 1076cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light output_oat.reset(new File(output_oat_fd, output_oat_filename)); 107753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 107853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(!output_oat_filename.empty()); 107953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light output_oat.reset(CreateOrOpen(output_oat_filename.c_str(), &new_oat_out)); 108053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 108153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 108253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 108353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light auto cleanup = [&output_image_filename, &output_oat_filename, 108453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light &new_oat_out, &new_image_out, &timings, &dump_timings](bool success) { 108553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light timings.EndTiming(); 108653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (!success) { 108753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (new_oat_out) { 108853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(!output_oat_filename.empty()); 108953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light unlink(output_oat_filename.c_str()); 109053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 109153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (new_image_out) { 109253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(!output_image_filename.empty()); 109353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light unlink(output_image_filename.c_str()); 109453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 109553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 109653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (dump_timings) { 109753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(INFO) << Dumpable<TimingLogger>(timings); 109853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 109953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light }; 110053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 1101cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light if ((have_oat_files && (input_oat.get() == nullptr || output_oat.get() == nullptr)) || 1102cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light (have_image_files && output_image.get() == nullptr)) { 1103cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light cleanup(false); 1104cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light return EXIT_FAILURE; 1105cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } 1106cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light 1107cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light ScopedFlock output_oat_lock; 1108cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light if (lock_output) { 1109cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light std::string error_msg; 1110cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light if (have_oat_files && !output_oat_lock.Init(output_oat.get(), &error_msg)) { 1111cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light LOG(ERROR) << "Unable to lock output oat " << output_image->GetPath() << ": " << error_msg; 1112cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light cleanup(false); 1113cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light return EXIT_FAILURE; 1114cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } 1115cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light } 1116cf4bf386ef3f527825c70e01130b9276da4f786aAlex Light 111753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (debug) { 1118a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light LOG(INFO) << "moving offset by " << base_delta 1119a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light << " (0x" << std::hex << base_delta << ") bytes or " 1120a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light << std::dec << (base_delta/kPageSize) << " pages."; 112153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 112253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 112353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light bool ret; 112453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (have_image_files && have_oat_files) { 112553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light TimingLogger::ScopedTiming pt("patch image and oat", &timings); 112653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light ret = PatchOat::Patch(input_oat.get(), input_image_location, base_delta, 1127eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light output_oat.get(), output_image.get(), isa, &timings); 112853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else if (have_oat_files) { 112953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light TimingLogger::ScopedTiming pt("patch oat", &timings); 1130eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light ret = PatchOat::Patch(input_oat.get(), base_delta, output_oat.get(), &timings); 113153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } else { 113253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light TimingLogger::ScopedTiming pt("patch image", &timings); 113353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK(have_image_files); 1134eefbe39799126afdf7d315a79359b9da23d1cef5Alex Light ret = PatchOat::Patch(input_image_location, base_delta, output_image.get(), isa, &timings); 113553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 113653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light cleanup(ret); 113753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return (ret) ? EXIT_SUCCESS : EXIT_FAILURE; 113853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 113953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 114053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} // namespace art 114153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 114253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightint main(int argc, char **argv) { 114353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return art::patchoat(argc, argv); 114453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 1145