/*
 * Copyright (C) 2016 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_VDEX_FILE_H_
#define ART_RUNTIME_VDEX_FILE_H_

#include <stdint.h>
#include <string>

#include "base/array_ref.h"
#include "base/macros.h"
#include "base/mem_map.h"
#include "base/os.h"
#include "class_status.h"
#include "dex/compact_offset_table.h"
#include "dex/dex_file.h"
#include "quicken_info.h"
#include "handle.h"

namespace art {

class ClassLoaderContext;
class Thread;

namespace mirror {
class Class;
}

namespace verifier {
class VerifierDeps;
}  // namespace verifier

// VDEX files contain extracted DEX files. The VdexFile class maps the file to
// memory and provides tools for accessing its individual sections.
//
// In the description below, D is the number of dex files.
//
// File format:
//   VdexFileHeader    fixed-length header
//   VdexSectionHeader[kNumberOfSections]
//
//   Checksum section
//     VdexChecksum[D]
//
//   Optionally:
//      DexSection
//          DEX[0]                array of the input DEX files
//          DEX[1]
//          ...
//          DEX[D-1]
//
//   VerifierDeps
//      4-byte alignment
//      uint32[D]                  DexFileDeps offsets for each dex file
//      DexFileDeps[D][]           verification dependencies
//        4-byte alignment
//        uint32[class_def_size]     TypeAssignability offsets (kNotVerifiedMarker for a class
//                                        that isn't verified)
//        uint32                     Offset of end of AssignabilityType sets
//        uint8[]                    AssignabilityType sets
//        4-byte alignment
//        uint32                     Number of strings
//        uint32[]                   String data offsets for each string
//        uint8[]                    String data


enum VdexSection : uint32_t {
  kChecksumSection = 0,
  kDexFileSection = 1,
  kVerifierDepsSection = 2,
  kTypeLookupTableSection = 3,
  kNumberOfSections = 4,
};

class VdexFile {
 public:
  using VdexChecksum = uint32_t;

  struct VdexSectionHeader {
    VdexSection section_kind;
    uint32_t section_offset;
    uint32_t section_size;

    VdexSectionHeader(VdexSection kind, uint32_t offset, uint32_t size)
        : section_kind(kind), section_offset(offset), section_size(size) {}

    VdexSectionHeader() {}
  };

  struct VdexFileHeader {
   public:
    explicit VdexFileHeader(bool has_dex_section);

    const char* GetMagic() const { return reinterpret_cast<const char*>(magic_); }
    const char* GetVdexVersion() const {
      return reinterpret_cast<const char*>(vdex_version_);
    }
    uint32_t GetNumberOfSections() const {
      return number_of_sections_;
    }
    bool IsMagicValid() const;
    bool IsVdexVersionValid() const;
    bool IsValid() const {
      return IsMagicValid() && IsVdexVersionValid();
    }

    static constexpr uint8_t kVdexInvalidMagic[] = { 'w', 'd', 'e', 'x' };

   private:
    static constexpr uint8_t kVdexMagic[] = { 'v', 'd', 'e', 'x' };

    // The format version of the verifier deps header and the verifier deps.
    // Last update: Introduce vdex sections.
    static constexpr uint8_t kVdexVersion[] = { '0', '2', '7', '\0' };

    uint8_t magic_[4];
    uint8_t vdex_version_[4];
    uint32_t number_of_sections_;
  };

  const VdexSectionHeader& GetSectionHeaderAt(uint32_t index) const {
    DCHECK_LT(index, GetVdexFileHeader().GetNumberOfSections());
    return *reinterpret_cast<const VdexSectionHeader*>(
        Begin() + sizeof(VdexFileHeader) + index * sizeof(VdexSectionHeader));
  }

  const VdexSectionHeader& GetSectionHeader(VdexSection kind) const {
    return GetSectionHeaderAt(static_cast<uint32_t>(kind));
  }

  static size_t GetChecksumsOffset() {
    return sizeof(VdexFileHeader) +
        static_cast<size_t>(VdexSection::kNumberOfSections) * sizeof(VdexSectionHeader);
  }

  size_t GetComputedFileSize() const {
    const VdexFileHeader& header = GetVdexFileHeader();
    uint32_t size = sizeof(VdexFileHeader) +
        header.GetNumberOfSections() * sizeof(VdexSectionHeader);
    for (uint32_t i = 0; i < header.GetNumberOfSections(); ++i) {
      size = std::max(size,
                      GetSectionHeaderAt(i).section_offset + GetSectionHeaderAt(i).section_size);
    }
    return size;
  }

  bool IsDexSectionValid() const;

  bool HasDexSection() const {
    return GetSectionHeader(VdexSection::kDexFileSection).section_size != 0u;
  }
  uint32_t GetVerifierDepsSize() const {
    return GetSectionHeader(VdexSection::kVerifierDepsSection).section_size;
  }
  uint32_t GetNumberOfDexFiles() const {
    return GetSectionHeader(VdexSection::kChecksumSection).section_size / sizeof(VdexChecksum);
  }

  bool HasTypeLookupTableSection() const {
    return GetVdexFileHeader().GetNumberOfSections() >= (kTypeLookupTableSection + 1);
  }

  const VdexChecksum* GetDexChecksumsArray() const {
    return reinterpret_cast<const VdexChecksum*>(
        Begin() + GetSectionHeader(VdexSection::kChecksumSection).section_offset);
  }

  VdexChecksum GetDexChecksumAt(size_t idx) const {
    DCHECK_LT(idx, GetNumberOfDexFiles());
    return GetDexChecksumsArray()[idx];
  }

  // Note: The file is called "primary" to match the naming with profiles.
  static const constexpr char* kVdexNameInDmFile = "primary.vdex";

  explicit VdexFile(MemMap&& mmap) : mmap_(std::move(mmap)) {}

  // Returns nullptr if the vdex file cannot be opened or is not valid.
  // The mmap_* parameters can be left empty (nullptr/0/false) to allocate at random address.
  static std::unique_ptr<VdexFile> OpenAtAddress(uint8_t* mmap_addr,
                                                 size_t mmap_size,
                                                 bool mmap_reuse,
                                                 const std::string& vdex_filename,
                                                 bool writable,
                                                 bool low_4gb,
                                                 bool unquicken,
                                                 std::string* error_msg);

  // Returns nullptr if the vdex file cannot be opened or is not valid.
  // The mmap_* parameters can be left empty (nullptr/0/false) to allocate at random address.
  static std::unique_ptr<VdexFile> OpenAtAddress(uint8_t* mmap_addr,
                                                 size_t mmap_size,
                                                 bool mmap_reuse,
                                                 int file_fd,
                                                 size_t vdex_length,
                                                 const std::string& vdex_filename,
                                                 bool writable,
                                                 bool low_4gb,
                                                 bool unquicken,
                                                 std::string* error_msg);

  // Returns nullptr if the vdex file cannot be opened or is not valid.
  static std::unique_ptr<VdexFile> Open(const std::string& vdex_filename,
                                        bool writable,
                                        bool low_4gb,
                                        bool unquicken,
                                        std::string* error_msg) {
    return OpenAtAddress(nullptr,
                         0,
                         false,
                         vdex_filename,
                         writable,
                         low_4gb,
                         unquicken,
                         error_msg);
  }

  // Returns nullptr if the vdex file cannot be opened or is not valid.
  static std::unique_ptr<VdexFile> Open(int file_fd,
                                        size_t vdex_length,
                                        const std::string& vdex_filename,
                                        bool writable,
                                        bool low_4gb,
                                        bool unquicken,
                                        std::string* error_msg) {
    return OpenAtAddress(nullptr,
                         0,
                         false,
                         file_fd,
                         vdex_length,
                         vdex_filename,
                         writable,
                         low_4gb,
                         unquicken,
                         error_msg);
  }

  const uint8_t* Begin() const { return mmap_.Begin(); }
  const uint8_t* End() const { return mmap_.End(); }
  size_t Size() const { return mmap_.Size(); }

  const VdexFileHeader& GetVdexFileHeader() const {
    return *reinterpret_cast<const VdexFileHeader*>(Begin());
  }

  ArrayRef<const uint8_t> GetVerifierDepsData() const {
    return ArrayRef<const uint8_t>(
        Begin() + GetSectionHeader(VdexSection::kVerifierDepsSection).section_offset,
        GetSectionHeader(VdexSection::kVerifierDepsSection).section_size);
  }

  bool IsValid() const {
    return mmap_.Size() >= sizeof(VdexFileHeader) && GetVdexFileHeader().IsValid();
  }

  // This method is for iterating over the dex files in the vdex. If `cursor` is null,
  // the first dex file is returned. If `cursor` is not null, it must point to a dex
  // file and this method returns the next dex file if there is one, or null if there
  // is none.
  const uint8_t* GetNextDexFileData(const uint8_t* cursor, uint32_t dex_file_index) const;

  const uint8_t* GetNextTypeLookupTableData(const uint8_t* cursor, uint32_t dex_file_index) const;

  // Get the location checksum of the dex file number `dex_file_index`.
  uint32_t GetLocationChecksum(uint32_t dex_file_index) const {
    DCHECK_LT(dex_file_index, GetNumberOfDexFiles());
    return GetDexChecksumAt(dex_file_index);
  }

  // Open all the dex files contained in this vdex file.
  bool OpenAllDexFiles(std::vector<std::unique_ptr<const DexFile>>* dex_files,
                       std::string* error_msg) const;

  // Writes a vdex into `path` and returns true on success.
  // The vdex will not contain a dex section but will store checksums of `dex_files`,
  // encoded `verifier_deps`, as well as the current boot class path cheksum and
  // encoded `class_loader_context`.
  static bool WriteToDisk(const std::string& path,
                          const std::vector<const DexFile*>& dex_files,
                          const verifier::VerifierDeps& verifier_deps,
                          std::string* error_msg);

  // Returns true if the dex file checksums stored in the vdex header match
  // the checksums in `dex_headers`. Both the number of dex files and their
  // order must match too.
  bool MatchesDexFileChecksums(const std::vector<const DexFile::Header*>& dex_headers) const;

  ClassStatus ComputeClassStatus(Thread* self, Handle<mirror::Class> cls) const
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Return the name of the underlying `MemMap` of the vdex file, typically the
  // location on disk of the vdex file.
  const std::string& GetName() const {
    return mmap_.GetName();
  }

 private:
  bool ContainsDexFile(const DexFile& dex_file) const;

  const uint8_t* DexBegin() const {
    DCHECK(HasDexSection());
    return Begin() + GetSectionHeader(VdexSection::kDexFileSection).section_offset;
  }

  const uint8_t* TypeLookupTableDataBegin() const {
    DCHECK(HasTypeLookupTableSection());
    return Begin() + GetSectionHeader(VdexSection::kTypeLookupTableSection).section_offset;
  }

  MemMap mmap_;

  DISALLOW_COPY_AND_ASSIGN(VdexFile);
};

}  // namespace art

#endif  // ART_RUNTIME_VDEX_FILE_H_
