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_GC_SPACE_IMAGE_SPACE_H_
18 #define ART_RUNTIME_GC_SPACE_IMAGE_SPACE_H_
19 
20 #include "gc/accounting/space_bitmap.h"
21 #include "image.h"
22 #include "space.h"
23 
24 namespace art {
25 
26 template <typename T> class ArrayRef;
27 class DexFile;
28 enum class InstructionSet;
29 class OatFile;
30 
31 namespace gc {
32 namespace space {
33 
34 // An image space is a space backed with a memory mapped image.
35 class ImageSpace : public MemMapSpace {
36  public:
GetType()37   SpaceType GetType() const override {
38     return kSpaceTypeImageSpace;
39   }
40 
41   // The separator for boot image location components.
42   static constexpr char kComponentSeparator = ':';
43   // The separator for profile filename.
44   static constexpr char kProfileSeparator = '!';
45 
46   // Load boot image spaces for specified boot class path, image location, instruction set, etc.
47   //
48   // On successful return, the loaded spaces are added to boot_image_spaces (which must be
49   // empty on entry) and `extra_reservation` is set to the requested reservation located
50   // after the end of the last loaded oat file.
51   //
52   // IMAGE LOCATION
53   //
54   // The "image location" is a colon-separated list that specifies one or more
55   // components by name and may also specify search paths for extensions
56   // corresponding to the remaining boot class path (BCP) extensions.
57   //
58   // The primary boot image can be specified as one of
59   //     <path>/<base-name>
60   //     <base-name>
61   // and the path of the first BCP component is used for the second form.
62   //
63   // Named extension specifications must correspond to an expansion of the
64   // <base-name> with a BCP component (for example boot.art with the BCP
65   // component name <jar-path>/framework.jar expands to boot-framework.art).
66   // They can be similarly specified as one of
67   //     <ext-path>/<ext-name>
68   //     <ext-name>
69   // and must be listed in the order of their corresponding BCP components.
70   // The specification may have a suffix with profile specification, one of
71   //     !<ext-path>/<ext-name>
72   //     !<ext-name>
73   // and this profile will be used to compile the extension when loading the
74   // boot image if the on-disk version is not acceptable (either not present
75   // or fails validation, presumably because it's out of date). The first
76   // extension specification that includes the profile specification also
77   // terminates the list of the boot image dependencies that each extension
78   // is compiled against.
79   //
80   // Search paths for remaining extensions can be specified after named
81   // components as one of
82   //     <search-path>/*
83   //     *
84   // where the second form means that the path of a particular BCP component
85   // should be used to search for that component's boot image extension.
86   //
87   // The actual filename shall be derived from the specified locations using
88   // `GetSystemImageFilename()` or `GetDalvikCacheFilename()`.
89   //
90   // Example image locations:
91   //     /system/framework/boot.art
92   //         - only primary boot image with full path.
93   //     boot.art:boot-framework.art
94   //         - primary and one extension, use BCP component paths.
95   //     /apex/com.android.art/boot.art:*
96   //         - primary with exact location, search for the rest based on BCP
97   //           component paths.
98   //     boot.art:/system/framework/*
99   //         - primary based on BCP component path, search for extensions in
100   //           /system/framework.
101   //     /apex/com.android.art/boot.art:/system/framework/*:*
102   //         - primary with exact location, search for extensions first in
103   //           /system/framework, then in the corresponding BCP component path.
104   //     /apex/com.android.art/boot.art:*:/system/framework/*
105   //         - primary with exact location, search for extensions first in the
106   //           corresponding BCP component path and then in /system/framework.
107   //     /apex/com.android.art/boot.art:*:boot-framework.jar
108   //         - invalid, named components may not follow search paths.
109   //     boot.art:boot-framework.jar!/system/framework/framework.prof
110   //         - primary and one extension, use BCP component paths; if extension
111   //           is not found or broken compile it in memory using the specified
112   //           profile file from the exact path.
113   //     boot.art:boot-framework.jar:conscrypt.jar!conscrypt.prof
114   //         - primary and two extensions, use BCP component paths; only the
115   //           second extension has a profile file and can be compiled in memory
116   //           when it is not found or broken, using the specified profile file
117   //           in the BCP component path and it is compiled against the primary
118   //           and first extension and only if the first extension is OK.
119   //     boot.art:boot-framework.jar!framework.prof:conscrypt.jar!conscrypt.prof
120   //         - primary and two extensions, use BCP component paths; if any
121   //           extension is not found or broken compile it in memory using
122   //           the specified profile file in the BCP component path, each
123   //           extension is compiled only against the primary boot image.
124   static bool LoadBootImage(
125       const std::vector<std::string>& boot_class_path,
126       const std::vector<std::string>& boot_class_path_locations,
127       const std::string& image_location,
128       const InstructionSet image_isa,
129       bool relocate,
130       bool executable,
131       size_t extra_reservation_size,
132       /*out*/std::vector<std::unique_ptr<ImageSpace>>* boot_image_spaces,
133       /*out*/MemMap* extra_reservation) REQUIRES_SHARED(Locks::mutator_lock_);
134 
135   // Try to open an existing app image space for an oat file,
136   // using the boot image spaces from the current Runtime.
137   static std::unique_ptr<ImageSpace> CreateFromAppImage(const char* image,
138                                                         const OatFile* oat_file,
139                                                         std::string* error_msg)
140       REQUIRES_SHARED(Locks::mutator_lock_);
141   // Try to open an existing app image space for an the oat file and given boot image spaces.
142   static std::unique_ptr<ImageSpace> CreateFromAppImage(
143       const char* image,
144       const OatFile* oat_file,
145       ArrayRef<ImageSpace* const> boot_image_spaces,
146       std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_);
147 
148   // Checks whether we have a primary boot image on the disk.
149   static bool IsBootClassPathOnDisk(InstructionSet image_isa);
150 
151   // Give access to the OatFile.
152   const OatFile* GetOatFile() const;
153 
154   // Releases the OatFile from the ImageSpace so it can be transfer to
155   // the caller, presumably the OatFileManager.
156   std::unique_ptr<const OatFile> ReleaseOatFile();
157 
158   void VerifyImageAllocations()
159       REQUIRES_SHARED(Locks::mutator_lock_);
160 
GetImageHeader()161   const ImageHeader& GetImageHeader() const {
162     return *reinterpret_cast<ImageHeader*>(Begin());
163   }
164 
165   // Actual filename where image was loaded from.
166   // For example: /data/dalvik-cache/arm/system@framework@boot.art
GetImageFilename()167   const std::string GetImageFilename() const {
168     return GetName();
169   }
170 
171   // Symbolic location for image.
172   // For example: /system/framework/boot.art
GetImageLocation()173   const std::string GetImageLocation() const {
174     return image_location_;
175   }
176 
GetProfileFile()177   const std::string GetProfileFile() const {
178     return profile_file_;
179   }
180 
GetLiveBitmap()181   accounting::ContinuousSpaceBitmap* GetLiveBitmap() override {
182     return &live_bitmap_;
183   }
184 
GetMarkBitmap()185   accounting::ContinuousSpaceBitmap* GetMarkBitmap() override {
186     // ImageSpaces have the same bitmap for both live and marked. This helps reduce the number of
187     // special cases to test against.
188     return &live_bitmap_;
189   }
190 
191   // Compute the number of components in the image (contributing jar files).
GetComponentCount()192   size_t GetComponentCount() const {
193     return GetImageHeader().GetComponentCount();
194   }
195 
196   void Dump(std::ostream& os) const override;
197 
198   // Sweeping image spaces is a NOP.
Sweep(bool,size_t *,size_t *)199   void Sweep(bool /* swap_bitmaps */, size_t* /* freed_objects */, size_t* /* freed_bytes */) {
200   }
201 
CanMoveObjects()202   bool CanMoveObjects() const override {
203     return false;
204   }
205 
206   // Returns the filename of the image corresponding to
207   // requested image_location, or the filename where a new image
208   // should be written if one doesn't exist. Looks for a generated
209   // image in the specified location and then in the dalvik-cache.
210   //
211   // Returns true if an image was found, false otherwise.
212   static bool FindImageFilename(const char* image_location,
213                                 InstructionSet image_isa,
214                                 std::string* system_location,
215                                 bool* has_system);
216 
217   // The leading character in an image checksum part of boot class path checksums.
218   static constexpr char kImageChecksumPrefix = 'i';
219   // The leading character in a dex file checksum part of boot class path checksums.
220   static constexpr char kDexFileChecksumPrefix = 'd';
221 
222   // Returns the checksums for the boot image, extensions and extra boot class path dex files,
223   // based on the image spaces and boot class path dex files loaded in memory.
224   // The `image_spaces` must correspond to the head of the `boot_class_path`.
225   static std::string GetBootClassPathChecksums(ArrayRef<ImageSpace* const> image_spaces,
226                                                ArrayRef<const DexFile* const> boot_class_path);
227 
228   // Returns the total number of components (jar files) associated with the image spaces.
229   static size_t GetNumberOfComponents(ArrayRef<gc::space::ImageSpace* const> image_spaces);
230 
231   // Returns whether the checksums are valid for the given boot class path,
232   // image location and ISA (may differ from the ISA of an initialized Runtime).
233   // The boot image and dex files do not need to be loaded in memory.
234   static bool VerifyBootClassPathChecksums(std::string_view oat_checksums,
235                                            std::string_view oat_boot_class_path,
236                                            const std::string& image_location,
237                                            ArrayRef<const std::string> boot_class_path_locations,
238                                            ArrayRef<const std::string> boot_class_path,
239                                            InstructionSet image_isa,
240                                            /*out*/std::string* error_msg);
241 
242   // Returns whether the oat checksums and boot class path description are valid
243   // for the given boot image spaces and boot class path. Used for boot image extensions.
244   static bool VerifyBootClassPathChecksums(
245       std::string_view oat_checksums,
246       std::string_view oat_boot_class_path,
247       ArrayRef<const std::unique_ptr<ImageSpace>> image_spaces,
248       ArrayRef<const std::string> boot_class_path_locations,
249       ArrayRef<const std::string> boot_class_path,
250       /*out*/std::string* error_msg);
251 
252   // Expand a single image location to multi-image locations based on the dex locations.
253   static std::vector<std::string> ExpandMultiImageLocations(
254       ArrayRef<const std::string> dex_locations,
255       const std::string& image_location,
256       bool boot_image_extension = false);
257 
258   // Returns true if the dex checksums in the given oat file match the
259   // checksums of the original dex files on disk. This is intended to be used
260   // to validate the boot image oat file, which may contain dex entries from
261   // multiple different (possibly multidex) dex files on disk. Prefer the
262   // OatFileAssistant for validating regular app oat files because the
263   // OatFileAssistant caches dex checksums that are reused to check both the
264   // oat and odex file.
265   //
266   // This function is exposed for testing purposes.
267   static bool ValidateOatFile(const OatFile& oat_file, std::string* error_msg);
268 
269   // Return the end of the image which includes non-heap objects such as ArtMethods and ArtFields.
GetImageEnd()270   uint8_t* GetImageEnd() const {
271     return Begin() + GetImageHeader().GetImageSize();
272   }
273 
274   void DumpSections(std::ostream& os) const;
275 
276   // De-initialize the image-space by undoing the effects in Init().
277   virtual ~ImageSpace();
278 
279   void ReleaseMetadata() REQUIRES_SHARED(Locks::mutator_lock_);
280 
281  protected:
282   // Tries to initialize an ImageSpace from the given image path, returning null on error.
283   //
284   // If validate_oat_file is false (for /system), do not verify that image's OatFile is up-to-date
285   // relative to its DexFile inputs. Otherwise (for /data), validate the inputs and generate the
286   // OatFile in /data/dalvik-cache if necessary. If the oat_file is null, it uses the oat file from
287   // the image.
288   static std::unique_ptr<ImageSpace> Init(const char* image_filename,
289                                           const char* image_location,
290                                           bool validate_oat_file,
291                                           const OatFile* oat_file,
292                                           std::string* error_msg)
293       REQUIRES_SHARED(Locks::mutator_lock_);
294 
295   static Atomic<uint32_t> bitmap_index_;
296 
297   accounting::ContinuousSpaceBitmap live_bitmap_;
298 
299   ImageSpace(const std::string& name,
300              const char* image_location,
301              const char* profile_file,
302              MemMap&& mem_map,
303              accounting::ContinuousSpaceBitmap&& live_bitmap,
304              uint8_t* end);
305 
306   // The OatFile associated with the image during early startup to
307   // reserve space contiguous to the image. It is later released to
308   // the ClassLinker during it's initialization.
309   std::unique_ptr<OatFile> oat_file_;
310 
311   // There are times when we need to find the boot image oat file. As
312   // we release ownership during startup, keep a non-owned reference.
313   const OatFile* oat_file_non_owned_;
314 
315   const std::string image_location_;
316   const std::string profile_file_;
317 
318   friend class Space;
319 
320  private:
321   class BootImageLayout;
322   class BootImageLoader;
323   template <typename ReferenceVisitor>
324   class ClassTableVisitor;
325   class RemapInternedStringsVisitor;
326   class Loader;
327   template <typename PatchObjectVisitor>
328   class PatchArtFieldVisitor;
329   template <PointerSize kPointerSize, typename PatchObjectVisitor, typename PatchCodeVisitor>
330   class PatchArtMethodVisitor;
331   template <PointerSize kPointerSize, typename HeapVisitor, typename NativeVisitor>
332   class PatchObjectVisitor;
333 
334   DISALLOW_COPY_AND_ASSIGN(ImageSpace);
335 };
336 
337 }  // namespace space
338 }  // namespace gc
339 }  // namespace art
340 
341 #endif  // ART_RUNTIME_GC_SPACE_IMAGE_SPACE_H_
342