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