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 //   QuickeningInfo
     43 //     uint8[]                     quickening data
     44 //     unaligned_uint32_t[2][]     table of offsets pair:
     45 //                                    uint32_t[0] contains code_item_offset
     46 //                                    uint32_t[1] contains quickening data offset from the start
     47 //                                                of QuickeningInfo
     48 //     unalgined_uint32_t[D]       start offsets (from the start of QuickeningInfo) in previous
     49 //                                 table for each dex file
     50 
     51 class VdexFile {
     52  public:
     53   struct Header {
     54    public:
     55     Header(uint32_t number_of_dex_files_,
     56            uint32_t dex_size,
     57            uint32_t verifier_deps_size,
     58            uint32_t quickening_info_size);
     59 
     60     const char* GetMagic() const { return reinterpret_cast<const char*>(magic_); }
     61     const char* GetVersion() const { return reinterpret_cast<const char*>(version_); }
     62     bool IsMagicValid() const;
     63     bool IsVersionValid() const;
     64     bool IsValid() const { return IsMagicValid() && IsVersionValid(); }
     65 
     66     uint32_t GetDexSize() const { return dex_size_; }
     67     uint32_t GetVerifierDepsSize() const { return verifier_deps_size_; }
     68     uint32_t GetQuickeningInfoSize() const { return quickening_info_size_; }
     69     uint32_t GetNumberOfDexFiles() const { return number_of_dex_files_; }
     70 
     71     static constexpr uint8_t kVdexInvalidMagic[] = { 'w', 'd', 'e', 'x' };
     72 
     73    private:
     74     static constexpr uint8_t kVdexMagic[] = { 'v', 'd', 'e', 'x' };
     75     // Last update: Use set for unverified_classes_.
     76     static constexpr uint8_t kVdexVersion[] = { '0', '1', '0', '\0' };
     77 
     78     uint8_t magic_[4];
     79     uint8_t version_[4];
     80     uint32_t number_of_dex_files_;
     81     uint32_t dex_size_;
     82     uint32_t verifier_deps_size_;
     83     uint32_t quickening_info_size_;
     84 
     85     friend class VdexFile;
     86   };
     87 
     88   typedef uint32_t VdexChecksum;
     89 
     90   // Returns nullptr if the vdex file cannot be opened or is not valid.
     91   static std::unique_ptr<VdexFile> Open(const std::string& vdex_filename,
     92                                         bool writable,
     93                                         bool low_4gb,
     94                                         bool unquicken,
     95                                         std::string* error_msg);
     96 
     97   // Returns nullptr if the vdex file cannot be opened or is not valid.
     98   static std::unique_ptr<VdexFile> Open(int file_fd,
     99                                         size_t vdex_length,
    100                                         const std::string& vdex_filename,
    101                                         bool writable,
    102                                         bool low_4gb,
    103                                         bool unquicken,
    104                                         std::string* error_msg);
    105 
    106   const uint8_t* Begin() const { return mmap_->Begin(); }
    107   const uint8_t* End() const { return mmap_->End(); }
    108   size_t Size() const { return mmap_->Size(); }
    109 
    110   const Header& GetHeader() const {
    111     return *reinterpret_cast<const Header*>(Begin());
    112   }
    113 
    114   ArrayRef<const uint8_t> GetVerifierDepsData() const {
    115     return ArrayRef<const uint8_t>(
    116         DexBegin() + GetHeader().GetDexSize(), GetHeader().GetVerifierDepsSize());
    117   }
    118 
    119   ArrayRef<const uint8_t> GetQuickeningInfo() const {
    120     return ArrayRef<const uint8_t>(
    121         GetVerifierDepsData().data() + GetHeader().GetVerifierDepsSize(),
    122         GetHeader().GetQuickeningInfoSize());
    123   }
    124 
    125   bool IsValid() const {
    126     return mmap_->Size() >= sizeof(Header) && GetHeader().IsValid();
    127   }
    128 
    129   // This method is for iterating over the dex files in the vdex. If `cursor` is null,
    130   // the first dex file is returned. If `cursor` is not null, it must point to a dex
    131   // file and this method returns the next dex file if there is one, or null if there
    132   // is none.
    133   const uint8_t* GetNextDexFileData(const uint8_t* cursor) const;
    134 
    135   // Get the location checksum of the dex file number `dex_file_index`.
    136   uint32_t GetLocationChecksum(uint32_t dex_file_index) const {
    137     DCHECK_LT(dex_file_index, GetHeader().GetNumberOfDexFiles());
    138     return reinterpret_cast<const uint32_t*>(Begin() + sizeof(Header))[dex_file_index];
    139   }
    140 
    141   // Open all the dex files contained in this vdex file.
    142   bool OpenAllDexFiles(std::vector<std::unique_ptr<const DexFile>>* dex_files,
    143                        std::string* error_msg);
    144 
    145   // In-place unquicken the given `dex_files` based on `quickening_info`.
    146   static void Unquicken(const std::vector<const DexFile*>& dex_files,
    147                         const ArrayRef<const uint8_t>& quickening_info);
    148 
    149   // Fully unquicken `target_dex_file` based on quickening info stored
    150   // in this vdex file for `original_dex_file`.
    151   void FullyUnquickenDexFile(const DexFile& target_dex_file,
    152                              const DexFile& original_dex_file) const;
    153 
    154   // Return the quickening info of the given code item.
    155   const uint8_t* GetQuickenedInfoOf(const DexFile& dex_file, uint32_t code_item_offset) const;
    156 
    157  private:
    158   explicit VdexFile(MemMap* mmap) : mmap_(mmap) {}
    159 
    160   bool HasDexSection() const {
    161     return GetHeader().GetDexSize() != 0;
    162   }
    163 
    164   const uint8_t* DexBegin() const {
    165     return Begin() + sizeof(Header) + GetSizeOfChecksumsSection();
    166   }
    167 
    168   const uint8_t* DexEnd() const {
    169     return DexBegin() + GetHeader().GetDexSize();
    170   }
    171 
    172   size_t GetSizeOfChecksumsSection() const {
    173     return sizeof(VdexChecksum) * GetHeader().GetNumberOfDexFiles();
    174   }
    175 
    176   uint32_t GetDexFileIndex(const DexFile& dex_file) const;
    177 
    178   std::unique_ptr<MemMap> mmap_;
    179 
    180   DISALLOW_COPY_AND_ASSIGN(VdexFile);
    181 };
    182 
    183 }  // namespace art
    184 
    185 #endif  // ART_RUNTIME_VDEX_FILE_H_
    186