/*
 * 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 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,
                                                 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,
                                                 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,
                                        std::string* error_msg) {
    return OpenAtAddress(nullptr,
                         0,
                         false,
                         vdex_filename,
                         writable,
                         low_4gb,
                         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,
                                        std::string* error_msg) {
    return OpenAtAddress(nullptr,
                         0,
                         false,
                         file_fd,
                         vdex_length,
                         vdex_filename,
                         writable,
                         low_4gb,
                         error_msg);
  }

  static std::unique_ptr<VdexFile> OpenFromDm(const std::string& filename,
                                              const ZipArchive& archive);

  const uint8_t* Begin() const { return mmap_.Begin(); }
  const uint8_t* End() const { return mmap_.End(); }
  size_t Size() const { return mmap_.Size(); }
  bool Contains(const uint8_t* pointer, size_t size) const {
    return Begin() <= pointer && size <= Size() && pointer <= End() - 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;

  // Returns true if all dex files are standard dex rather than compact dex.
  // Also returns true if there are no dex files at all.
  bool HasOnlyStandardDexFiles() 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_
