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