Remove unused code for patching oat files.
patchoat is now only used for patching images. It no longer needs to
support patching of non-PIC oat files. This change removes code from
patchoat that was specific to patching of non-PIC oat files.
Bug: 33192586
Test: m test-art-host
Test: device boots
Change-Id: I8918a708e441493a21f25d537ed0b74748bb9641
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index 5bdfbc7..392f044 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -120,14 +120,14 @@
ART_GTEST_dex2oat_environment_tests_HOST_DEPS := \
$(HOST_CORE_IMAGE_optimizing_pic_64) \
$(HOST_CORE_IMAGE_optimizing_pic_32) \
- $(HOST_CORE_IMAGE_optimizing_no-pic_64) \
- $(HOST_CORE_IMAGE_optimizing_no-pic_32) \
+ $(HOST_CORE_IMAGE_optimizing_pic_multi_64) \
+ $(HOST_CORE_IMAGE_optimizing_pic_multi_32) \
$(HOST_OUT_EXECUTABLES)/patchoatd
ART_GTEST_dex2oat_environment_tests_TARGET_DEPS := \
$(TARGET_CORE_IMAGE_optimizing_pic_64) \
$(TARGET_CORE_IMAGE_optimizing_pic_32) \
- $(TARGET_CORE_IMAGE_optimizing_no-pic_64) \
- $(TARGET_CORE_IMAGE_optimizing_no-pic_32) \
+ $(TARGET_CORE_IMAGE_optimizing_pic_multi_64) \
+ $(TARGET_CORE_IMAGE_optimizing_pic_multi_32) \
$(TARGET_OUT_EXECUTABLES)/patchoatd
ART_GTEST_oat_file_assistant_test_HOST_DEPS := \
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index 7ae13a5..2bf7495 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -54,48 +54,6 @@
namespace art {
-static bool LocationToFilename(const std::string& location, InstructionSet isa,
- std::string* filename) {
- bool has_system = false;
- bool has_cache = false;
- // image_location = /system/framework/boot.art
- // system_image_filename = /system/framework/<image_isa>/boot.art
- std::string system_filename(GetSystemImageFilename(location.c_str(), isa));
- if (OS::FileExists(system_filename.c_str())) {
- has_system = true;
- }
-
- bool have_android_data = false;
- bool dalvik_cache_exists = false;
- bool is_global_cache = false;
- std::string dalvik_cache;
- GetDalvikCache(GetInstructionSetString(isa), false, &dalvik_cache,
- &have_android_data, &dalvik_cache_exists, &is_global_cache);
-
- std::string cache_filename;
- if (have_android_data && dalvik_cache_exists) {
- // Always set output location even if it does not exist,
- // so that the caller knows where to create the image.
- //
- // image_location = /system/framework/boot.art
- // *image_filename = /data/dalvik-cache/<image_isa>/boot.art
- std::string error_msg;
- if (GetDalvikCacheFilename(location.c_str(), dalvik_cache.c_str(),
- &cache_filename, &error_msg)) {
- has_cache = true;
- }
- }
- if (has_system) {
- *filename = system_filename;
- return true;
- } else if (has_cache) {
- *filename = cache_filename;
- return true;
- } else {
- return false;
- }
-}
-
static const OatHeader* GetOatHeader(const ElfFile* elf_file) {
uint64_t off = 0;
if (!elf_file->GetSectionOffsetAndSize(".rodata", &off, nullptr)) {
@@ -106,28 +64,10 @@
return oat_header;
}
-// This function takes an elf file and reads the current patch delta value
-// encoded in its oat header value
-static bool ReadOatPatchDelta(const ElfFile* elf_file, off_t* delta, std::string* error_msg) {
- const OatHeader* oat_header = GetOatHeader(elf_file);
- if (oat_header == nullptr) {
- *error_msg = "Unable to get oat header from elf file.";
- return false;
- }
- if (!oat_header->IsValid()) {
- *error_msg = "Elf file has an invalid oat header";
- return false;
- }
- *delta = oat_header->GetImagePatchDelta();
- return true;
-}
-
-static File* CreateOrOpen(const char* name, bool* created) {
+static File* CreateOrOpen(const char* name) {
if (OS::FileExists(name)) {
- *created = false;
return OS::OpenFileReadWrite(name);
} else {
- *created = true;
std::unique_ptr<File> f(OS::CreateEmptyFile(name));
if (f.get() != nullptr) {
if (fchmod(f->Fd(), 0644) != 0) {
@@ -206,12 +146,11 @@
Thread::Current()->TransitionFromRunnableToSuspended(kNative);
ScopedObjectAccess soa(Thread::Current());
- t.NewTiming("Image and oat Patching setup");
+ t.NewTiming("Image Patching setup");
std::vector<gc::space::ImageSpace*> spaces = Runtime::Current()->GetHeap()->GetBootImageSpaces();
std::map<gc::space::ImageSpace*, std::unique_ptr<File>> space_to_file_map;
std::map<gc::space::ImageSpace*, std::unique_ptr<MemMap>> space_to_memmap_map;
std::map<gc::space::ImageSpace*, PatchOat> space_to_patchoat_map;
- std::map<gc::space::ImageSpace*, bool> space_to_skip_patching_map;
for (size_t i = 0; i < spaces.size(); ++i) {
gc::space::ImageSpace* space = spaces[i];
@@ -255,8 +194,7 @@
space_to_memmap_map.emplace(space, std::move(image));
}
- // Do a first pass over the image spaces. Symlink PIC oat and vdex files, and
- // prepare PatchOat instances for the rest.
+ // Symlink PIC oat and vdex files and patch the image spaces in memory.
for (size_t i = 0; i < spaces.size(); ++i) {
gc::space::ImageSpace* space = spaces[i];
std::string input_image_filename = space->GetImageFilename();
@@ -277,14 +215,17 @@
return false;
}
- bool skip_patching_oat = false;
MaybePic is_oat_pic = IsOatPic(elf.get());
if (is_oat_pic >= ERROR_FIRST) {
// Error logged by IsOatPic
return false;
- } else if (is_oat_pic == PIC) {
- // Do not need to do ELF-file patching. Create a symlink and skip the ELF patching.
+ } else if (is_oat_pic == NOT_PIC) {
+ LOG(ERROR) << input_oat_file->GetPath() << " is not PIC";
+ return false;
+ } else {
+ CHECK(is_oat_pic == PIC);
+ // Create a symlink.
std::string converted_image_filename = space->GetImageLocation();
std::replace(converted_image_filename.begin() + 1, converted_image_filename.end(), '/', '@');
std::string output_image_filename = output_directory +
@@ -296,23 +237,16 @@
ImageHeader::GetOatLocationFromImageLocation(output_image_filename);
if (!ReplaceOatFileWithSymlink(input_oat_file->GetPath(),
- output_oat_filename,
- false,
- true) ||
+ output_oat_filename) ||
!SymlinkFile(input_vdex_filename, output_vdex_filename)) {
// Errors already logged by above call.
return false;
}
- // Don't patch the OAT, since we just symlinked it. Image still needs patching.
- skip_patching_oat = true;
- } else {
- CHECK(is_oat_pic == NOT_PIC);
}
PatchOat& p = space_to_patchoat_map.emplace(space,
PatchOat(
isa,
- elf.release(),
space_to_memmap_map.find(space)->second.get(),
space->GetLiveBitmap(),
space->GetMemMap(),
@@ -320,36 +254,24 @@
&space_to_memmap_map,
timings)).first->second;
- t.NewTiming("Patching files");
- if (!skip_patching_oat && !p.PatchElf()) {
- LOG(ERROR) << "Failed to patch oat file " << input_oat_file->GetPath();
- return false;
- }
+ t.NewTiming("Patching image");
if (!p.PatchImage(i == 0)) {
LOG(ERROR) << "Failed to patch image file " << input_image_filename;
return false;
}
-
- space_to_skip_patching_map.emplace(space, skip_patching_oat);
}
- // Do a second pass over the image spaces. Patch image files, non-PIC oat files
- // and symlink their corresponding vdex files.
+ // Write the patched image spaces.
for (size_t i = 0; i < spaces.size(); ++i) {
gc::space::ImageSpace* space = spaces[i];
- std::string input_image_filename = space->GetImageFilename();
- std::string input_vdex_filename =
- ImageHeader::GetVdexLocationFromImageLocation(input_image_filename);
- t.NewTiming("Writing files");
+ t.NewTiming("Writing image");
std::string converted_image_filename = space->GetImageLocation();
std::replace(converted_image_filename.begin() + 1, converted_image_filename.end(), '/', '@');
std::string output_image_filename = output_directory +
(android::base::StartsWith(converted_image_filename, "/") ? "" : "/") +
converted_image_filename;
- bool new_oat_out;
- std::unique_ptr<File>
- output_image_file(CreateOrOpen(output_image_filename.c_str(), &new_oat_out));
+ std::unique_ptr<File> output_image_file(CreateOrOpen(output_image_filename.c_str()));
if (output_image_file.get() == nullptr) {
LOG(ERROR) << "Failed to open output image file at " << output_image_filename;
return false;
@@ -362,48 +284,10 @@
if (!success) {
return false;
}
-
- bool skip_patching_oat = space_to_skip_patching_map.find(space)->second;
- if (!skip_patching_oat) {
- std::string output_vdex_filename =
- ImageHeader::GetVdexLocationFromImageLocation(output_image_filename);
- std::string output_oat_filename =
- ImageHeader::GetOatLocationFromImageLocation(output_image_filename);
-
- std::unique_ptr<File>
- output_oat_file(CreateOrOpen(output_oat_filename.c_str(), &new_oat_out));
- if (output_oat_file.get() == nullptr) {
- LOG(ERROR) << "Failed to open output oat file at " << output_oat_filename;
- return false;
- }
- success = p.WriteElf(output_oat_file.get());
- success = FinishFile(output_oat_file.get(), success);
- if (success) {
- success = SymlinkFile(input_vdex_filename, output_vdex_filename);
- }
- if (!success) {
- return false;
- }
- }
}
return true;
}
-bool PatchOat::WriteElf(File* out) {
- TimingLogger::ScopedTiming t("Writing Elf File", timings_);
-
- CHECK(oat_file_.get() != nullptr);
- CHECK(out != nullptr);
- size_t expect = oat_file_->Size();
- if (out->WriteFully(reinterpret_cast<char*>(oat_file_->Begin()), expect) &&
- out->SetLength(expect) == 0) {
- return true;
- } else {
- LOG(ERROR) << "Writing to oat file " << out->GetPath() << " failed.";
- return false;
- }
-}
-
bool PatchOat::WriteImage(File* out) {
TimingLogger::ScopedTiming t("Writing image File", timings_);
std::string error_msg;
@@ -466,22 +350,7 @@
}
bool PatchOat::ReplaceOatFileWithSymlink(const std::string& input_oat_filename,
- const std::string& output_oat_filename,
- bool output_oat_opened_from_fd,
- bool new_oat_out) {
- // Need a file when we are PIC, since we symlink over it. Refusing to symlink into FD.
- if (output_oat_opened_from_fd) {
- // TODO: installd uses --output-oat-fd. Should we change class linking logic for PIC?
- LOG(ERROR) << "No output oat filename specified, needs filename for when we are PIC";
- return false;
- }
-
- // Image was PIC. Create symlink where the oat is supposed to go.
- if (!new_oat_out) {
- LOG(ERROR) << "Oat file " << output_oat_filename << " already exists, refusing to overwrite";
- return false;
- }
-
+ const std::string& output_oat_filename) {
// Delete the original file, since we won't need it.
unlink(output_oat_filename.c_str());
@@ -799,133 +668,6 @@
object->GetDataPtrSize(pointer_size)), pointer_size);
}
-bool PatchOat::Patch(File* input_oat, off_t delta, File* output_oat, TimingLogger* timings,
- bool output_oat_opened_from_fd, bool new_oat_out) {
- CHECK(input_oat != nullptr);
- CHECK(output_oat != nullptr);
- CHECK_GE(input_oat->Fd(), 0);
- CHECK_GE(output_oat->Fd(), 0);
- TimingLogger::ScopedTiming t("Setup Oat File Patching", timings);
-
- std::string error_msg;
- std::unique_ptr<ElfFile> elf(ElfFile::Open(input_oat,
- PROT_READ | PROT_WRITE, MAP_PRIVATE, &error_msg));
- if (elf.get() == nullptr) {
- LOG(ERROR) << "unable to open oat file " << input_oat->GetPath() << " : " << error_msg;
- return false;
- }
-
- MaybePic is_oat_pic = IsOatPic(elf.get());
- if (is_oat_pic >= ERROR_FIRST) {
- // Error logged by IsOatPic
- return false;
- } else if (is_oat_pic == PIC) {
- // Do not need to do ELF-file patching. Create a symlink and skip the rest.
- // Any errors will be logged by the function call.
- return ReplaceOatFileWithSymlink(input_oat->GetPath(),
- output_oat->GetPath(),
- output_oat_opened_from_fd,
- new_oat_out);
- } else {
- CHECK(is_oat_pic == NOT_PIC);
- }
-
- PatchOat p(elf.release(), delta, timings);
- t.NewTiming("Patch Oat file");
- if (!p.PatchElf()) {
- return false;
- }
-
- t.NewTiming("Writing oat file");
- if (!p.WriteElf(output_oat)) {
- return false;
- }
- return true;
-}
-
-template <typename ElfFileImpl>
-bool PatchOat::PatchOatHeader(ElfFileImpl* oat_file) {
- auto rodata_sec = oat_file->FindSectionByName(".rodata");
- if (rodata_sec == nullptr) {
- return false;
- }
- OatHeader* oat_header = reinterpret_cast<OatHeader*>(oat_file->Begin() + rodata_sec->sh_offset);
- if (!oat_header->IsValid()) {
- LOG(ERROR) << "Elf file " << oat_file->GetFilePath() << " has an invalid oat header";
- return false;
- }
- oat_header->RelocateOat(delta_);
- return true;
-}
-
-bool PatchOat::PatchElf() {
- if (oat_file_->Is64Bit()) {
- return PatchElf<ElfFileImpl64>(oat_file_->GetImpl64());
- } else {
- return PatchElf<ElfFileImpl32>(oat_file_->GetImpl32());
- }
-}
-
-template <typename ElfFileImpl>
-bool PatchOat::PatchElf(ElfFileImpl* oat_file) {
- TimingLogger::ScopedTiming t("Fixup Elf Text Section", timings_);
-
- // Fix up absolute references to locations within the boot image.
- if (!oat_file->ApplyOatPatchesTo(".text", delta_)) {
- return false;
- }
-
- // Update the OatHeader fields referencing the boot image.
- if (!PatchOatHeader<ElfFileImpl>(oat_file)) {
- return false;
- }
-
- bool need_boot_oat_fixup = true;
- for (unsigned int i = 0; i < oat_file->GetProgramHeaderNum(); ++i) {
- auto hdr = oat_file->GetProgramHeader(i);
- if (hdr->p_type == PT_LOAD && hdr->p_vaddr == 0u) {
- need_boot_oat_fixup = false;
- break;
- }
- }
- if (!need_boot_oat_fixup) {
- // This is an app oat file that can be loaded at an arbitrary address in memory.
- // Boot image references were patched above and there's nothing else to do.
- return true;
- }
-
- // This is a boot oat file that's loaded at a particular address and we need
- // to patch all absolute addresses, starting with ELF program headers.
-
- t.NewTiming("Fixup Elf Headers");
- // Fixup Phdr's
- oat_file->FixupProgramHeaders(delta_);
-
- t.NewTiming("Fixup Section Headers");
- // Fixup Shdr's
- oat_file->FixupSectionHeaders(delta_);
-
- t.NewTiming("Fixup Dynamics");
- oat_file->FixupDynamic(delta_);
-
- t.NewTiming("Fixup Elf Symbols");
- // Fixup dynsym
- if (!oat_file->FixupSymbols(delta_, true)) {
- return false;
- }
- // Fixup symtab
- if (!oat_file->FixupSymbols(delta_, false)) {
- return false;
- }
-
- t.NewTiming("Fixup Debug Sections");
- if (!oat_file->FixupDebugSections(delta_)) {
- return false;
- }
-
- return true;
-}
-
static int orig_argc;
static char** orig_argv;
@@ -960,32 +702,10 @@
UsageError("Usage: patchoat [options]...");
UsageError("");
UsageError(" --instruction-set=<isa>: Specifies the instruction set the patched code is");
- UsageError(" compiled for. Required if you use --input-oat-location");
- UsageError("");
- UsageError(" --input-oat-file=<file.oat>: Specifies the exact filename of the oat file to be");
- UsageError(" patched.");
- UsageError("");
- UsageError(" --input-oat-fd=<file-descriptor>: Specifies the file-descriptor of the oat file");
- UsageError(" to be patched.");
- UsageError("");
- UsageError(" --input-vdex-fd=<file-descriptor>: Specifies the file-descriptor of the vdex file");
- UsageError(" associated with the oat file.");
- UsageError("");
- UsageError(" --input-oat-location=<file.oat>: Specifies the 'location' to read the patched");
- UsageError(" oat file from. If used one must also supply the --instruction-set");
+ UsageError(" compiled for (required).");
UsageError("");
UsageError(" --input-image-location=<file.art>: Specifies the 'location' of the image file to");
- UsageError(" be patched. If --instruction-set is not given it will use the instruction set");
- UsageError(" extracted from the --input-oat-file.");
- UsageError("");
- UsageError(" --output-oat-file=<file.oat>: Specifies the exact file to write the patched oat");
- UsageError(" file to.");
- UsageError("");
- UsageError(" --output-oat-fd=<file-descriptor>: Specifies the file-descriptor to write the");
- UsageError(" patched oat file to.");
- UsageError("");
- UsageError(" --output-vdex-fd=<file-descriptor>: Specifies the file-descriptor to copy the");
- UsageError(" the vdex file associated with the patch oat file to.");
+ UsageError(" be patched.");
UsageError("");
UsageError(" --output-image-file=<file.art>: Specifies the exact file to write the patched");
UsageError(" image file to.");
@@ -993,15 +713,6 @@
UsageError(" --base-offset-delta=<delta>: Specify the amount to change the old base-offset by.");
UsageError(" This value may be negative.");
UsageError("");
- UsageError(" --patched-image-location=<file.art>: Relocate the oat file to be the same as the");
- UsageError(" image at the given location. If used one must also specify the");
- UsageError(" --instruction-set flag. It will search for this image in the same way that");
- UsageError(" is done when loading one.");
- UsageError("");
- UsageError(" --lock-output: Obtain a flock on output oat file before starting.");
- UsageError("");
- UsageError(" --no-lock-output: Do not attempt to obtain a flock on output oat file.");
- UsageError("");
UsageError(" --dump-timings: dump out patch timing information");
UsageError("");
UsageError(" --no-dump-timings: do not dump out patch timing information");
@@ -1010,34 +721,6 @@
exit(EXIT_FAILURE);
}
-static bool ReadBaseDelta(const char* name, off_t* delta, std::string* error_msg) {
- CHECK(name != nullptr);
- CHECK(delta != nullptr);
- std::unique_ptr<File> file;
- if (OS::FileExists(name)) {
- file.reset(OS::OpenFileForReading(name));
- if (file.get() == nullptr) {
- *error_msg = "Failed to open file %s for reading";
- return false;
- }
- } else {
- *error_msg = "File %s does not exist";
- return false;
- }
- CHECK(file.get() != nullptr);
- ImageHeader hdr;
- if (sizeof(hdr) != file->Read(reinterpret_cast<char*>(&hdr), sizeof(hdr), 0)) {
- *error_msg = "Failed to read file %s";
- return false;
- }
- if (!hdr.IsValid()) {
- *error_msg = "%s does not contain a valid image header.";
- return false;
- }
- *delta = hdr.GetPatchDelta();
- return true;
-}
-
static int patchoat_image(TimingLogger& timings,
InstructionSet isa,
const std::string& input_image_location,
@@ -1076,293 +759,6 @@
return ret ? EXIT_SUCCESS : EXIT_FAILURE;
}
-static int patchoat_oat(TimingLogger& timings,
- InstructionSet isa,
- const std::string& patched_image_location,
- off_t base_delta,
- bool base_delta_set,
- int input_oat_fd,
- int input_vdex_fd,
- const std::string& input_oat_location,
- std::string input_oat_filename,
- bool have_input_oat,
- int output_oat_fd,
- int output_vdex_fd,
- std::string output_oat_filename,
- bool have_output_oat,
- bool lock_output,
- bool debug) {
- {
- // Only 1 of these may be set.
- uint32_t cnt = 0;
- cnt += (base_delta_set) ? 1 : 0;
- cnt += (!patched_image_location.empty()) ? 1 : 0;
- if (cnt > 1) {
- Usage("Only one of --base-offset-delta or --patched-image-location may be used.");
- } else if (cnt == 0) {
- Usage("Must specify --base-offset-delta or --patched-image-location.");
- }
- }
-
- if (!have_input_oat || !have_output_oat) {
- Usage("Both input and output oat must be supplied to patch an app odex.");
- }
-
- if (!input_oat_location.empty()) {
- if (!LocationToFilename(input_oat_location, isa, &input_oat_filename)) {
- Usage("Unable to find filename for input oat location %s", input_oat_location.c_str());
- }
- if (debug) {
- LOG(INFO) << "Using input-oat-file " << input_oat_filename;
- }
- }
-
- if ((input_oat_fd == -1) != (input_vdex_fd == -1)) {
- Usage("Either both input oat and vdex have to be passed as file descriptors or none of them");
- } else if ((output_oat_fd == -1) != (output_vdex_fd == -1)) {
- Usage("Either both output oat and vdex have to be passed as file descriptors or none of them");
- }
-
- bool match_delta = false;
- if (!patched_image_location.empty()) {
- std::string system_filename;
- bool has_system = false;
- std::string cache_filename;
- bool has_cache = false;
- bool has_android_data_unused = false;
- bool is_global_cache = false;
- if (!gc::space::ImageSpace::FindImageFilename(patched_image_location.c_str(), isa,
- &system_filename, &has_system, &cache_filename,
- &has_android_data_unused, &has_cache,
- &is_global_cache)) {
- Usage("Unable to determine image file for location %s", patched_image_location.c_str());
- }
- std::string patched_image_filename;
- if (has_cache) {
- patched_image_filename = cache_filename;
- } else if (has_system) {
- LOG(WARNING) << "Only image file found was in /system for image location "
- << patched_image_location;
- patched_image_filename = system_filename;
- } else {
- Usage("Unable to determine image file for location %s", patched_image_location.c_str());
- }
- if (debug) {
- LOG(INFO) << "Using patched-image-file " << patched_image_filename;
- }
-
- base_delta_set = true;
- match_delta = true;
- std::string error_msg;
- if (!ReadBaseDelta(patched_image_filename.c_str(), &base_delta, &error_msg)) {
- Usage(error_msg.c_str(), patched_image_filename.c_str());
- }
- }
-
- if (!IsAligned<kPageSize>(base_delta)) {
- Usage("Base offset/delta must be alligned to a pagesize (0x%08x) boundary.", kPageSize);
- }
-
- // We can symlink VDEX only if we have both input and output specified as filenames.
- // Store that piece of information before we possibly create bogus filenames for
- // files passed as file descriptors.
- bool symlink_vdex = !input_oat_filename.empty() && !output_oat_filename.empty();
-
- // Infer names of VDEX files.
- std::string input_vdex_filename;
- std::string output_vdex_filename;
- if (!input_oat_filename.empty()) {
- input_vdex_filename = ReplaceFileExtension(input_oat_filename, "vdex");
- }
- if (!output_oat_filename.empty()) {
- output_vdex_filename = ReplaceFileExtension(output_oat_filename, "vdex");
- }
-
- // Do we need to cleanup output files if we fail?
- bool new_oat_out = false;
- bool new_vdex_out = false;
-
- std::unique_ptr<File> input_oat;
- std::unique_ptr<File> output_oat;
-
- if (input_oat_fd != -1) {
- if (input_oat_filename.empty()) {
- input_oat_filename = "input-oat-file";
- }
- input_oat.reset(new File(input_oat_fd, input_oat_filename, false));
- if (input_oat_fd == output_oat_fd) {
- input_oat.get()->DisableAutoClose();
- }
- if (input_oat == nullptr) {
- // Unlikely, but ensure exhaustive logging in non-0 exit code case
- LOG(ERROR) << "Failed to open input oat file by its FD" << input_oat_fd;
- return EXIT_FAILURE;
- }
- } else {
- CHECK(!input_oat_filename.empty());
- input_oat.reset(OS::OpenFileForReading(input_oat_filename.c_str()));
- if (input_oat == nullptr) {
- int err = errno;
- LOG(ERROR) << "Failed to open input oat file " << input_oat_filename
- << ": " << strerror(err) << "(" << err << ")";
- return EXIT_FAILURE;
- }
- }
-
- std::string error_msg;
- std::unique_ptr<ElfFile> elf(ElfFile::Open(input_oat.get(), PROT_READ, MAP_PRIVATE, &error_msg));
- if (elf.get() == nullptr) {
- LOG(ERROR) << "unable to open oat file " << input_oat->GetPath() << " : " << error_msg;
- return EXIT_FAILURE;
- }
- if (!elf->HasSection(".text.oat_patches")) {
- LOG(ERROR) << "missing oat patch section in input oat file " << input_oat->GetPath();
- return EXIT_FAILURE;
- }
-
- if (output_oat_fd != -1) {
- if (output_oat_filename.empty()) {
- output_oat_filename = "output-oat-file";
- }
- output_oat.reset(new File(output_oat_fd, output_oat_filename, true));
- if (output_oat == nullptr) {
- // Unlikely, but ensure exhaustive logging in non-0 exit code case
- LOG(ERROR) << "Failed to open output oat file by its FD" << output_oat_fd;
- }
- } else {
- CHECK(!output_oat_filename.empty());
- output_oat.reset(CreateOrOpen(output_oat_filename.c_str(), &new_oat_out));
- if (output_oat == nullptr) {
- int err = errno;
- LOG(ERROR) << "Failed to open output oat file " << output_oat_filename
- << ": " << strerror(err) << "(" << err << ")";
- }
- }
-
- // Open VDEX files if we are not symlinking them.
- std::unique_ptr<File> input_vdex;
- std::unique_ptr<File> output_vdex;
- if (symlink_vdex) {
- new_vdex_out = !OS::FileExists(output_vdex_filename.c_str());
- } else {
- if (input_vdex_fd != -1) {
- input_vdex.reset(new File(input_vdex_fd, input_vdex_filename, true));
- if (input_vdex == nullptr) {
- // Unlikely, but ensure exhaustive logging in non-0 exit code case
- LOG(ERROR) << "Failed to open input vdex file by its FD" << input_vdex_fd;
- }
- } else {
- input_vdex.reset(OS::OpenFileForReading(input_vdex_filename.c_str()));
- if (input_vdex == nullptr) {
- PLOG(ERROR) << "Failed to open input vdex file " << input_vdex_filename;
- return EXIT_FAILURE;
- }
- }
- if (output_vdex_fd != -1) {
- output_vdex.reset(new File(output_vdex_fd, output_vdex_filename, true));
- if (output_vdex == nullptr) {
- // Unlikely, but ensure exhaustive logging in non-0 exit code case
- LOG(ERROR) << "Failed to open output vdex file by its FD" << output_vdex_fd;
- }
- } else {
- output_vdex.reset(CreateOrOpen(output_vdex_filename.c_str(), &new_vdex_out));
- if (output_vdex == nullptr) {
- PLOG(ERROR) << "Failed to open output vdex file " << output_vdex_filename;
- return EXIT_FAILURE;
- }
- }
- }
-
- // TODO: get rid of this.
- auto cleanup = [&output_oat_filename, &output_vdex_filename, &new_oat_out, &new_vdex_out]
- (bool success) {
- if (!success) {
- if (new_oat_out) {
- CHECK(!output_oat_filename.empty());
- unlink(output_oat_filename.c_str());
- }
- if (new_vdex_out) {
- CHECK(!output_vdex_filename.empty());
- unlink(output_vdex_filename.c_str());
- }
- }
-
- if (kIsDebugBuild) {
- LOG(INFO) << "Cleaning up.. success? " << success;
- }
- };
-
- if (output_oat.get() == nullptr) {
- cleanup(false);
- return EXIT_FAILURE;
- }
-
- if (match_delta) {
- // Figure out what the current delta is so we can match it to the desired delta.
- off_t current_delta = 0;
- if (!ReadOatPatchDelta(elf.get(), ¤t_delta, &error_msg)) {
- LOG(ERROR) << "Unable to get current delta: " << error_msg;
- cleanup(false);
- return EXIT_FAILURE;
- }
- // Before this line base_delta is the desired final delta. We need it to be the actual amount to
- // change everything by. We subtract the current delta from it to make it this.
- base_delta -= current_delta;
- if (!IsAligned<kPageSize>(base_delta)) {
- LOG(ERROR) << "Given image file was relocated by an illegal delta";
- cleanup(false);
- return false;
- }
- }
-
- if (debug) {
- LOG(INFO) << "moving offset by " << base_delta
- << " (0x" << std::hex << base_delta << ") bytes or "
- << std::dec << (base_delta/kPageSize) << " pages.";
- }
-
- ScopedFlock output_oat_lock;
- if (lock_output) {
- if (!output_oat_lock.Init(output_oat.get(), &error_msg)) {
- LOG(ERROR) << "Unable to lock output oat " << output_oat->GetPath() << ": " << error_msg;
- cleanup(false);
- return EXIT_FAILURE;
- }
- }
-
- TimingLogger::ScopedTiming pt("patch oat", &timings);
- bool ret = PatchOat::Patch(input_oat.get(), base_delta, output_oat.get(), &timings,
- output_oat_fd >= 0, // was it opened from FD?
- new_oat_out);
- ret = FinishFile(output_oat.get(), ret);
-
- if (ret) {
- if (symlink_vdex) {
- ret = SymlinkFile(input_vdex_filename, output_vdex_filename);
- } else {
- ret = unix_file::CopyFile(*input_vdex.get(), output_vdex.get());
- }
- }
-
- if (kIsDebugBuild) {
- LOG(INFO) << "Exiting with return ... " << ret;
- }
- cleanup(ret);
- return ret ? EXIT_SUCCESS : EXIT_FAILURE;
-}
-
-static int ParseFd(const StringPiece& option, const char* cmdline_arg) {
- int fd;
- const char* fd_str = option.substr(strlen(cmdline_arg)).data();
- if (!ParseInt(fd_str, &fd)) {
- Usage("Failed to parse %d argument '%s' as an integer", cmdline_arg, fd_str);
- }
- if (fd < 0) {
- Usage("%s pass a negative value %d", cmdline_arg, fd);
- }
- return fd;
-}
-
static int patchoat(int argc, char **argv) {
InitLogging(argv, Runtime::Aborter);
MemMap::Init();
@@ -1384,23 +780,11 @@
// cmd line args
bool isa_set = false;
InstructionSet isa = kNone;
- std::string input_oat_filename;
- std::string input_oat_location;
- int input_oat_fd = -1;
- int input_vdex_fd = -1;
- bool have_input_oat = false;
std::string input_image_location;
- std::string output_oat_filename;
- int output_oat_fd = -1;
- int output_vdex_fd = -1;
- bool have_output_oat = false;
std::string output_image_filename;
off_t base_delta = 0;
bool base_delta_set = false;
- std::string patched_image_filename;
- std::string patched_image_location;
bool dump_timings = kIsDebugBuild;
- bool lock_output = true;
for (int i = 0; i < argc; ++i) {
const StringPiece option(argv[i]);
@@ -1415,42 +799,8 @@
if (isa == kNone) {
Usage("Unknown or invalid instruction set %s", isa_str);
}
- } else if (option.starts_with("--input-oat-location=")) {
- if (have_input_oat) {
- Usage("Only one of --input-oat-file, --input-oat-location and --input-oat-fd may be used.");
- }
- have_input_oat = true;
- input_oat_location = option.substr(strlen("--input-oat-location=")).data();
- } else if (option.starts_with("--input-oat-file=")) {
- if (have_input_oat) {
- Usage("Only one of --input-oat-file, --input-oat-location and --input-oat-fd may be used.");
- }
- have_input_oat = true;
- input_oat_filename = option.substr(strlen("--input-oat-file=")).data();
- } else if (option.starts_with("--input-oat-fd=")) {
- if (have_input_oat) {
- Usage("Only one of --input-oat-file, --input-oat-location and --input-oat-fd may be used.");
- }
- have_input_oat = true;
- input_oat_fd = ParseFd(option, "--input-oat-fd=");
- } else if (option.starts_with("--input-vdex-fd=")) {
- input_vdex_fd = ParseFd(option, "--input-vdex-fd=");
} else if (option.starts_with("--input-image-location=")) {
input_image_location = option.substr(strlen("--input-image-location=")).data();
- } else if (option.starts_with("--output-oat-file=")) {
- if (have_output_oat) {
- Usage("Only one of --output-oat-file, and --output-oat-fd may be used.");
- }
- have_output_oat = true;
- output_oat_filename = option.substr(strlen("--output-oat-file=")).data();
- } else if (option.starts_with("--output-oat-fd=")) {
- if (have_output_oat) {
- Usage("Only one of --output-oat-file, --output-oat-fd may be used.");
- }
- have_output_oat = true;
- output_oat_fd = ParseFd(option, "--output-oat-fd=");
- } else if (option.starts_with("--output-vdex-fd=")) {
- output_vdex_fd = ParseFd(option, "--output-vdex-fd=");
} else if (option.starts_with("--output-image-file=")) {
output_image_filename = option.substr(strlen("--output-image-file=")).data();
} else if (option.starts_with("--base-offset-delta=")) {
@@ -1459,12 +809,6 @@
if (!ParseInt(base_delta_str, &base_delta)) {
Usage("Failed to parse --base-offset-delta argument '%s' as an off_t", base_delta_str);
}
- } else if (option.starts_with("--patched-image-location=")) {
- patched_image_location = option.substr(strlen("--patched-image-location=")).data();
- } else if (option == "--lock-output") {
- lock_output = true;
- } else if (option == "--no-lock-output") {
- lock_output = false;
} else if (option == "--dump-timings") {
dump_timings = true;
} else if (option == "--no-dump-timings") {
@@ -1479,33 +823,13 @@
Usage("Instruction set must be set.");
}
- int ret;
- if (!input_image_location.empty()) {
- ret = patchoat_image(timings,
- isa,
- input_image_location,
- output_image_filename,
- base_delta,
- base_delta_set,
- debug);
- } else {
- ret = patchoat_oat(timings,
- isa,
- patched_image_location,
- base_delta,
- base_delta_set,
- input_oat_fd,
- input_vdex_fd,
- input_oat_location,
- input_oat_filename,
- have_input_oat,
- output_oat_fd,
- output_vdex_fd,
- output_oat_filename,
- have_output_oat,
- lock_output,
- debug);
- }
+ int ret = patchoat_image(timings,
+ isa,
+ input_image_location,
+ output_image_filename,
+ base_delta,
+ base_delta_set,
+ debug);
timings.EndTiming();
if (dump_timings) {
diff --git a/patchoat/patchoat.h b/patchoat/patchoat.h
index a519631..e15a6bc 100644
--- a/patchoat/patchoat.h
+++ b/patchoat/patchoat.h
@@ -44,17 +44,7 @@
class PatchOat {
public:
- // Patch only the oat file
- static bool Patch(File* oat_in, off_t delta, File* oat_out, TimingLogger* timings,
- bool output_oat_opened_from_fd, // Was this using --oatput-oat-fd ?
- bool new_oat_out); // Output oat was a new file created by us?
-
- // Patch only the image (art file)
- static bool Patch(const std::string& art_location, off_t delta, File* art_out, InstructionSet isa,
- TimingLogger* timings);
-
- // Patch both the image and the oat file
- static bool Patch(const std::string& art_location,
+ static bool Patch(const std::string& image_location,
off_t delta,
const std::string& output_directory,
InstructionSet isa,
@@ -64,18 +54,11 @@
PatchOat(PatchOat&&) = default;
private:
- // Takes ownership only of the ElfFile. All other pointers are only borrowed.
- PatchOat(ElfFile* oat_file, off_t delta, TimingLogger* timings)
- : oat_file_(oat_file), image_(nullptr), bitmap_(nullptr), heap_(nullptr), delta_(delta),
- isa_(kNone), space_map_(nullptr), timings_(timings) {}
- PatchOat(InstructionSet isa, MemMap* image, gc::accounting::ContinuousSpaceBitmap* bitmap,
- MemMap* heap, off_t delta, TimingLogger* timings)
- : image_(image), bitmap_(bitmap), heap_(heap),
- delta_(delta), isa_(isa), space_map_(nullptr), timings_(timings) {}
- PatchOat(InstructionSet isa, ElfFile* oat_file, MemMap* image,
+ // All pointers are only borrowed.
+ PatchOat(InstructionSet isa, MemMap* image,
gc::accounting::ContinuousSpaceBitmap* bitmap, MemMap* heap, off_t delta,
std::map<gc::space::ImageSpace*, std::unique_ptr<MemMap>>* map, TimingLogger* timings)
- : oat_file_(oat_file), image_(image), bitmap_(bitmap), heap_(heap),
+ : image_(image), bitmap_(bitmap), heap_(heap),
delta_(delta), isa_(isa), space_map_(map), timings_(timings) {}
// Was the .art image at image_path made with --compile-pic ?
@@ -94,9 +77,7 @@
// Attempt to replace the file with a symlink
// Returns false if it fails
static bool ReplaceOatFileWithSymlink(const std::string& input_oat_filename,
- const std::string& output_oat_filename,
- bool output_oat_opened_from_fd,
- bool new_oat_out); // Output oat was newly created?
+ const std::string& output_oat_filename);
static void BitmapCallback(mirror::Object* obj, void* arg)
REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -108,13 +89,6 @@
void FixupMethod(ArtMethod* object, ArtMethod* copy)
REQUIRES_SHARED(Locks::mutator_lock_);
- // Patches oat in place, modifying the oat_file given to the constructor.
- bool PatchElf();
- template <typename ElfFileImpl>
- bool PatchElf(ElfFileImpl* oat_file);
- template <typename ElfFileImpl>
- bool PatchOatHeader(ElfFileImpl* oat_file);
-
bool PatchImage(bool primary_image) REQUIRES_SHARED(Locks::mutator_lock_);
void PatchArtFields(const ImageHeader* image_header) REQUIRES_SHARED(Locks::mutator_lock_);
void PatchArtMethods(const ImageHeader* image_header) REQUIRES_SHARED(Locks::mutator_lock_);
@@ -128,7 +102,6 @@
void PatchDexFileArrays(mirror::ObjectArray<mirror::Object>* img_roots)
REQUIRES_SHARED(Locks::mutator_lock_);
- bool WriteElf(File* out);
bool WriteImage(File* out);
template <typename T>
@@ -175,19 +148,6 @@
return reinterpret_cast<T*>(ret);
}
- template <typename T>
- T RelocatedAddressOfIntPointer(T obj) const {
- if (obj == 0) {
- return obj;
- }
- T ret = obj + delta_;
- // Trim off high bits in case negative relocation with 64 bit patchoat.
- if (Is32BitISA()) {
- ret = static_cast<T>(static_cast<uint32_t>(ret));
- }
- return ret;
- }
-
bool Is32BitISA() const {
return InstructionSetPointerSize(isa_) == PointerSize::k32;
}
@@ -213,8 +173,6 @@
mirror::Object* const copy_;
};
- // The elf file we are patching.
- std::unique_ptr<ElfFile> oat_file_;
// A mmap of the image we are patching. This is modified.
const MemMap* const image_;
// The bitmap over the image within the heap we are patching. This is not modified.
diff --git a/runtime/dex2oat_environment_test.h b/runtime/dex2oat_environment_test.h
index b0c4597..8b1b5a3 100644
--- a/runtime/dex2oat_environment_test.h
+++ b/runtime/dex2oat_environment_test.h
@@ -160,7 +160,7 @@
// image at GetImageLocation(). This is used for testing mismatched
// image checksums in the oat_file_assistant_tests.
std::string GetImageLocation2() const {
- return GetImageDirectory() + "/core-npic.art";
+ return GetImageDirectory() + "/core-multi.art";
}
std::string GetDexSrc1() const {