summaryrefslogtreecommitdiff
path: root/patchoat/patchoat.cc
diff options
context:
space:
mode:
author Mathieu Chartier <mathieuc@google.com> 2018-01-11 22:21:24 +0000
committer Mathieu Chartier <mathieuc@google.com> 2018-01-11 22:24:10 +0000
commit24e4f73f21c098e6fdffc5fc28fd3d185f94c27d (patch)
tree5ca19b04f91a01aecfa0f78f576af78cecd6c071 /patchoat/patchoat.cc
parentfbe5f2f85244bf57707afb5520b2f9aa189d9d55 (diff)
Revert "Enable patchoat to write image relocation files"
This reverts commit fbe5f2f85244bf57707afb5520b2f9aa189d9d55. Test is failing very often on the buildbots. Bug: 66697305 Change-Id: I9be7471b1c988bdddeca732c39b9323125e4384d
Diffstat (limited to 'patchoat/patchoat.cc')
-rw-r--r--patchoat/patchoat.cc289
1 files changed, 48 insertions, 241 deletions
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index 6c9cf864b3..eb648cba18 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -15,7 +15,6 @@
*/
#include "patchoat.h"
-#include <openssl/sha.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/file.h>
@@ -43,7 +42,6 @@
#include "gc/space/image_space.h"
#include "image-inl.h"
#include "intern_table.h"
-#include "leb128.h"
#include "mirror/dex_cache.h"
#include "mirror/executable.h"
#include "mirror/method.h"
@@ -60,8 +58,6 @@
namespace art {
-using android::base::StringPrintf;
-
static const OatHeader* GetOatHeader(const ElfFile* elf_file) {
uint64_t off = 0;
if (!elf_file->GetSectionOffsetAndSize(".rodata", &off, nullptr)) {
@@ -124,134 +120,11 @@ static bool SymlinkFile(const std::string& input_filename, const std::string& ou
return true;
}
-bool PatchOat::GeneratePatch(
- const MemMap& original,
- const MemMap& relocated,
- std::vector<uint8_t>* output,
- std::string* error_msg) {
- // FORMAT of the patch (aka image relocation) file:
- // * SHA-256 digest (32 bytes) of original/unrelocated file (e.g., the one from /system)
- // * List of monotonically increasing offsets (max value defined by uint32_t) at which relocations
- // occur.
- // Each element is represented as the delta from the previous offset in the list (first element
- // is a delta from 0). Each delta is encoded using unsigned LEB128: little-endian
- // variable-length 7 bits per byte encoding, where all bytes have the highest bit (0x80) set
- // except for the final byte which does not have that bit set. For example, 0x3f is offset 0x3f,
- // whereas 0xbf 0x05 is offset (0x3f & 0x7f) | (0x5 << 7) which is 0x2bf. Most deltas end up
- // being encoding using just one byte, achieving ~4x decrease in relocation file size compared
- // to the encoding where offsets are stored verbatim, as uint32_t.
-
- size_t original_size = original.Size();
- size_t relocated_size = relocated.Size();
- if (original_size != relocated_size) {
- *error_msg =
- StringPrintf(
- "Original and relocated image sizes differ: %zu vs %zu", original_size, relocated_size);
- return false;
- }
- if ((original_size % 4) != 0) {
- *error_msg = StringPrintf("Image size not multiple of 4: %zu", original_size);
- return false;
- }
- if (original_size > UINT32_MAX) {
- *error_msg = StringPrintf("Image too large: %zu" , original_size);
- return false;
- }
-
- const ImageHeader& relocated_header =
- *reinterpret_cast<const ImageHeader*>(relocated.Begin());
- // Offsets are supposed to differ between original and relocated by this value
- off_t expected_diff = relocated_header.GetPatchDelta();
- if (expected_diff == 0) {
- // Can't identify offsets which are supposed to differ due to relocation
- *error_msg = "Relocation delta is 0";
- return false;
- }
-
- // Output the SHA-256 digest of the original
- output->resize(SHA256_DIGEST_LENGTH);
- const uint8_t* original_bytes = original.Begin();
- SHA256(original_bytes, original_size, output->data());
-
- // Output the list of offsets at which the original and patched images differ
- size_t last_diff_offset = 0;
- size_t diff_offset_count = 0;
- const uint8_t* relocated_bytes = relocated.Begin();
- for (size_t offset = 0; offset < original_size; offset += 4) {
- uint32_t original_value = *reinterpret_cast<const uint32_t*>(original_bytes + offset);
- uint32_t relocated_value = *reinterpret_cast<const uint32_t*>(relocated_bytes + offset);
- off_t diff = relocated_value - original_value;
- if (diff == 0) {
- continue;
- } else if (diff != expected_diff) {
- *error_msg =
- StringPrintf(
- "Unexpected diff at offset %zu. Expected: %jd, but was: %jd",
- offset,
- (intmax_t) expected_diff,
- (intmax_t) diff);
- return false;
- }
-
- uint32_t offset_diff = offset - last_diff_offset;
- last_diff_offset = offset;
- diff_offset_count++;
-
- EncodeUnsignedLeb128(output, offset_diff);
- }
-
- if (diff_offset_count == 0) {
- *error_msg = "Original and patched images are identical";
- return false;
- }
-
- return true;
-}
-
-static bool WriteRelFile(
- const MemMap& original,
- const MemMap& relocated,
- const std::string& rel_filename,
- std::string* error_msg) {
- std::vector<uint8_t> output;
- if (!PatchOat::GeneratePatch(original, relocated, &output, error_msg)) {
- return false;
- }
-
- std::unique_ptr<File> rel_file(OS::CreateEmptyFileWriteOnly(rel_filename.c_str()));
- if (rel_file.get() == nullptr) {
- *error_msg = StringPrintf("Failed to create/open output file %s", rel_filename.c_str());
- return false;
- }
- if (!rel_file->WriteFully(output.data(), output.size())) {
- *error_msg = StringPrintf("Failed to write to %s", rel_filename.c_str());
- return false;
- }
- if (rel_file->FlushCloseOrErase() != 0) {
- *error_msg = StringPrintf("Failed to flush and close %s", rel_filename.c_str());
- return false;
- }
-
- return true;
-}
-
bool PatchOat::Patch(const std::string& image_location,
off_t delta,
- const std::string& output_image_directory,
- const std::string& output_image_relocation_directory,
+ const std::string& output_directory,
InstructionSet isa,
TimingLogger* timings) {
- bool output_image = !output_image_directory.empty();
- bool output_image_relocation = !output_image_relocation_directory.empty();
- if ((!output_image) && (!output_image_relocation)) {
- // Nothing to do
- return true;
- }
- if ((output_image_relocation) && (delta == 0)) {
- LOG(ERROR) << "Cannot output image relocation information when requested relocation delta is 0";
- return false;
- }
-
CHECK(Runtime::Current() == nullptr);
CHECK(!image_location.empty()) << "image file must have a filename.";
@@ -348,35 +221,32 @@ bool PatchOat::Patch(const std::string& image_location,
return false;
}
- if (output_image) {
- MaybePic is_oat_pic = IsOatPic(elf.get());
- if (is_oat_pic >= ERROR_FIRST) {
- // Error logged by IsOatPic
- return false;
- } else if (is_oat_pic == NOT_PIC) {
- LOG(ERROR) << "patchoat cannot be used on non-PIC oat file: " << input_oat_file->GetPath();
+ MaybePic is_oat_pic = IsOatPic(elf.get());
+ if (is_oat_pic >= ERROR_FIRST) {
+ // Error logged by IsOatPic
+ return false;
+ } else if (is_oat_pic == NOT_PIC) {
+ LOG(ERROR) << "patchoat cannot be used on non-PIC oat file: " << input_oat_file->GetPath();
+ 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 +
+ (android::base::StartsWith(converted_image_filename, "/") ? "" : "/") +
+ converted_image_filename;
+ std::string output_vdex_filename =
+ ImageHeader::GetVdexLocationFromImageLocation(output_image_filename);
+ std::string output_oat_filename =
+ ImageHeader::GetOatLocationFromImageLocation(output_image_filename);
+
+ if (!ReplaceOatFileWithSymlink(input_oat_file->GetPath(),
+ output_oat_filename) ||
+ !SymlinkFile(input_vdex_filename, output_vdex_filename)) {
+ // Errors already logged by above call.
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_image_directory +
- (android::base::StartsWith(converted_image_filename, "/") ? "" : "/") +
- converted_image_filename;
- std::string output_vdex_filename =
- ImageHeader::GetVdexLocationFromImageLocation(output_image_filename);
- std::string output_oat_filename =
- ImageHeader::GetOatLocationFromImageLocation(output_image_filename);
-
- if (!ReplaceOatFileWithSymlink(input_oat_file->GetPath(),
- output_oat_filename) ||
- !SymlinkFile(input_vdex_filename, output_vdex_filename)) {
- // Errors already logged by above call.
- return false;
- }
}
}
@@ -397,72 +267,28 @@ bool PatchOat::Patch(const std::string& image_location,
}
}
- if (output_image) {
- // Write the patched image spaces.
- for (size_t i = 0; i < spaces.size(); ++i) {
- gc::space::ImageSpace* space = spaces[i];
-
- 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_image_directory +
- (android::base::StartsWith(converted_image_filename, "/") ? "" : "/") +
- converted_image_filename;
- 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;
- }
-
- PatchOat& p = space_to_patchoat_map.find(space)->second;
+ // Write the patched image spaces.
+ for (size_t i = 0; i < spaces.size(); ++i) {
+ gc::space::ImageSpace* space = spaces[i];
- bool success = p.WriteImage(output_image_file.get());
- success = FinishFile(output_image_file.get(), success);
- if (!success) {
- return false;
- }
+ 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;
+ 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;
}
- }
- if (output_image_relocation) {
- // Write the image relocation information for each space.
- for (size_t i = 0; i < spaces.size(); ++i) {
- gc::space::ImageSpace* space = spaces[i];
-
- t.NewTiming("Writing image relocation");
- std::string original_image_filename(space->GetImageLocation() + ".rel");
- std::string image_relocation_filename =
- output_image_relocation_directory
- + (android::base::StartsWith(original_image_filename, "/") ? "" : "/")
- + original_image_filename.substr(original_image_filename.find_last_of("/"));
- File& input_image = *space_to_file_map.find(space)->second;
- int64_t input_image_size = input_image.GetLength();
- if (input_image_size < 0) {
- LOG(ERROR) << "Error while getting input image size";
- return false;
- }
- std::string error_msg;
- std::unique_ptr<MemMap> original(MemMap::MapFile(input_image_size,
- PROT_READ,
- MAP_PRIVATE,
- input_image.Fd(),
- 0,
- /*low_4gb*/false,
- input_image.GetPath().c_str(),
- &error_msg));
- if (original.get() == nullptr) {
- LOG(ERROR) << "Unable to map image file " << input_image.GetPath() << " : " << error_msg;
- return false;
- }
-
- PatchOat& p = space_to_patchoat_map.find(space)->second;
- const MemMap* relocated = p.image_;
+ PatchOat& p = space_to_patchoat_map.find(space)->second;
- if (!WriteRelFile(*original, *relocated, image_relocation_filename, &error_msg)) {
- LOG(ERROR) << "Failed to create image relocation file " << image_relocation_filename
- << ": " << error_msg;
- return false;
- }
+ bool success = p.WriteImage(output_image_file.get());
+ success = FinishFile(output_image_file.get(), success);
+ if (!success) {
+ return false;
}
}
@@ -913,9 +739,6 @@ NO_RETURN static void Usage(const char *fmt, ...) {
UsageError(" --output-image-file=<file.art>: Specifies the exact file to write the patched");
UsageError(" image file to.");
UsageError("");
- UsageError(" --output-image-relocation-file=<file.art.rel>: Specifies the exact file to write");
- UsageError(" the image relocation information to.");
- UsageError("");
UsageError(" --base-offset-delta=<delta>: Specify the amount to change the old base-offset by.");
UsageError(" This value may be negative.");
UsageError("");
@@ -931,13 +754,12 @@ static int patchoat_image(TimingLogger& timings,
InstructionSet isa,
const std::string& input_image_location,
const std::string& output_image_filename,
- const std::string& output_image_relocation_filename,
off_t base_delta,
bool base_delta_set,
bool debug) {
CHECK(!input_image_location.empty());
- if ((output_image_filename.empty()) && (output_image_relocation_filename.empty())) {
- Usage("Image patching requires --output-image-file or --output-image-relocation-file");
+ if (output_image_filename.empty()) {
+ Usage("Image patching requires --output-image-file");
}
if (!base_delta_set) {
@@ -956,19 +778,9 @@ static int patchoat_image(TimingLogger& timings,
TimingLogger::ScopedTiming pt("patch image and oat", &timings);
- std::string output_image_directory =
+ std::string output_directory =
output_image_filename.substr(0, output_image_filename.find_last_of('/'));
- std::string output_image_relocation_directory =
- output_image_relocation_filename.substr(
- 0, output_image_relocation_filename.find_last_of('/'));
- bool ret =
- PatchOat::Patch(
- input_image_location,
- base_delta,
- output_image_directory,
- output_image_relocation_directory,
- isa,
- &timings);
+ bool ret = PatchOat::Patch(input_image_location, base_delta, output_directory, isa, &timings);
if (kIsDebugBuild) {
LOG(INFO) << "Exiting with return ... " << ret;
@@ -999,7 +811,6 @@ static int patchoat(int argc, char **argv) {
InstructionSet isa = InstructionSet::kNone;
std::string input_image_location;
std::string output_image_filename;
- std::string output_image_relocation_filename;
off_t base_delta = 0;
bool base_delta_set = false;
bool dump_timings = kIsDebugBuild;
@@ -1021,9 +832,6 @@ static int patchoat(int argc, char **argv) {
input_image_location = option.substr(strlen("--input-image-location=")).data();
} else if (option.starts_with("--output-image-file=")) {
output_image_filename = option.substr(strlen("--output-image-file=")).data();
- } else if (option.starts_with("--output-image-relocation-file=")) {
- output_image_relocation_filename =
- option.substr(strlen("--output-image-relocation-file=")).data();
} else if (option.starts_with("--base-offset-delta=")) {
const char* base_delta_str = option.substr(strlen("--base-offset-delta=")).data();
base_delta_set = true;
@@ -1048,7 +856,6 @@ static int patchoat(int argc, char **argv) {
isa,
input_image_location,
output_image_filename,
- output_image_relocation_filename,
base_delta,
base_delta_set,
debug);