/*
 * 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 "dex/compact_offset_table.h"
#include "quicken_info.h"

namespace art {

class DexFile;

// VDEX files contain extracted DEX files. The VdexFile class maps the file to
// memory and provides tools for accessing its individual sections.
//
// File format:
//   VdexFile::VerifierDepsHeader    fixed-length header
//      Dex file checksums
//
//   Optionally:
//      VdexFile::DexSectionHeader   fixed-length header
//
//      quicken_table_off[0]  offset into QuickeningInfo section for offset table for DEX[0].
//      DEX[0]                array of the input DEX files, the bytecode may have been quickened.
//      quicken_table_off[1]
//      DEX[1]
//      ...
//      DEX[D]
//
//   VerifierDeps
//      uint8[D][]                 verification dependencies
//
//   Optionally:
//      QuickeningInfo
//        uint8[D][]                  quickening data
//        uint32[D][]                 quickening data offset tables

class VdexFile {
 public:
  struct VerifierDepsHeader {
   public:
    VerifierDepsHeader(uint32_t number_of_dex_files_,
                       uint32_t verifier_deps_size,
                       bool has_dex_section);

    const char* GetMagic() const { return reinterpret_cast<const char*>(magic_); }
    const char* GetVerifierDepsVersion() const {
      return reinterpret_cast<const char*>(verifier_deps_version_);
    }
    const char* GetDexSectionVersion() const {
      return reinterpret_cast<const char*>(dex_section_version_);
    }
    bool IsMagicValid() const;
    bool IsVerifierDepsVersionValid() const;
    bool IsDexSectionVersionValid() const;
    bool IsValid() const {
      return IsMagicValid() && IsVerifierDepsVersionValid() && IsDexSectionVersionValid();
    }
    bool HasDexSection() const;

    uint32_t GetVerifierDepsSize() const { return verifier_deps_size_; }
    uint32_t GetNumberOfDexFiles() const { return number_of_dex_files_; }

    size_t GetSizeOfChecksumsSection() const {
      return sizeof(VdexChecksum) * GetNumberOfDexFiles();
    }

    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: Add DexSectionHeader
    static constexpr uint8_t kVerifierDepsVersion[] = { '0', '1', '9', '\0' };

    // The format version of the dex section header and the dex section, containing
    // both the dex code and the quickening data.
    // Last update: Add owned section for CompactDex.
    static constexpr uint8_t kDexSectionVersion[] = { '0', '0', '2', '\0' };

    // If the .vdex file has no dex section (hence no dex code nor quickening data),
    // we encode this magic version.
    static constexpr uint8_t kDexSectionVersionEmpty[] = { '0', '0', '0', '\0' };

    uint8_t magic_[4];
    uint8_t verifier_deps_version_[4];
    uint8_t dex_section_version_[4];
    uint32_t number_of_dex_files_;
    uint32_t verifier_deps_size_;
  };

  struct DexSectionHeader {
   public:
    DexSectionHeader(uint32_t dex_size,
                     uint32_t dex_shared_data_size,
                     uint32_t quickening_info_size);

    uint32_t GetDexSize() const { return dex_size_; }
    uint32_t GetDexSharedDataSize() const { return dex_shared_data_size_; }
    uint32_t GetQuickeningInfoSize() const { return quickening_info_size_; }

    size_t GetDexSectionSize() const {
      return sizeof(DexSectionHeader) +
           GetDexSize() +
           GetDexSharedDataSize();
    }

   private:
    uint32_t dex_size_;
    uint32_t dex_shared_data_size_;
    uint32_t quickening_info_size_;

    friend class VdexFile;  // For updatig quickening_info_size_.
  };

  size_t GetComputedFileSize() const {
    size_t size = sizeof(VerifierDepsHeader);
    const VerifierDepsHeader& header = GetVerifierDepsHeader();
    size += header.GetVerifierDepsSize();
    size += header.GetSizeOfChecksumsSection();
    if (header.HasDexSection()) {
      size += GetDexSectionHeader().GetDexSectionSize();
      size += GetDexSectionHeader().GetQuickeningInfoSize();
    }
    return size;
  }

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

  typedef uint32_t VdexChecksum;
  using QuickeningTableOffsetType = uint32_t;

  explicit VdexFile(MemMap* mmap) : mmap_(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 VerifierDepsHeader& GetVerifierDepsHeader() const {
    return *reinterpret_cast<const VerifierDepsHeader*>(Begin());
  }

  uint32_t GetDexSectionHeaderOffset() const {
    return sizeof(VerifierDepsHeader) + GetVerifierDepsHeader().GetSizeOfChecksumsSection();
  }

  const DexSectionHeader& GetDexSectionHeader() const {
    DCHECK(GetVerifierDepsHeader().HasDexSection());
    return *reinterpret_cast<const DexSectionHeader*>(Begin() + GetDexSectionHeaderOffset());
  }

  const uint8_t* GetVerifierDepsStart() const {
    const uint8_t* result = Begin() + GetDexSectionHeaderOffset();
    if (GetVerifierDepsHeader().HasDexSection()) {
      // When there is a dex section, the verifier deps are after it, but before the quickening.
      return result + GetDexSectionHeader().GetDexSectionSize();
    } else {
      // When there is no dex section, the verifier deps are just after the header.
      return result;
    }
  }

  ArrayRef<const uint8_t> GetVerifierDepsData() const {
    return ArrayRef<const uint8_t>(
        GetVerifierDepsStart(),
        GetVerifierDepsHeader().GetVerifierDepsSize());
  }

  ArrayRef<const uint8_t> GetQuickeningInfo() const {
    if (GetVerifierDepsHeader().HasDexSection()) {
      return ArrayRef<const uint8_t>(
          GetVerifierDepsData().data() + GetVerifierDepsHeader().GetVerifierDepsSize(),
          GetDexSectionHeader().GetQuickeningInfoSize());
    } else {
      return ArrayRef<const uint8_t>();
    }
  }

  bool IsValid() const {
    return mmap_->Size() >= sizeof(VerifierDepsHeader) && GetVerifierDepsHeader().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) 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, GetVerifierDepsHeader().GetNumberOfDexFiles());
    return reinterpret_cast<const uint32_t*>(Begin() + sizeof(VerifierDepsHeader))[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);

  // In-place unquicken the given `dex_files` based on `quickening_info`.
  // `decompile_return_instruction` controls if RETURN_VOID_BARRIER instructions are
  // decompiled to RETURN_VOID instructions using the slower ClassDataItemIterator
  // instead of the faster QuickeningInfoIterator.
  // Always unquickens using the vdex dex files as the source for quicken tables.
  void Unquicken(const std::vector<const DexFile*>& target_dex_files,
                 bool decompile_return_instruction) const;

  // Fully unquicken `target_dex_file` based on `quickening_info`.
  void UnquickenDexFile(const DexFile& target_dex_file,
                        const DexFile& source_dex_file,
                        bool decompile_return_instruction) const;

  // Return the quickening info of a given method index (or null if it's empty).
  ArrayRef<const uint8_t> GetQuickenedInfoOf(const DexFile& dex_file,
                                             uint32_t dex_method_idx) const;

  bool HasDexSection() const {
    return GetVerifierDepsHeader().HasDexSection();
  }

 private:
  uint32_t GetQuickeningInfoTableOffset(const uint8_t* source_dex_begin) const;

  // Source dex must be the in the vdex file.
  void UnquickenDexFile(const DexFile& target_dex_file,
                        const uint8_t* source_dex_begin,
                        bool decompile_return_instruction) const;

  CompactOffsetTable::Accessor GetQuickenInfoOffsetTable(
        const DexFile& dex_file,
        const ArrayRef<const uint8_t>& quickening_info) const;

  CompactOffsetTable::Accessor GetQuickenInfoOffsetTable(
      const uint8_t* source_dex_begin,
      const ArrayRef<const uint8_t>& quickening_info) const;

  bool ContainsDexFile(const DexFile& dex_file) const;

  const uint8_t* DexBegin() const {
    DCHECK(HasDexSection());
    return Begin() + GetDexSectionHeaderOffset() + sizeof(DexSectionHeader);
  }

  const uint8_t* DexEnd() const {
    DCHECK(HasDexSection());
    return DexBegin() + GetDexSectionHeader().GetDexSize();
  }

  std::unique_ptr<MemMap> mmap_;

  DISALLOW_COPY_AND_ASSIGN(VdexFile);
};

}  // namespace art

#endif  // ART_RUNTIME_VDEX_FILE_H_
