/*
 * 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_OAT_FILE_H_
#define ART_RUNTIME_OAT_FILE_H_

#include <list>
#include <string>
#include <string_view>
#include <vector>

#include "base/array_ref.h"
#include "base/mutex.h"
#include "base/os.h"
#include "base/safe_map.h"
#include "base/tracking_safe_map.h"
#include "class_status.h"
#include "compiler_filter.h"
#include "dex/dex_file_layout.h"
#include "dex/type_lookup_table.h"
#include "dex/utf.h"
#include "index_bss_mapping.h"
#include "mirror/object.h"
#include "oat.h"
#include "runtime.h"

namespace art {

class BitVector;
class DexFile;
class ElfFile;
class DexLayoutSections;
template <class MirrorType> class GcRoot;
class MemMap;
class OatDexFile;
class OatHeader;
class OatMethodOffsets;
class OatQuickMethodHeader;
class VdexFile;

namespace dex {
struct ClassDef;
}  // namespace dex

namespace gc {
namespace collector {
class DummyOatFile;
}  // namespace collector
}  // namespace gc

// Runtime representation of the OAT file format which holds compiler output.
// The class opens an OAT file from storage and maps it to memory, typically with
// dlopen and provides access to its internal data structures (see OatWriter for
// for more details about the OAT format).
// In the process of loading OAT, the class also loads the associated VDEX file
// with the input DEX files (see VdexFile for details about the VDEX format).
// The raw DEX data are accessible transparently through the OatDexFile objects.

class OatFile {
 public:
  // Special classpath that skips shared library check.
  static constexpr const char* kSpecialSharedLibrary = "&";

  // Opens an oat file contained within the given elf file. This is always opened as
  // non-executable at the moment.
  static OatFile* OpenWithElfFile(int zip_fd,
                                  ElfFile* elf_file,
                                  VdexFile* vdex_file,
                                  const std::string& location,
                                  const char* abs_dex_location,
                                  std::string* error_msg);
  // Open an oat file. Returns null on failure.  Requested base can
  // optionally be used to request where the file should be loaded.
  // See the ResolveRelativeEncodedDexLocation for a description of how the
  // abs_dex_location argument is used.
  static OatFile* Open(int zip_fd,
                       const std::string& filename,
                       const std::string& location,
                       bool executable,
                       bool low_4gb,
                       const char* abs_dex_location,
                       /*inout*/MemMap* reservation,  // Where to load if not null.
                       /*out*/std::string* error_msg);

  // Similar to OatFile::Open(const std::string...), but accepts input vdex and
  // odex files as file descriptors. We also take zip_fd in case the vdex does not
  // contain the dex code, and we need to read it from the zip file.
  static OatFile* Open(int zip_fd,
                       int vdex_fd,
                       int oat_fd,
                       const std::string& oat_location,
                       bool executable,
                       bool low_4gb,
                       const char* abs_dex_location,
                       /*inout*/MemMap* reservation,  // Where to load if not null.
                       /*out*/std::string* error_msg);

  // Open an oat file from an already opened File.
  // Does not use dlopen underneath so cannot be used for runtime use
  // where relocations may be required. Currently used from
  // ImageWriter which wants to open a writable version from an existing
  // file descriptor for patching.
  static OatFile* OpenWritable(int zip_fd,
                               File* file,
                               const std::string& location,
                               const char* abs_dex_location,
                               std::string* error_msg);
  // Open an oat file from an already opened File. Maps it PROT_READ, MAP_PRIVATE.
  static OatFile* OpenReadable(int zip_fd,
                               File* file,
                               const std::string& location,
                               const char* abs_dex_location,
                               std::string* error_msg);

  // Initialize OatFile instance from an already loaded VdexFile. This assumes
  // the vdex does not have a dex section and accepts a vector of DexFiles separately.
  static OatFile* OpenFromVdex(const std::vector<const DexFile*>& dex_files,
                               std::unique_ptr<VdexFile>&& vdex_file,
                               const std::string& location);

  virtual ~OatFile();

  bool IsExecutable() const {
    return is_executable_;
  }

  // Indicates whether the oat file was compiled with full debugging capability.
  bool IsDebuggable() const;

  CompilerFilter::Filter GetCompilerFilter() const;

  std::string GetClassLoaderContext() const;

  const char* GetCompilationReason() const;

  const std::string& GetLocation() const {
    return location_;
  }

  const OatHeader& GetOatHeader() const;

  class OatMethod final {
   public:
    uint32_t GetCodeOffset() const;

    const void* GetQuickCode() const;

    // Returns size of quick code.
    uint32_t GetQuickCodeSize() const;
    uint32_t GetQuickCodeSizeOffset() const;

    // Returns OatQuickMethodHeader for debugging. Most callers should
    // use more specific methods such as GetQuickCodeSize.
    const OatQuickMethodHeader* GetOatQuickMethodHeader() const;
    uint32_t GetOatQuickMethodHeaderOffset() const;

    size_t GetFrameSizeInBytes() const;
    uint32_t GetCoreSpillMask() const;
    uint32_t GetFpSpillMask() const;

    const uint8_t* GetVmapTable() const;
    uint32_t GetVmapTableOffset() const;
    uint32_t GetVmapTableOffsetOffset() const;

    // Create an OatMethod with offsets relative to the given base address
    OatMethod(const uint8_t* base, const uint32_t code_offset)
        : begin_(base), code_offset_(code_offset) {
    }
    OatMethod(const OatMethod&) = default;
    ~OatMethod() {}

    OatMethod& operator=(const OatMethod&) = default;

    // A representation of an invalid OatMethod, used when an OatMethod or OatClass can't be found.
    // See ClassLinker::FindOatMethodFor.
    static const OatMethod Invalid() {
      return OatMethod(nullptr, -1);
    }

   private:
    template<class T>
    T GetOatPointer(uint32_t offset) const {
      if (offset == 0) {
        return nullptr;
      }
      return reinterpret_cast<T>(begin_ + offset);
    }

    const uint8_t* begin_;
    uint32_t code_offset_;

    friend class OatClass;
  };

  class OatClass final {
   public:
    ClassStatus GetStatus() const {
      return status_;
    }

    OatClassType GetType() const {
      return type_;
    }

    // Get the OatMethod entry based on its index into the class
    // defintion. Direct methods come first, followed by virtual
    // methods. Note that runtime created methods such as miranda
    // methods are not included.
    const OatMethod GetOatMethod(uint32_t method_index) const;

    // Return a pointer to the OatMethodOffsets for the requested
    // method_index, or null if none is present. Note that most
    // callers should use GetOatMethod.
    const OatMethodOffsets* GetOatMethodOffsets(uint32_t method_index) const;

    // Return the offset from the start of the OatFile to the
    // OatMethodOffsets for the requested method_index, or 0 if none
    // is present. Note that most callers should use GetOatMethod.
    uint32_t GetOatMethodOffsetsOffset(uint32_t method_index) const;

    // A representation of an invalid OatClass, used when an OatClass can't be found.
    // See FindOatClass().
    static OatClass Invalid() {
      return OatClass(/* oat_file= */ nullptr,
                      ClassStatus::kErrorUnresolved,
                      kOatClassNoneCompiled,
                      /* bitmap_size= */ 0,
                      /* bitmap_pointer= */ nullptr,
                      /* methods_pointer= */ nullptr);
    }

   private:
    OatClass(const OatFile* oat_file,
             ClassStatus status,
             OatClassType type,
             uint32_t bitmap_size,
             const uint32_t* bitmap_pointer,
             const OatMethodOffsets* methods_pointer);

    const OatFile* const oat_file_;

    const ClassStatus status_;

    const OatClassType type_;

    const uint32_t* const bitmap_;

    const OatMethodOffsets* const methods_pointer_;

    friend class art::OatDexFile;
  };

  // Get the OatDexFile for the given dex_location within this oat file.
  // If dex_location_checksum is non-null, the OatDexFile will only be
  // returned if it has a matching checksum.
  // If error_msg is non-null and no OatDexFile is returned, error_msg will
  // be updated with a description of why no OatDexFile was returned.
  const OatDexFile* GetOatDexFile(const char* dex_location,
                                  const uint32_t* const dex_location_checksum,
                                  /*out*/std::string* error_msg = nullptr) const
      REQUIRES(!secondary_lookup_lock_);

  const std::vector<const OatDexFile*>& GetOatDexFiles() const {
    return oat_dex_files_storage_;
  }

  size_t Size() const {
    return End() - Begin();
  }

  bool Contains(const void* p) const {
    return p >= Begin() && p < End();
  }

  size_t DataBimgRelRoSize() const {
    return DataBimgRelRoEnd() - DataBimgRelRoBegin();
  }

  size_t BssSize() const {
    return BssEnd() - BssBegin();
  }

  size_t VdexSize() const {
    return VdexEnd() - VdexBegin();
  }

  size_t BssMethodsOffset() const {
    // Note: This is used only for symbolizer and needs to return a valid .bss offset.
    return (bss_methods_ != nullptr) ? bss_methods_ - BssBegin() : BssRootsOffset();
  }

  size_t BssRootsOffset() const {
    // Note: This is used only for symbolizer and needs to return a valid .bss offset.
    return (bss_roots_ != nullptr) ? bss_roots_ - BssBegin() : BssSize();
  }

  size_t DexSize() const {
    return DexEnd() - DexBegin();
  }

  const uint8_t* Begin() const;
  const uint8_t* End() const;

  const uint8_t* DataBimgRelRoBegin() const { return data_bimg_rel_ro_begin_; }
  const uint8_t* DataBimgRelRoEnd() const { return data_bimg_rel_ro_end_; }

  const uint8_t* BssBegin() const { return bss_begin_; }
  const uint8_t* BssEnd() const { return bss_end_; }

  const uint8_t* VdexBegin() const { return vdex_begin_; }
  const uint8_t* VdexEnd() const { return vdex_end_; }

  const uint8_t* DexBegin() const;
  const uint8_t* DexEnd() const;

  ArrayRef<const uint32_t> GetBootImageRelocations() const;
  ArrayRef<ArtMethod*> GetBssMethods() const;
  ArrayRef<GcRoot<mirror::Object>> GetBssGcRoots() const;

  // Initialize relocation sections (.data.bimg.rel.ro and .bss).
  void InitializeRelocations() const;

  // Constructs the absolute dex location and/or dex file name for the relative dex
  // location (`rel_dex_location`) in the oat file, using the `abs_dex_location` of
  // the dex file this oat belongs to.
  //
  // The dex file name and dex location differ when cross compiling where the dex file
  // name is the host path (for opening files) and dex location is the future path on target.
  //
  // If not null, abs_dex_location is used to resolve the absolute dex
  // location of relative dex locations encoded in the oat file.
  // For example, given absolute location "/data/app/foo/base.apk", encoded
  // dex locations "base.apk", "base.apk!classes2.dex", etc. would be resolved
  // to "/data/app/foo/base.apk", "/data/app/foo/base.apk!classes2.dex", etc.
  // Relative encoded dex locations that don't match the given abs_dex_location
  // are left unchanged.
  //
  // Computation of both `dex_file_location` and `dex_file_name` can be skipped
  // by setting the corresponding out parameter to `nullptr`.
  static void ResolveRelativeEncodedDexLocation(const char* abs_dex_location,
                                                const std::string& rel_dex_location,
                                                /* out */ std::string* dex_file_location,
                                                /* out */ std::string* dex_file_name = nullptr);

  // Finds the associated oat class for a dex_file and descriptor. Returns an invalid OatClass on
  // error and sets found to false.
  static OatClass FindOatClass(const DexFile& dex_file, uint16_t class_def_idx, bool* found);

  VdexFile* GetVdexFile() const {
    return vdex_.get();
  }

  // Whether the OatFile embeds the Dex code.
  bool ContainsDexCode() const {
    return uncompressed_dex_files_ == nullptr;
  }

 protected:
  OatFile(const std::string& filename, bool executable);

 private:
  // The oat file name.
  //
  // The image will embed this to link its associated oat file.
  const std::string location_;

  // Pointer to the Vdex file with the Dex files for this Oat file.
  std::unique_ptr<VdexFile> vdex_;

  // Pointer to OatHeader.
  const uint8_t* begin_;

  // Pointer to end of oat region for bounds checking.
  const uint8_t* end_;

  // Pointer to the .data.bimg.rel.ro section, if present, otherwise null.
  const uint8_t* data_bimg_rel_ro_begin_;

  // Pointer to the end of the .data.bimg.rel.ro section, if present, otherwise null.
  const uint8_t* data_bimg_rel_ro_end_;

  // Pointer to the .bss section, if present, otherwise null.
  uint8_t* bss_begin_;

  // Pointer to the end of the .bss section, if present, otherwise null.
  uint8_t* bss_end_;

  // Pointer to the beginning of the ArtMethod*s in .bss section, if present, otherwise null.
  uint8_t* bss_methods_;

  // Pointer to the beginning of the GC roots in .bss section, if present, otherwise null.
  uint8_t* bss_roots_;

  // Was this oat_file loaded executable?
  const bool is_executable_;

  // Pointer to the .vdex section, if present, otherwise null.
  uint8_t* vdex_begin_;

  // Pointer to the end of the .vdex section, if present, otherwise null.
  uint8_t* vdex_end_;

  // Owning storage for the OatDexFile objects.
  std::vector<const OatDexFile*> oat_dex_files_storage_;

  // NOTE: We use a std::string_view as the key type to avoid a memory allocation on every
  // lookup with a const char* key. The std::string_view doesn't own its backing storage,
  // therefore we're using the OatFile's stored dex location as the backing storage
  // for keys in oat_dex_files_ and the string_cache_ entries for the backing storage
  // of keys in secondary_oat_dex_files_ and oat_dex_files_by_canonical_location_.
  using Table =
      AllocationTrackingSafeMap<std::string_view, const OatDexFile*, kAllocatorTagOatFile>;

  // Map each location and canonical location (if different) retrieved from the
  // oat file to its OatDexFile. This map doesn't change after it's constructed in Setup()
  // and therefore doesn't need any locking and provides the cheapest dex file lookup
  // for GetOatDexFile() for a very frequent use case. Never contains a null value.
  Table oat_dex_files_;

  // Lock guarding all members needed for secondary lookup in GetOatDexFile().
  mutable Mutex secondary_lookup_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;

  // If the primary oat_dex_files_ lookup fails, use a secondary map. This map stores
  // the results of all previous secondary lookups, whether successful (non-null) or
  // failed (null). If it doesn't contain an entry we need to calculate the canonical
  // location and use oat_dex_files_by_canonical_location_.
  mutable Table secondary_oat_dex_files_ GUARDED_BY(secondary_lookup_lock_);

  // Cache of strings. Contains the backing storage for keys in the secondary_oat_dex_files_
  // and the lazily initialized oat_dex_files_by_canonical_location_.
  // NOTE: We're keeping references to contained strings in form of std::string_view and adding
  // new strings to the end. The adding of a new element must not touch any previously stored
  // elements. std::list<> and std::deque<> satisfy this requirement, std::vector<> doesn't.
  mutable std::list<std::string> string_cache_ GUARDED_BY(secondary_lookup_lock_);

  // Cache of dex files mapped directly from a location, in case the OatFile does
  // not embed the dex code.
  std::unique_ptr<std::vector<std::unique_ptr<const DexFile>>> uncompressed_dex_files_;

  friend class gc::collector::DummyOatFile;  // For modifying begin_ and end_.
  friend class OatClass;
  friend class art::OatDexFile;
  friend class OatDumper;  // For GetBase and GetLimit
  friend class OatFileBase;
  DISALLOW_COPY_AND_ASSIGN(OatFile);
};

// OatDexFile should be an inner class of OatFile. Unfortunately, C++ doesn't
// support forward declarations of inner classes, and we want to
// forward-declare OatDexFile so that we can store an opaque pointer to an
// OatDexFile in DexFile.
class OatDexFile final {
 public:
  // Opens the DexFile referred to by this OatDexFile from within the containing OatFile.
  std::unique_ptr<const DexFile> OpenDexFile(std::string* error_msg) const;

  // May return null if the OatDexFile only contains a type lookup table. This case only happens
  // for the compiler to speed up compilation, or in jitzygote.
  const OatFile* GetOatFile() const {
    // Avoid pulling in runtime.h in the header file.
    if (kIsDebugBuild && oat_file_ == nullptr) {
      if (!Runtime::Current()->IsUsingApexBootImageLocation()) {
        AssertAotCompiler();
      }
    }
    return oat_file_;
  }

  // Returns the size of the DexFile refered to by this OatDexFile.
  size_t FileSize() const;

  // Returns original path of DexFile that was the source of this OatDexFile.
  const std::string& GetDexFileLocation() const {
    return dex_file_location_;
  }

  // Returns the canonical location of DexFile that was the source of this OatDexFile.
  const std::string& GetCanonicalDexFileLocation() const {
    return canonical_dex_file_location_;
  }

  // Returns checksum of original DexFile that was the source of this OatDexFile;
  uint32_t GetDexFileLocationChecksum() const {
    return dex_file_location_checksum_;
  }

  // Returns the OatClass for the class specified by the given DexFile class_def_index.
  OatFile::OatClass GetOatClass(uint16_t class_def_index) const;

  // Returns the offset to the OatClass information. Most callers should use GetOatClass.
  uint32_t GetOatClassOffset(uint16_t class_def_index) const;

  const uint8_t* GetLookupTableData() const {
    return lookup_table_data_;
  }

  const IndexBssMapping* GetMethodBssMapping() const {
    return method_bss_mapping_;
  }

  const IndexBssMapping* GetTypeBssMapping() const {
    return type_bss_mapping_;
  }

  const IndexBssMapping* GetStringBssMapping() const {
    return string_bss_mapping_;
  }

  const uint8_t* GetDexFilePointer() const {
    return dex_file_pointer_;
  }

  ArrayRef<const uint8_t> GetQuickenedInfoOf(const DexFile& dex_file,
                                             uint32_t dex_method_idx) const;

  // Looks up a class definition by its class descriptor. Hash must be
  // ComputeModifiedUtf8Hash(descriptor).
  static const dex::ClassDef* FindClassDef(const DexFile& dex_file,
                                           const char* descriptor,
                                           size_t hash);

  // Madvise the dex file based on the state we are moving to.
  static void MadviseDexFile(const DexFile& dex_file, MadviseState state);

  const TypeLookupTable& GetTypeLookupTable() const {
    return lookup_table_;
  }

  ~OatDexFile();

  // Create only with a type lookup table, used by the compiler to speed up compilation.
  explicit OatDexFile(TypeLookupTable&& lookup_table);

  // Return the dex layout sections.
  const DexLayoutSections* GetDexLayoutSections() const {
    return dex_layout_sections_;
  }

 private:
  OatDexFile(const OatFile* oat_file,
             const std::string& dex_file_location,
             const std::string& canonical_dex_file_location,
             uint32_t dex_file_checksum,
             const uint8_t* dex_file_pointer,
             const uint8_t* lookup_table_data,
             const IndexBssMapping* method_bss_mapping,
             const IndexBssMapping* type_bss_mapping,
             const IndexBssMapping* string_bss_mapping,
             const uint32_t* oat_class_offsets_pointer,
             const DexLayoutSections* dex_layout_sections);

  // Create an OatDexFile wrapping an existing DexFile. Will set the OatDexFile
  // pointer in the DexFile.
  OatDexFile(const OatFile* oat_file,
             const DexFile* dex_file,
             const std::string& dex_file_location,
             const std::string& canonical_dex_file_location);

  bool IsBackedByVdexOnly() const;

  static void AssertAotCompiler();

  const OatFile* const oat_file_ = nullptr;
  const std::string dex_file_location_;
  const std::string canonical_dex_file_location_;
  const uint32_t dex_file_location_checksum_ = 0u;
  const uint8_t* const dex_file_pointer_ = nullptr;
  const uint8_t* const lookup_table_data_ = nullptr;
  const IndexBssMapping* const method_bss_mapping_ = nullptr;
  const IndexBssMapping* const type_bss_mapping_ = nullptr;
  const IndexBssMapping* const string_bss_mapping_ = nullptr;
  const uint32_t* const oat_class_offsets_pointer_ = nullptr;
  TypeLookupTable lookup_table_;
  const DexLayoutSections* const dex_layout_sections_ = nullptr;

  friend class OatFile;
  friend class OatFileBase;
  DISALLOW_COPY_AND_ASSIGN(OatDexFile);
};

}  // namespace art

#endif  // ART_RUNTIME_OAT_FILE_H_
