/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_RUNTIME_GC_SPACE_IMAGE_SPACE_H_
#define ART_RUNTIME_GC_SPACE_IMAGE_SPACE_H_

#include "android-base/unique_fd.h"
#include "base/array_ref.h"
#include "gc/accounting/space_bitmap.h"
#include "image.h"
#include "runtime.h"
#include "space.h"

namespace art {

class DexFile;
enum class InstructionSet;
class OatFile;
class OatHeader;

namespace gc {
namespace space {

// An image space is a space backed with a memory mapped image.
class ImageSpace : public MemMapSpace {
 public:
  SpaceType GetType() const override {
    return kSpaceTypeImageSpace;
  }

  // The separator for boot image location components.
  static constexpr char kComponentSeparator = ':';
  // The separator for profile filename.
  static constexpr char kProfileSeparator = '!';

  // Load boot image spaces for specified boot class path, image location, instruction set, etc.
  //
  // On successful return, the loaded spaces are added to boot_image_spaces (which must be
  // empty on entry) and `extra_reservation` is set to the requested reservation located
  // after the end of the last loaded oat file.
  //
  // IMAGE LOCATION
  //
  // The "image location" is a colon-separated list that specifies one or more
  // components by name and may also specify search paths for extensions
  // corresponding to the remaining boot class path (BCP) extensions.
  //
  // The primary boot image can be specified as one of
  //     <path>/<base-name>
  //     <base-name>
  // and the path of the first BCP component is used for the second form.
  // The specification may be followed by one or more profile specifications, where each profile
  // specification is one of
  //     !<profile-path>/<profile-name>
  //     !<profile-name>
  // and the profiles will be used to compile the primary boot image when loading the boot image if
  // the on-disk version is not acceptable (either not present or fails validation, presumably
  // because it's out of date). The primary boot image is compiled with no dependency.
  //
  // Named extension specifications must correspond to an expansion of the
  // <base-name> with a BCP component (for example boot.art with the BCP
  // component name <jar-path>/framework.jar expands to boot-framework.art).
  // They can be similarly specified as one of
  //     <ext-path>/<ext-name>
  //     <ext-name>
  // and must be listed in the order of their corresponding BCP components.
  // Similarly, the specification may be followed by one or more profile specifications, where each
  // profile specification is one of
  //     !<profile-path>/<profile-name>
  //     !<profile-name>
  // and the profiles will be used to compile the extension when loading the boot image if the
  // on-disk version is not acceptable (either not present or fails validation, presumably because
  // it's out of date). The primary boot image (i.e., the first element in "image location") is the
  // dependency that each extension is compiled against.
  //
  // Search paths for remaining extensions can be specified after named
  // components as one of
  //     <search-path>/*
  //     *
  // where the second form means that the path of a particular BCP component
  // should be used to search for that component's boot image extension.
  //
  // The actual filename shall be derived from the specified locations using
  // `GetSystemImageFilename()`.
  //
  // Example image locations:
  //     /system/framework/boot.art
  //         - only primary boot image with full path.
  //     /data/misc/apexdata/com.android.art/dalvik-cache/boot.art!/apex/com.android.art/etc/boot-image.prof!/system/etc/boot-image.prof
  //         - only primary boot image with full path; if the primary boot image is not found or
  //           broken, compile it in memory using two specified profile files at the exact paths.
  //     boot.art:boot-framework.art
  //         - primary and one extension, use BCP component paths.
  //     /apex/com.android.art/boot.art:*
  //         - primary with exact location, search for the rest based on BCP
  //           component paths.
  //     boot.art:/system/framework/*
  //         - primary based on BCP component path, search for extensions in
  //           /system/framework.
  //     /apex/com.android.art/boot.art:/system/framework/*:*
  //         - primary with exact location, search for extensions first in
  //           /system/framework, then in the corresponding BCP component path.
  //     /apex/com.android.art/boot.art:*:/system/framework/*
  //         - primary with exact location, search for extensions first in the
  //           corresponding BCP component path and then in /system/framework.
  //     /apex/com.android.art/boot.art:*:boot-framework.jar
  //         - invalid, named components may not follow search paths.
  //     boot.art:boot-framework.jar!/system/framework/framework.prof
  //         - primary and one extension, use BCP component paths; if extension
  //           is not found or broken compile it in memory using the specified
  //           profile file from the exact path.
  //     boot.art:boot-framework.jar:conscrypt.jar!conscrypt.prof
  //         - primary and two extensions, use BCP component paths; only the
  //           second extension has a profile file and can be compiled in memory
  //           when it is not found or broken, using the specified profile file
  //           in the BCP component path and it is compiled against the primary
  //           and first extension and only if the first extension is OK.
  //     boot.art:boot-framework.jar!framework.prof:conscrypt.jar!conscrypt.prof
  //         - primary and two extensions, use BCP component paths; if any
  //           extension is not found or broken compile it in memory using
  //           the specified profile file in the BCP component path, each
  //           extension is compiled only against the primary boot image.
  static bool LoadBootImage(
      const std::vector<std::string>& boot_class_path,
      const std::vector<std::string>& boot_class_path_locations,
      const std::vector<int>& boot_class_path_fds,
      const std::vector<int>& boot_class_path_image_fds,
      const std::vector<int>& boot_class_path_vdex_fds,
      const std::vector<int>& boot_class_path_oat_fds,
      const std::vector<std::string>& image_locations,
      const InstructionSet image_isa,
      bool relocate,
      bool executable,
      size_t extra_reservation_size,
      bool allow_in_memory_compilation,
      /*out*/std::vector<std::unique_ptr<ImageSpace>>* boot_image_spaces,
      /*out*/MemMap* extra_reservation) REQUIRES_SHARED(Locks::mutator_lock_);

  // Try to open an existing app image space for an oat file,
  // using the boot image spaces from the current Runtime.
  static std::unique_ptr<ImageSpace> CreateFromAppImage(const char* image,
                                                        const OatFile* oat_file,
                                                        std::string* error_msg)
      REQUIRES_SHARED(Locks::mutator_lock_);
  // Try to open an existing app image space for an the oat file and given boot image spaces.
  static std::unique_ptr<ImageSpace> CreateFromAppImage(
      const char* image,
      const OatFile* oat_file,
      ArrayRef<ImageSpace* const> boot_image_spaces,
      std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_);

  // Checks whether we have a primary boot image on the disk.
  static bool IsBootClassPathOnDisk(InstructionSet image_isa);

  // Give access to the OatFile.
  const OatFile* GetOatFile() const;

  // Releases the OatFile from the ImageSpace so it can be transfer to
  // the caller, presumably the OatFileManager.
  std::unique_ptr<const OatFile> ReleaseOatFile();

  void VerifyImageAllocations()
      REQUIRES_SHARED(Locks::mutator_lock_);

  const ImageHeader& GetImageHeader() const {
    return *reinterpret_cast<ImageHeader*>(Begin());
  }

  // Actual filename where image was loaded from.
  // For example: /system/framework/arm64/boot.art
  const std::string GetImageFilename() const {
    return GetName();
  }

  // Symbolic location for image.
  // For example: /system/framework/boot.art
  const std::string GetImageLocation() const {
    return image_location_;
  }

  const std::vector<std::string>& GetProfileFiles() const { return profile_files_; }

  accounting::ContinuousSpaceBitmap* GetLiveBitmap() override {
    return &live_bitmap_;
  }

  accounting::ContinuousSpaceBitmap* GetMarkBitmap() override {
    // ImageSpaces have the same bitmap for both live and marked. This helps reduce the number of
    // special cases to test against.
    return &live_bitmap_;
  }

  // Compute the number of components in the image (contributing jar files).
  size_t GetComponentCount() const {
    return GetImageHeader().GetComponentCount();
  }

  void Dump(std::ostream& os) const override;

  // Sweeping image spaces is a NOP.
  void Sweep(bool /* swap_bitmaps */, size_t* /* freed_objects */, size_t* /* freed_bytes */) {
  }

  bool CanMoveObjects() const override {
    return false;
  }

  // Returns the filename of the image corresponding to
  // requested image_location, or the filename where a new image
  // should be written if one doesn't exist. Looks for a generated
  // image in the specified location.
  //
  // Returns true if an image was found, false otherwise.
  static bool FindImageFilename(const char* image_location,
                                InstructionSet image_isa,
                                std::string* system_location,
                                bool* has_system);

  // The leading character in an image checksum part of boot class path checksums.
  static constexpr char kImageChecksumPrefix = 'i';
  // The leading character in a dex file checksum part of boot class path checksums.
  static constexpr char kDexFileChecksumPrefix = 'd';

  // Returns the checksums for the boot image, extensions and extra boot class path dex files,
  // based on the image spaces and boot class path dex files loaded in memory.
  // The `image_spaces` must correspond to the head of the `boot_class_path`.
  static std::string GetBootClassPathChecksums(ArrayRef<ImageSpace* const> image_spaces,
                                               ArrayRef<const DexFile* const> boot_class_path);

  // Returns the total number of components (jar files) associated with the image spaces.
  static size_t GetNumberOfComponents(ArrayRef<gc::space::ImageSpace* const> image_spaces);

  // Returns whether the oat checksums and boot class path description are valid
  // for the given boot image spaces and boot class path. Used for boot image extensions.
  static bool VerifyBootClassPathChecksums(
      std::string_view oat_checksums,
      std::string_view oat_boot_class_path,
      ArrayRef<const std::unique_ptr<ImageSpace>> image_spaces,
      ArrayRef<const std::string> boot_class_path_locations,
      ArrayRef<const std::string> boot_class_path,
      /*out*/std::string* error_msg);

  // Expand a single image location to multi-image locations based on the dex locations.
  static std::vector<std::string> ExpandMultiImageLocations(
      ArrayRef<const std::string> dex_locations,
      const std::string& image_location,
      bool boot_image_extension = false);

  // Returns true if the APEX versions in the OAT header match the given APEX versions.
  static bool ValidateApexVersions(const OatHeader& oat_header,
                                   const std::string& apex_versions,
                                   const std::string& file_location,
                                   std::string* error_msg);

  // Returns true if the dex checksums in the given oat file match the
  // checksums of the original dex files on disk. This is intended to be used
  // to validate the boot image oat file, which may contain dex entries from
  // multiple different (possibly multidex) dex files on disk. Prefer the
  // OatFileAssistant for validating regular app oat files because the
  // OatFileAssistant caches dex checksums that are reused to check both the
  // oat and odex file.
  //
  // This function is exposed for testing purposes.
  //
  // Calling this function requires an active runtime.
  static bool ValidateOatFile(const OatFile& oat_file, std::string* error_msg);

  // Same as above, but allows to use `dex_filenames` and `dex_fds` to find the dex files instead of
  // using the dex filenames in the header of the oat file, and also takes `apex_versions` from the
  // input. This overload is useful when the actual dex filenames are different from what's in the
  // header (e.g., when we run dex2oat on host), when the runtime can only access files through FDs
  // (e.g., when we run dex2oat on target in a restricted SELinux domain), or when there is no
  // active runtime.
  //
  // Calling this function does not require an active runtime.
  static bool ValidateOatFile(const OatFile& oat_file,
                              std::string* error_msg,
                              ArrayRef<const std::string> dex_filenames,
                              ArrayRef<const int> dex_fds,
                              const std::string& apex_versions);

  // Return the end of the image which includes non-heap objects such as ArtMethods and ArtFields.
  uint8_t* GetImageEnd() const {
    return Begin() + GetImageHeader().GetImageSize();
  }

  void DumpSections(std::ostream& os) const;

  // De-initialize the image-space by undoing the effects in Init().
  virtual ~ImageSpace();

  void ReleaseMetadata() REQUIRES_SHARED(Locks::mutator_lock_);

  static void AppendImageChecksum(uint32_t component_count,
                                  uint32_t checksum,
                                  /*inout*/ std::string* checksums);

  static size_t CheckAndCountBCPComponents(std::string_view oat_boot_class_path,
                                           ArrayRef<const std::string> boot_class_path,
                                           /*out*/ std::string* error_msg);

  // Helper class to find the primary boot image and boot image extensions
  // and determine the boot image layout.
  class BootImageLayout {
   public:
    // Description of a "chunk" of the boot image, i.e. either primary boot image
    // or a boot image extension, used in conjunction with the boot class path to
    // load boot image components.
    struct ImageChunk {
      std::string base_location;
      std::string base_filename;
      std::vector<std::string> profile_files;
      size_t start_index;
      uint32_t component_count;
      uint32_t image_space_count;
      uint32_t reservation_size;
      uint32_t checksum;
      uint32_t boot_image_component_count;
      uint32_t boot_image_checksum;
      uint32_t boot_image_size;

      // The following file descriptors hold the memfd files for extensions compiled
      // in memory and described by the above fields. We want to use them to mmap()
      // the contents and then close them while treating the ImageChunk description
      // as immutable (const), so make these fields explicitly mutable.
      mutable android::base::unique_fd art_fd;
      mutable android::base::unique_fd vdex_fd;
      mutable android::base::unique_fd oat_fd;
    };

    BootImageLayout(ArrayRef<const std::string> image_locations,
                    ArrayRef<const std::string> boot_class_path,
                    ArrayRef<const std::string> boot_class_path_locations,
                    ArrayRef<const int> boot_class_path_fds,
                    ArrayRef<const int> boot_class_path_image_fds,
                    ArrayRef<const int> boot_class_path_vdex_fds,
                    ArrayRef<const int> boot_class_path_oat_fds,
                    const std::string* apex_versions = nullptr)
        : image_locations_(image_locations),
          boot_class_path_(boot_class_path),
          boot_class_path_locations_(boot_class_path_locations),
          boot_class_path_fds_(boot_class_path_fds),
          boot_class_path_image_fds_(boot_class_path_image_fds),
          boot_class_path_vdex_fds_(boot_class_path_vdex_fds),
          boot_class_path_oat_fds_(boot_class_path_oat_fds),
          apex_versions_(GetApexVersions(apex_versions)) {}

    std::string GetPrimaryImageLocation();

    bool LoadFromSystem(InstructionSet image_isa,
                        bool allow_in_memory_compilation,
                        /*out*/ std::string* error_msg);

    ArrayRef<const ImageChunk> GetChunks() const { return ArrayRef<const ImageChunk>(chunks_); }

    uint32_t GetBaseAddress() const { return base_address_; }

    size_t GetNextBcpIndex() const { return next_bcp_index_; }

    size_t GetTotalComponentCount() const { return total_component_count_; }

    size_t GetTotalReservationSize() const { return total_reservation_size_; }

   private:
    struct NamedComponentLocation {
      std::string base_location;
      size_t bcp_index;
      std::vector<std::string> profile_filenames;
    };

    std::string ExpandLocationImpl(const std::string& location,
                                   size_t bcp_index,
                                   bool boot_image_extension) {
      std::vector<std::string> expanded = ExpandMultiImageLocations(
          ArrayRef<const std::string>(boot_class_path_).SubArray(bcp_index, 1u),
          location,
          boot_image_extension);
      DCHECK_EQ(expanded.size(), 1u);
      return expanded[0];
    }

    std::string ExpandLocation(const std::string& location, size_t bcp_index) {
      if (bcp_index == 0u) {
        DCHECK_EQ(location,
                  ExpandLocationImpl(location, bcp_index, /*boot_image_extension=*/false));
        return location;
      } else {
        return ExpandLocationImpl(location, bcp_index, /*boot_image_extension=*/true);
      }
    }

    std::string GetBcpComponentPath(size_t bcp_index) {
      DCHECK_LE(bcp_index, boot_class_path_.size());
      size_t bcp_slash_pos = boot_class_path_[bcp_index].rfind('/');
      DCHECK_NE(bcp_slash_pos, std::string::npos);
      return boot_class_path_[bcp_index].substr(0u, bcp_slash_pos + 1u);
    }

    bool VerifyImageLocation(ArrayRef<const std::string> components,
                             /*out*/ size_t* named_components_count,
                             /*out*/ std::string* error_msg);

    bool MatchNamedComponents(
        ArrayRef<const std::string> named_components,
        /*out*/ std::vector<NamedComponentLocation>* named_component_locations,
        /*out*/ std::string* error_msg);

    bool ValidateBootImageChecksum(const char* file_description,
                                   const ImageHeader& header,
                                   /*out*/ std::string* error_msg);

    bool ValidateHeader(const ImageHeader& header,
                        size_t bcp_index,
                        const char* file_description,
                        /*out*/ std::string* error_msg);

    bool ValidateOatFile(const std::string& base_location,
                         const std::string& base_filename,
                         size_t bcp_index,
                         size_t component_count,
                         /*out*/ std::string* error_msg);

    bool ReadHeader(const std::string& base_location,
                    const std::string& base_filename,
                    size_t bcp_index,
                    /*out*/ std::string* error_msg);

    // Compiles a consecutive subsequence of bootclasspath dex files, whose contents are included in
    // the profiles specified by `profile_filenames`, starting from `bcp_index`.
    bool CompileBootclasspathElements(const std::string& base_location,
                                      const std::string& base_filename,
                                      size_t bcp_index,
                                      const std::vector<std::string>& profile_filenames,
                                      ArrayRef<const std::string> dependencies,
                                      /*out*/ std::string* error_msg);

    // Returns true if a least one chuck has been loaded.
    template <typename FilenameFn>
    bool Load(FilenameFn&& filename_fn,
              bool allow_in_memory_compilation,
              /*out*/ std::string* error_msg);

    // This function prefers taking APEX versions from the input instead of from the runtime if
    // possible. If the input is present, `ValidateFromSystem` can work without an active runtime.
    static const std::string& GetApexVersions(const std::string* apex_versions) {
      if (apex_versions == nullptr) {
        DCHECK(Runtime::Current() != nullptr);
        return Runtime::Current()->GetApexVersions();
      } else {
        return *apex_versions;
      }
    }

    ArrayRef<const std::string> image_locations_;
    ArrayRef<const std::string> boot_class_path_;
    ArrayRef<const std::string> boot_class_path_locations_;
    ArrayRef<const int> boot_class_path_fds_;
    ArrayRef<const int> boot_class_path_image_fds_;
    ArrayRef<const int> boot_class_path_vdex_fds_;
    ArrayRef<const int> boot_class_path_oat_fds_;

    std::vector<ImageChunk> chunks_;
    uint32_t base_address_ = 0u;
    size_t next_bcp_index_ = 0u;
    size_t total_component_count_ = 0u;
    size_t total_reservation_size_ = 0u;
    const std::string& apex_versions_;
  };

 protected:
  // Tries to initialize an ImageSpace from the given image path, returning null on error.
  //
  // If validate_oat_file is false (for /system), do not verify that image's OatFile is up-to-date
  // relative to its DexFile inputs. Otherwise, validate `oat_file` and abandon it if the validation
  // fails. If the oat_file is null, it uses the oat file from the image.
  static std::unique_ptr<ImageSpace> Init(const char* image_filename,
                                          const char* image_location,
                                          bool validate_oat_file,
                                          const OatFile* oat_file,
                                          std::string* error_msg)
      REQUIRES_SHARED(Locks::mutator_lock_);

  static Atomic<uint32_t> bitmap_index_;

  accounting::ContinuousSpaceBitmap live_bitmap_;

  ImageSpace(const std::string& name,
             const char* image_location,
             const std::vector<std::string>& profile_files,
             MemMap&& mem_map,
             accounting::ContinuousSpaceBitmap&& live_bitmap,
             uint8_t* end);

  // The OatFile associated with the image during early startup to
  // reserve space contiguous to the image. It is later released to
  // the ClassLinker during it's initialization.
  std::unique_ptr<OatFile> oat_file_;

  // There are times when we need to find the boot image oat file. As
  // we release ownership during startup, keep a non-owned reference.
  const OatFile* oat_file_non_owned_;

  const std::string image_location_;
  const std::vector<std::string> profile_files_;

  friend class Space;

 private:
  class BootImageLoader;
  template <typename ReferenceVisitor>
  class ClassTableVisitor;
  class RemapInternedStringsVisitor;
  class Loader;
  template <typename PatchObjectVisitor>
  class PatchArtFieldVisitor;
  template <PointerSize kPointerSize, typename PatchObjectVisitor, typename PatchCodeVisitor>
  class PatchArtMethodVisitor;
  template <PointerSize kPointerSize, typename HeapVisitor, typename NativeVisitor>
  class PatchObjectVisitor;

  DISALLOW_COPY_AND_ASSIGN(ImageSpace);
};

}  // namespace space
}  // namespace gc
}  // namespace art

#endif  // ART_RUNTIME_GC_SPACE_IMAGE_SPACE_H_
