ART: Add support for patching and loading OAT files compiled with PIC
* Images (.art) compiled with pic now have a new field added.
* isDexOptNeeded will now skip patch-ing for apps compiled PIC
* First-boot patching now only copies boot.art, boot.oat is linked
As a result, all system preopted dex files (with --compile-pic) no
longer take up any space in /data/dalvik-cache/<isa>.
Bug: 18035729
Change-Id: Ie1acad81a0fd8b2f24e1f3f07a06e6fdb548be62
diff --git a/patchoat/patchoat.h b/patchoat/patchoat.h
index fd36ad5..0ceef64 100644
--- a/patchoat/patchoat.h
+++ b/patchoat/patchoat.h
@@ -30,6 +30,7 @@
namespace art {
class ImageHeader;
+class OatHeader;
namespace mirror {
class Object;
@@ -40,14 +41,21 @@
class PatchOat {
public:
- static bool Patch(File* oat_in, off_t delta, File* oat_out, TimingLogger* timings);
+ // 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);
- static bool Patch(const File* oat_in, const std::string& art_location,
+ // Patch both the image and the oat file
+ static bool Patch(File* oat_in, const std::string& art_location,
off_t delta, File* oat_out, File* art_out, InstructionSet isa,
- TimingLogger* timings);
+ 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?
private:
// Takes ownership only of the ElfFile. All other pointers are only borrowed.
@@ -64,6 +72,26 @@
delta_(delta), timings_(timings) {}
~PatchOat() {}
+ // Was the .art image at image_path made with --compile-pic ?
+ static bool IsImagePic(const ImageHeader& image_header, const std::string& image_path);
+
+ enum MaybePic {
+ NOT_PIC, // Code not pic. Patch as usual.
+ PIC, // Code was pic. Create symlink; skip OAT patching.
+ ERROR_OAT_FILE, // Failed to symlink oat file
+ ERROR_FIRST = ERROR_OAT_FILE,
+ };
+
+ // Was the .oat image at oat_in made with --compile-pic ?
+ static MaybePic IsOatPic(const ElfFile* oat_in);
+
+ // 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?
+
static void BitmapCallback(mirror::Object* obj, void* arg)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
reinterpret_cast<PatchOat*>(arg)->VisitObject(obj);
@@ -95,6 +123,13 @@
mirror::Object* RelocatedCopyOf(mirror::Object*);
mirror::Object* RelocatedAddressOf(mirror::Object* obj);
+ // Look up the oat header from any elf file.
+ static const OatHeader* GetOatHeader(const ElfFile* elf_file);
+
+ // Templatized version to actually look up the oat header
+ template <typename ElfFileImpl>
+ static const OatHeader* GetOatHeader(const ElfFileImpl* elf_file);
+
// Walks through the old image and patches the mmap'd copy of it to the new offset. It does not
// change the heap.
class PatchVisitor {