Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ART_RUNTIME_VDEX_FILE_H_
     18 #define ART_RUNTIME_VDEX_FILE_H_
     19 
     20 #include <stdint.h>
     21 #include <string>
     22 
     23 #include "base/array_ref.h"
     24 #include "base/macros.h"
     25 #include "mem_map.h"
     26 #include "os.h"
     27 
     28 namespace art {
     29 
     30 class DexFile;
     31 
     32 // VDEX files contain extracted DEX files. The VdexFile class maps the file to
     33 // memory and provides tools for accessing its individual sections.
     34 //
     35 // File format:
     36 //   VdexFile::Header    fixed-length header
     37 //
     38 //   DEX[0]              array of the input DEX files
     39 //   DEX[1]              the bytecode may have been quickened
     40 //   ...
     41 //   DEX[D]
     42 //
     43 
     44 class VdexFile {
     45  public:
     46   struct Header {
     47    public:
     48     Header(uint32_t number_of_dex_files_,
     49            uint32_t dex_size,
     50            uint32_t verifier_deps_size,
     51            uint32_t quickening_info_size);
     52 
     53     const char* GetMagic() const { return reinterpret_cast<const char*>(magic_); }
     54     const char* GetVersion() const { return reinterpret_cast<const char*>(version_); }
     55     bool IsMagicValid() const;
     56     bool IsVersionValid() const;
     57     bool IsValid() const { return IsMagicValid() && IsVersionValid(); }
     58 
     59     uint32_t GetDexSize() const { return dex_size_; }
     60     uint32_t GetVerifierDepsSize() const { return verifier_deps_size_; }
     61     uint32_t GetQuickeningInfoSize() const { return quickening_info_size_; }
     62     uint32_t GetNumberOfDexFiles() const { return number_of_dex_files_; }
     63 
     64     static constexpr uint8_t kVdexInvalidMagic[] = { 'w', 'd', 'e', 'x' };
     65 
     66    private:
     67     static constexpr uint8_t kVdexMagic[] = { 'v', 'd', 'e', 'x' };
     68     // Last update: Disable in-place vdex update
     69     static constexpr uint8_t kVdexVersion[] = { '0', '0', '6', '\0' };
     70 
     71     uint8_t magic_[4];
     72     uint8_t version_[4];
     73     uint32_t number_of_dex_files_;
     74     uint32_t dex_size_;
     75     uint32_t verifier_deps_size_;
     76     uint32_t quickening_info_size_;
     77 
     78     friend class VdexFile;
     79   };
     80 
     81   typedef uint32_t VdexChecksum;
     82 
     83   // Returns nullptr if the vdex file cannot be opened or is not valid.
     84   static std::unique_ptr<VdexFile> Open(const std::string& vdex_filename,
     85                                         bool writable,
     86                                         bool low_4gb,
     87                                         bool unquicken,
     88                                         std::string* error_msg);
     89 
     90   // Returns nullptr if the vdex file cannot be opened or is not valid.
     91   static std::unique_ptr<VdexFile> Open(int file_fd,
     92                                         size_t vdex_length,
     93                                         const std::string& vdex_filename,
     94                                         bool writable,
     95                                         bool low_4gb,
     96                                         bool unquicken,
     97                                         std::string* error_msg);
     98 
     99   const uint8_t* Begin() const { return mmap_->Begin(); }
    100   const uint8_t* End() const { return mmap_->End(); }
    101   size_t Size() const { return mmap_->Size(); }
    102 
    103   const Header& GetHeader() const {
    104     return *reinterpret_cast<const Header*>(Begin());
    105   }
    106 
    107   ArrayRef<const uint8_t> GetVerifierDepsData() const {
    108     return ArrayRef<const uint8_t>(
    109         DexBegin() + GetHeader().GetDexSize(), GetHeader().GetVerifierDepsSize());
    110   }
    111 
    112   ArrayRef<const uint8_t> GetQuickeningInfo() const {
    113     return ArrayRef<const uint8_t>(
    114         GetVerifierDepsData().data() + GetHeader().GetVerifierDepsSize(),
    115         GetHeader().GetQuickeningInfoSize());
    116   }
    117 
    118   bool IsValid() const {
    119     return mmap_->Size() >= sizeof(Header) && GetHeader().IsValid();
    120   }
    121 
    122   // This method is for iterating over the dex files in the vdex. If `cursor` is null,
    123   // the first dex file is returned. If `cursor` is not null, it must point to a dex
    124   // file and this method returns the next dex file if there is one, or null if there
    125   // is none.
    126   const uint8_t* GetNextDexFileData(const uint8_t* cursor) const;
    127 
    128   // Get the location checksum of the dex file number `dex_file_index`.
    129   uint32_t GetLocationChecksum(uint32_t dex_file_index) const {
    130     DCHECK_LT(dex_file_index, GetHeader().GetNumberOfDexFiles());
    131     return reinterpret_cast<const uint32_t*>(Begin() + sizeof(Header))[dex_file_index];
    132   }
    133 
    134   // Opens all the dex files contained in this vdex file.
    135   bool OpenAllDexFiles(std::vector<std::unique_ptr<const DexFile>>* dex_files,
    136                        std::string* error_msg);
    137 
    138   // In-place unquicken the given `dex_files` based on `quickening_info`.
    139   static void Unquicken(const std::vector<const DexFile*>& dex_files,
    140                         const ArrayRef<const uint8_t>& quickening_info);
    141 
    142  private:
    143   explicit VdexFile(MemMap* mmap) : mmap_(mmap) {}
    144 
    145   bool HasDexSection() const {
    146     return GetHeader().GetDexSize() != 0;
    147   }
    148 
    149   const uint8_t* DexBegin() const {
    150     return Begin() + sizeof(Header) + GetSizeOfChecksumsSection();
    151   }
    152 
    153   const uint8_t* DexEnd() const {
    154     return DexBegin() + GetHeader().GetDexSize();
    155   }
    156 
    157   size_t GetSizeOfChecksumsSection() const {
    158     return sizeof(VdexChecksum) * GetHeader().GetNumberOfDexFiles();
    159   }
    160 
    161   std::unique_ptr<MemMap> mmap_;
    162 
    163   DISALLOW_COPY_AND_ASSIGN(VdexFile);
    164 };
    165 
    166 }  // namespace art
    167 
    168 #endif  // ART_RUNTIME_VDEX_FILE_H_
    169