1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_PATCHOAT_PATCHOAT_H_ 18 #define ART_PATCHOAT_PATCHOAT_H_ 19 20 #include "base/macros.h" 21 #include "base/mutex.h" 22 #include "instruction_set.h" 23 #include "os.h" 24 #include "elf_file.h" 25 #include "elf_utils.h" 26 #include "gc/accounting/space_bitmap.h" 27 #include "gc/heap.h" 28 #include "utils.h" 29 30 namespace art { 31 32 class ImageHeader; 33 class OatHeader; 34 35 namespace mirror { 36 class Object; 37 class Reference; 38 class Class; 39 class ArtMethod; 40 }; // namespace mirror 41 42 class PatchOat { 43 public: 44 // Patch only the oat file 45 static bool Patch(File* oat_in, off_t delta, File* oat_out, TimingLogger* timings, 46 bool output_oat_opened_from_fd, // Was this using --oatput-oat-fd ? 47 bool new_oat_out); // Output oat was a new file created by us? 48 49 // Patch only the image (art file) 50 static bool Patch(const std::string& art_location, off_t delta, File* art_out, InstructionSet isa, 51 TimingLogger* timings); 52 53 // Patch both the image and the oat file 54 static bool Patch(File* oat_in, const std::string& art_location, 55 off_t delta, File* oat_out, File* art_out, InstructionSet isa, 56 TimingLogger* timings, 57 bool output_oat_opened_from_fd, // Was this using --oatput-oat-fd ? 58 bool new_oat_out); // Output oat was a new file created by us? 59 60 private: 61 // Takes ownership only of the ElfFile. All other pointers are only borrowed. PatchOat(ElfFile * oat_file,off_t delta,TimingLogger * timings)62 PatchOat(ElfFile* oat_file, off_t delta, TimingLogger* timings) 63 : oat_file_(oat_file), delta_(delta), isa_(kNone), timings_(timings) {} PatchOat(InstructionSet isa,MemMap * image,gc::accounting::ContinuousSpaceBitmap * bitmap,MemMap * heap,off_t delta,TimingLogger * timings)64 PatchOat(InstructionSet isa, MemMap* image, gc::accounting::ContinuousSpaceBitmap* bitmap, 65 MemMap* heap, off_t delta, TimingLogger* timings) 66 : image_(image), bitmap_(bitmap), heap_(heap), 67 delta_(delta), isa_(isa), timings_(timings) {} PatchOat(InstructionSet isa,ElfFile * oat_file,MemMap * image,gc::accounting::ContinuousSpaceBitmap * bitmap,MemMap * heap,off_t delta,TimingLogger * timings)68 PatchOat(InstructionSet isa, ElfFile* oat_file, MemMap* image, 69 gc::accounting::ContinuousSpaceBitmap* bitmap, MemMap* heap, off_t delta, 70 TimingLogger* timings) 71 : oat_file_(oat_file), image_(image), bitmap_(bitmap), heap_(heap), 72 delta_(delta), isa_(isa), timings_(timings) {} ~PatchOat()73 ~PatchOat() {} 74 75 // Was the .art image at image_path made with --compile-pic ? 76 static bool IsImagePic(const ImageHeader& image_header, const std::string& image_path); 77 78 enum MaybePic { 79 NOT_PIC, // Code not pic. Patch as usual. 80 PIC, // Code was pic. Create symlink; skip OAT patching. 81 ERROR_OAT_FILE, // Failed to symlink oat file 82 ERROR_FIRST = ERROR_OAT_FILE, 83 }; 84 85 // Was the .oat image at oat_in made with --compile-pic ? 86 static MaybePic IsOatPic(const ElfFile* oat_in); 87 88 // Attempt to replace the file with a symlink 89 // Returns false if it fails 90 static bool ReplaceOatFileWithSymlink(const std::string& input_oat_filename, 91 const std::string& output_oat_filename, 92 bool output_oat_opened_from_fd, 93 bool new_oat_out); // Output oat was newly created? 94 BitmapCallback(mirror::Object * obj,void * arg)95 static void BitmapCallback(mirror::Object* obj, void* arg) 96 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 97 reinterpret_cast<PatchOat*>(arg)->VisitObject(obj); 98 } 99 100 void VisitObject(mirror::Object* obj) 101 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 102 void FixupMethod(mirror::ArtMethod* object, mirror::ArtMethod* copy) 103 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 104 bool InHeap(mirror::Object*); 105 106 bool CheckOatFile(); 107 108 // Patches oat in place, modifying the oat_file given to the constructor. 109 bool PatchElf(); 110 bool PatchTextSection(); 111 bool PatchOatHeader(); 112 bool PatchSymbols(Elf32_Shdr* section); 113 114 bool PatchImage() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 115 116 bool WriteElf(File* out); 117 bool WriteImage(File* out); 118 119 mirror::Object* RelocatedCopyOf(mirror::Object*); 120 mirror::Object* RelocatedAddressOf(mirror::Object* obj); 121 122 // Look up the oat header from any elf file. 123 static const OatHeader* GetOatHeader(const ElfFile* elf_file); 124 125 // Walks through the old image and patches the mmap'd copy of it to the new offset. It does not 126 // change the heap. 127 class PatchVisitor { 128 public: PatchVisitor(PatchOat * patcher,mirror::Object * copy)129 PatchVisitor(PatchOat* patcher, mirror::Object* copy) : patcher_(patcher), copy_(copy) {} ~PatchVisitor()130 ~PatchVisitor() {} 131 void operator() (mirror::Object* obj, MemberOffset off, bool b) const 132 EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_); 133 // For reference classes. 134 void operator() (mirror::Class* cls, mirror::Reference* ref) const 135 EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_); 136 private: 137 PatchOat* patcher_; 138 mirror::Object* copy_; 139 }; 140 141 // The elf file we are patching. 142 std::unique_ptr<ElfFile> oat_file_; 143 // A mmap of the image we are patching. This is modified. 144 const MemMap* image_; 145 // The heap we are patching. This is not modified. 146 gc::accounting::ContinuousSpaceBitmap* bitmap_; 147 // The heap we are patching. This is not modified. 148 const MemMap* heap_; 149 // The amount we are changing the offset by. 150 off_t delta_; 151 // Active instruction set, used to know the entrypoint size. 152 const InstructionSet isa_; 153 154 TimingLogger* timings_; 155 156 DISALLOW_IMPLICIT_CONSTRUCTORS(PatchOat); 157 }; 158 159 } // namespace art 160 #endif // ART_PATCHOAT_PATCHOAT_H_ 161