1 /*
2  * Copyright (C) 2011 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_RUNTIME_IMAGE_H_
18 #define ART_RUNTIME_IMAGE_H_
19 
20 #include <string.h>
21 
22 #include "base/bit_utils.h"
23 #include "base/enums.h"
24 #include "globals.h"
25 #include "mirror/object.h"
26 
27 namespace art {
28 
29 class ArtField;
30 class ArtMethod;
31 
32 namespace linker {
33 class ImageWriter;
34 }  // namespace linker
35 
36 class ObjectVisitor {
37  public:
~ObjectVisitor()38   virtual ~ObjectVisitor() {}
39 
40   virtual void Visit(mirror::Object* object) = 0;
41 };
42 
43 class ArtMethodVisitor {
44  public:
~ArtMethodVisitor()45   virtual ~ArtMethodVisitor() {}
46 
47   virtual void Visit(ArtMethod* method) = 0;
48 };
49 
50 class ArtFieldVisitor {
51  public:
~ArtFieldVisitor()52   virtual ~ArtFieldVisitor() {}
53 
54   virtual void Visit(ArtField* method) = 0;
55 };
56 
57 class PACKED(4) ImageSection {
58  public:
ImageSection()59   ImageSection() : offset_(0), size_(0) { }
ImageSection(uint32_t offset,uint32_t size)60   ImageSection(uint32_t offset, uint32_t size) : offset_(offset), size_(size) { }
61   ImageSection(const ImageSection& section) = default;
62   ImageSection& operator=(const ImageSection& section) = default;
63 
Offset()64   uint32_t Offset() const {
65     return offset_;
66   }
67 
Size()68   uint32_t Size() const {
69     return size_;
70   }
71 
End()72   uint32_t End() const {
73     return Offset() + Size();
74   }
75 
Contains(uint64_t offset)76   bool Contains(uint64_t offset) const {
77     return offset - offset_ < size_;
78   }
79 
80  private:
81   uint32_t offset_;
82   uint32_t size_;
83 };
84 
85 // header of image files written by ImageWriter, read and validated by Space.
86 class PACKED(4) ImageHeader {
87  public:
88   enum StorageMode : uint32_t {
89     kStorageModeUncompressed,
90     kStorageModeLZ4,
91     kStorageModeLZ4HC,
92     kStorageModeCount,  // Number of elements in enum.
93   };
94   static constexpr StorageMode kDefaultStorageMode = kStorageModeUncompressed;
95 
ImageHeader()96   ImageHeader()
97       : image_begin_(0U),
98         image_size_(0U),
99         oat_checksum_(0U),
100         oat_file_begin_(0U),
101         oat_data_begin_(0U),
102         oat_data_end_(0U),
103         oat_file_end_(0U),
104         boot_image_begin_(0U),
105         boot_image_size_(0U),
106         boot_oat_begin_(0U),
107         boot_oat_size_(0U),
108         patch_delta_(0),
109         image_roots_(0U),
110         pointer_size_(0U),
111         compile_pic_(0),
112         is_pic_(0),
113         storage_mode_(kDefaultStorageMode),
114         data_size_(0) {}
115 
116   ImageHeader(uint32_t image_begin,
117               uint32_t image_size,
118               ImageSection* sections,
119               uint32_t image_roots,
120               uint32_t oat_checksum,
121               uint32_t oat_file_begin,
122               uint32_t oat_data_begin,
123               uint32_t oat_data_end,
124               uint32_t oat_file_end,
125               uint32_t boot_image_begin,
126               uint32_t boot_image_size,
127               uint32_t boot_oat_begin,
128               uint32_t boot_oat_size,
129               uint32_t pointer_size,
130               bool compile_pic,
131               bool is_pic,
132               StorageMode storage_mode,
133               size_t data_size);
134 
135   bool IsValid() const;
136   const char* GetMagic() const;
137 
GetImageBegin()138   uint8_t* GetImageBegin() const {
139     return reinterpret_cast<uint8_t*>(image_begin_);
140   }
141 
GetImageSize()142   size_t GetImageSize() const {
143     return static_cast<uint32_t>(image_size_);
144   }
145 
GetOatChecksum()146   uint32_t GetOatChecksum() const {
147     return oat_checksum_;
148   }
149 
SetOatChecksum(uint32_t oat_checksum)150   void SetOatChecksum(uint32_t oat_checksum) {
151     oat_checksum_ = oat_checksum;
152   }
153 
154   // The location that the oat file was expected to be when the image was created. The actual
155   // oat file may be at a different location for application images.
GetOatFileBegin()156   uint8_t* GetOatFileBegin() const {
157     return reinterpret_cast<uint8_t*>(oat_file_begin_);
158   }
159 
GetOatDataBegin()160   uint8_t* GetOatDataBegin() const {
161     return reinterpret_cast<uint8_t*>(oat_data_begin_);
162   }
163 
GetOatDataEnd()164   uint8_t* GetOatDataEnd() const {
165     return reinterpret_cast<uint8_t*>(oat_data_end_);
166   }
167 
GetOatFileEnd()168   uint8_t* GetOatFileEnd() const {
169     return reinterpret_cast<uint8_t*>(oat_file_end_);
170   }
171 
172   PointerSize GetPointerSize() const;
173 
GetPointerSizeUnchecked()174   uint32_t GetPointerSizeUnchecked() const {
175     return pointer_size_;
176   }
177 
GetPatchDelta()178   off_t GetPatchDelta() const {
179     return patch_delta_;
180   }
181 
SetPatchDelta(off_t patch_delta)182   void SetPatchDelta(off_t patch_delta) {
183     patch_delta_ = patch_delta;
184   }
185 
GetOatLocationFromImageLocation(const std::string & image)186   static std::string GetOatLocationFromImageLocation(const std::string& image) {
187     return GetLocationFromImageLocation(image, "oat");
188   }
189 
GetVdexLocationFromImageLocation(const std::string & image)190   static std::string GetVdexLocationFromImageLocation(const std::string& image) {
191     return GetLocationFromImageLocation(image, "vdex");
192   }
193 
194   enum ImageMethod {
195     kResolutionMethod,
196     kImtConflictMethod,
197     kImtUnimplementedMethod,
198     kSaveAllCalleeSavesMethod,
199     kSaveRefsOnlyMethod,
200     kSaveRefsAndArgsMethod,
201     kSaveEverythingMethod,
202     kSaveEverythingMethodForClinit,
203     kSaveEverythingMethodForSuspendCheck,
204     kImageMethodsCount,  // Number of elements in enum.
205   };
206 
207   enum ImageRoot {
208     kDexCaches,
209     kClassRoots,
210     kClassLoader,  // App image only.
211     kImageRootsMax,
212   };
213 
214   enum ImageSections {
215     kSectionObjects,
216     kSectionArtFields,
217     kSectionArtMethods,
218     kSectionRuntimeMethods,
219     kSectionImTables,
220     kSectionIMTConflictTables,
221     kSectionDexCacheArrays,
222     kSectionInternedStrings,
223     kSectionClassTable,
224     kSectionImageBitmap,
225     kSectionCount,  // Number of elements in enum.
226   };
227 
NumberOfImageRoots(bool app_image)228   static size_t NumberOfImageRoots(bool app_image) {
229     return app_image ? kImageRootsMax : kImageRootsMax - 1u;
230   }
231 
232   ArtMethod* GetImageMethod(ImageMethod index) const;
233   void SetImageMethod(ImageMethod index, ArtMethod* method);
234 
GetImageSection(ImageSections index)235   const ImageSection& GetImageSection(ImageSections index) const {
236     DCHECK_LT(static_cast<size_t>(index), kSectionCount);
237     return sections_[index];
238   }
239 
GetObjectsSection()240   const ImageSection& GetObjectsSection() const {
241     return GetImageSection(kSectionObjects);
242   }
243 
GetFieldsSection()244   const ImageSection& GetFieldsSection() const {
245     return GetImageSection(ImageHeader::kSectionArtFields);
246   }
247 
GetMethodsSection()248   const ImageSection& GetMethodsSection() const {
249     return GetImageSection(kSectionArtMethods);
250   }
251 
GetRuntimeMethodsSection()252   const ImageSection& GetRuntimeMethodsSection() const {
253     return GetImageSection(kSectionRuntimeMethods);
254   }
255 
GetImTablesSection()256   const ImageSection& GetImTablesSection() const {
257     return GetImageSection(kSectionImTables);
258   }
259 
GetIMTConflictTablesSection()260   const ImageSection& GetIMTConflictTablesSection() const {
261     return GetImageSection(kSectionIMTConflictTables);
262   }
263 
GetDexCacheArraysSection()264   const ImageSection& GetDexCacheArraysSection() const {
265     return GetImageSection(kSectionDexCacheArrays);
266   }
267 
GetInternedStringsSection()268   const ImageSection& GetInternedStringsSection() const {
269     return GetImageSection(kSectionInternedStrings);
270   }
271 
GetClassTableSection()272   const ImageSection& GetClassTableSection() const {
273     return GetImageSection(kSectionClassTable);
274   }
275 
GetImageBitmapSection()276   const ImageSection& GetImageBitmapSection() const {
277     return GetImageSection(kSectionImageBitmap);
278   }
279 
280   template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
281   mirror::Object* GetImageRoot(ImageRoot image_root) const
282       REQUIRES_SHARED(Locks::mutator_lock_);
283 
284   template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
285   mirror::ObjectArray<mirror::Object>* GetImageRoots() const
286       REQUIRES_SHARED(Locks::mutator_lock_);
287 
288   void RelocateImage(off_t delta);
289   void RelocateImageMethods(off_t delta);
290   void RelocateImageObjects(off_t delta);
291 
CompilePic()292   bool CompilePic() const {
293     return compile_pic_ != 0;
294   }
295 
IsPic()296   bool IsPic() const {
297     return is_pic_ != 0;
298   }
299 
GetBootImageBegin()300   uint32_t GetBootImageBegin() const {
301     return boot_image_begin_;
302   }
303 
GetBootImageSize()304   uint32_t GetBootImageSize() const {
305     return boot_image_size_;
306   }
307 
GetBootOatBegin()308   uint32_t GetBootOatBegin() const {
309     return boot_oat_begin_;
310   }
311 
GetBootOatSize()312   uint32_t GetBootOatSize() const {
313     return boot_oat_size_;
314   }
315 
GetStorageMode()316   StorageMode GetStorageMode() const {
317     return storage_mode_;
318   }
319 
GetDataSize()320   uint64_t GetDataSize() const {
321     return data_size_;
322   }
323 
IsAppImage()324   bool IsAppImage() const {
325     // App images currently require a boot image, if the size is non zero then it is an app image
326     // header.
327     return boot_image_size_ != 0u;
328   }
329 
GetBootImageConstantTablesOffset()330   uint32_t GetBootImageConstantTablesOffset() const {
331     // Interned strings table and class table for boot image are mmapped read only.
332     DCHECK(!IsAppImage());
333     const ImageSection& interned_strings = GetInternedStringsSection();
334     DCHECK_ALIGNED(interned_strings.Offset(), kPageSize);
335     return interned_strings.Offset();
336   }
337 
GetBootImageConstantTablesSize()338   uint32_t GetBootImageConstantTablesSize() const {
339     uint32_t start_offset = GetBootImageConstantTablesOffset();
340     const ImageSection& class_table = GetClassTableSection();
341     DCHECK_LE(start_offset, class_table.Offset());
342     size_t tables_size = class_table.Offset() + class_table.Size() - start_offset;
343     return RoundUp(tables_size, kPageSize);
344   }
345 
346   // Visit mirror::Objects in the section starting at base.
347   // TODO: Delete base parameter if it is always equal to GetImageBegin.
348   void VisitObjects(ObjectVisitor* visitor,
349                     uint8_t* base,
350                     PointerSize pointer_size) const
351       REQUIRES_SHARED(Locks::mutator_lock_);
352 
353   // Visit ArtMethods in the section starting at base. Includes runtime methods.
354   // TODO: Delete base parameter if it is always equal to GetImageBegin.
355   void VisitPackedArtMethods(ArtMethodVisitor* visitor,
356                              uint8_t* base,
357                              PointerSize pointer_size) const;
358 
359   // Visit ArtMethods in the section starting at base.
360   // TODO: Delete base parameter if it is always equal to GetImageBegin.
361   void VisitPackedArtFields(ArtFieldVisitor* visitor, uint8_t* base) const;
362 
363   template <typename Visitor>
364   void VisitPackedImTables(const Visitor& visitor,
365                            uint8_t* base,
366                            PointerSize pointer_size) const;
367 
368   template <typename Visitor>
369   void VisitPackedImtConflictTables(const Visitor& visitor,
370                                     uint8_t* base,
371                                     PointerSize pointer_size) const;
372 
373  private:
374   static const uint8_t kImageMagic[4];
375   static const uint8_t kImageVersion[4];
376 
GetLocationFromImageLocation(const std::string & image,const std::string & extension)377   static std::string GetLocationFromImageLocation(const std::string& image,
378                                                   const std::string& extension) {
379     std::string filename = image;
380     if (filename.length() <= 3) {
381       filename += "." + extension;
382     } else {
383       filename.replace(filename.length() - 3, 3, extension);
384     }
385     return filename;
386   }
387 
388   uint8_t magic_[4];
389   uint8_t version_[4];
390 
391   // Required base address for mapping the image.
392   uint32_t image_begin_;
393 
394   // Image size, not page aligned.
395   uint32_t image_size_;
396 
397   // Checksum of the oat file we link to for load time sanity check.
398   uint32_t oat_checksum_;
399 
400   // Start address for oat file. Will be before oat_data_begin_ for .so files.
401   uint32_t oat_file_begin_;
402 
403   // Required oat address expected by image Method::GetCode() pointers.
404   uint32_t oat_data_begin_;
405 
406   // End of oat data address range for this image file.
407   uint32_t oat_data_end_;
408 
409   // End of oat file address range. will be after oat_data_end_ for
410   // .so files. Used for positioning a following alloc spaces.
411   uint32_t oat_file_end_;
412 
413   // Boot image begin and end (app image headers only).
414   uint32_t boot_image_begin_;
415   uint32_t boot_image_size_;
416 
417   // Boot oat begin and end (app image headers only).
418   uint32_t boot_oat_begin_;
419   uint32_t boot_oat_size_;
420 
421   // TODO: We should probably insert a boot image checksum for app images.
422 
423   // The total delta that this image has been patched.
424   int32_t patch_delta_;
425 
426   // Absolute address of an Object[] of objects needed to reinitialize from an image.
427   uint32_t image_roots_;
428 
429   // Pointer size, this affects the size of the ArtMethods.
430   uint32_t pointer_size_;
431 
432   // Boolean (0 or 1) to denote if the image was compiled with --compile-pic option
433   const uint32_t compile_pic_;
434 
435   // Boolean (0 or 1) to denote if the image can be mapped at a random address, this only refers to
436   // the .art file. Currently, app oat files do not depend on their app image. There are no pointers
437   // from the app oat code to the app image.
438   const uint32_t is_pic_;
439 
440   // Image section sizes/offsets correspond to the uncompressed form.
441   ImageSection sections_[kSectionCount];
442 
443   // Image methods, may be inside of the boot image for app images.
444   uint64_t image_methods_[kImageMethodsCount];
445 
446   // Storage method for the image, the image may be compressed.
447   StorageMode storage_mode_;
448 
449   // Data size for the image data excluding the bitmap and the header. For compressed images, this
450   // is the compressed size in the file.
451   uint32_t data_size_;
452 
453   friend class linker::ImageWriter;
454 };
455 
456 std::ostream& operator<<(std::ostream& os, const ImageHeader::ImageMethod& policy);
457 std::ostream& operator<<(std::ostream& os, const ImageHeader::ImageRoot& policy);
458 std::ostream& operator<<(std::ostream& os, const ImageHeader::ImageSections& section);
459 std::ostream& operator<<(std::ostream& os, const ImageSection& section);
460 std::ostream& operator<<(std::ostream& os, const ImageHeader::StorageMode& mode);
461 
462 }  // namespace art
463 
464 #endif  // ART_RUNTIME_IMAGE_H_
465