Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2011 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 #include "oat_file.h"
     18 
     19 #include <dlfcn.h>
     20 #include <string.h>
     21 #include <type_traits>
     22 #include <unistd.h>
     23 
     24 #include <cstdlib>
     25 #ifndef __APPLE__
     26 #include <link.h>  // for dl_iterate_phdr.
     27 #endif
     28 #include <sstream>
     29 
     30 // dlopen_ext support from bionic.
     31 #ifdef __ANDROID__
     32 #include "android/dlext.h"
     33 #endif
     34 
     35 #include "art_method-inl.h"
     36 #include "base/bit_vector.h"
     37 #include "base/stl_util.h"
     38 #include "base/systrace.h"
     39 #include "base/unix_file/fd_file.h"
     40 #include "elf_file.h"
     41 #include "elf_utils.h"
     42 #include "oat.h"
     43 #include "mem_map.h"
     44 #include "mirror/class.h"
     45 #include "mirror/object-inl.h"
     46 #include "oat_file-inl.h"
     47 #include "oat_file_manager.h"
     48 #include "os.h"
     49 #include "runtime.h"
     50 #include "type_lookup_table.h"
     51 #include "utils.h"
     52 #include "utils/dex_cache_arrays_layout-inl.h"
     53 
     54 namespace art {
     55 
     56 // Whether OatFile::Open will try dlopen. Fallback is our own ELF loader.
     57 static constexpr bool kUseDlopen = true;
     58 
     59 // Whether OatFile::Open will try dlopen on the host. On the host we're not linking against
     60 // bionic, so cannot take advantage of the support for changed semantics (loading the same soname
     61 // multiple times). However, if/when we switch the above, we likely want to switch this, too,
     62 // to get test coverage of the code paths.
     63 static constexpr bool kUseDlopenOnHost = true;
     64 
     65 // For debugging, Open will print DlOpen error message if set to true.
     66 static constexpr bool kPrintDlOpenErrorMessage = false;
     67 
     68 // Note for OatFileBase and descendents:
     69 //
     70 // These are used in OatFile::Open to try all our loaders.
     71 //
     72 // The process is simple:
     73 //
     74 // 1) Allocate an instance through the standard constructor (location, executable)
     75 // 2) Load() to try to open the file.
     76 // 3) ComputeFields() to populate the OatFile fields like begin_, using FindDynamicSymbolAddress.
     77 // 4) PreSetup() for any steps that should be done before the final setup.
     78 // 5) Setup() to complete the procedure.
     79 
     80 class OatFileBase : public OatFile {
     81  public:
     82   virtual ~OatFileBase() {}
     83 
     84   template <typename kOatFileBaseSubType>
     85   static OatFileBase* OpenOatFile(const std::string& elf_filename,
     86                                   const std::string& location,
     87                                   uint8_t* requested_base,
     88                                   uint8_t* oat_file_begin,
     89                                   bool writable,
     90                                   bool executable,
     91                                   bool low_4gb,
     92                                   const char* abs_dex_location,
     93                                   std::string* error_msg);
     94 
     95  protected:
     96   OatFileBase(const std::string& filename, bool executable) : OatFile(filename, executable) {}
     97 
     98   virtual const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
     99                                                   std::string* error_msg) const = 0;
    100 
    101   virtual void PreLoad() = 0;
    102 
    103   virtual bool Load(const std::string& elf_filename,
    104                     uint8_t* oat_file_begin,
    105                     bool writable,
    106                     bool executable,
    107                     bool low_4gb,
    108                     std::string* error_msg) = 0;
    109 
    110   bool ComputeFields(uint8_t* requested_base,
    111                      const std::string& file_path,
    112                      std::string* error_msg);
    113 
    114   virtual void PreSetup(const std::string& elf_filename) = 0;
    115 
    116   bool Setup(const char* abs_dex_location, std::string* error_msg);
    117 
    118   // Setters exposed for ElfOatFile.
    119 
    120   void SetBegin(const uint8_t* begin) {
    121     begin_ = begin;
    122   }
    123 
    124   void SetEnd(const uint8_t* end) {
    125     end_ = end;
    126   }
    127 
    128  private:
    129   DISALLOW_COPY_AND_ASSIGN(OatFileBase);
    130 };
    131 
    132 template <typename kOatFileBaseSubType>
    133 OatFileBase* OatFileBase::OpenOatFile(const std::string& elf_filename,
    134                                       const std::string& location,
    135                                       uint8_t* requested_base,
    136                                       uint8_t* oat_file_begin,
    137                                       bool writable,
    138                                       bool executable,
    139                                       bool low_4gb,
    140                                       const char* abs_dex_location,
    141                                       std::string* error_msg) {
    142   std::unique_ptr<OatFileBase> ret(new kOatFileBaseSubType(location, executable));
    143 
    144   ret->PreLoad();
    145 
    146   if (!ret->Load(elf_filename,
    147                  oat_file_begin,
    148                  writable,
    149                  executable,
    150                  low_4gb,
    151                  error_msg)) {
    152     return nullptr;
    153   }
    154 
    155   if (!ret->ComputeFields(requested_base, elf_filename, error_msg)) {
    156     return nullptr;
    157   }
    158 
    159   ret->PreSetup(elf_filename);
    160 
    161   if (!ret->Setup(abs_dex_location, error_msg)) {
    162     return nullptr;
    163   }
    164 
    165   return ret.release();
    166 }
    167 
    168 bool OatFileBase::ComputeFields(uint8_t* requested_base,
    169                                 const std::string& file_path,
    170                                 std::string* error_msg) {
    171   std::string symbol_error_msg;
    172   begin_ = FindDynamicSymbolAddress("oatdata", &symbol_error_msg);
    173   if (begin_ == nullptr) {
    174     *error_msg = StringPrintf("Failed to find oatdata symbol in '%s' %s",
    175                               file_path.c_str(),
    176                               symbol_error_msg.c_str());
    177     return false;
    178   }
    179   if (requested_base != nullptr && begin_ != requested_base) {
    180     // Host can fail this check. Do not dump there to avoid polluting the output.
    181     if (kIsTargetBuild && (kIsDebugBuild || VLOG_IS_ON(oat))) {
    182       PrintFileToLog("/proc/self/maps", LogSeverity::WARNING);
    183     }
    184     *error_msg = StringPrintf("Failed to find oatdata symbol at expected address: "
    185         "oatdata=%p != expected=%p. See process maps in the log.",
    186         begin_, requested_base);
    187     return false;
    188   }
    189   end_ = FindDynamicSymbolAddress("oatlastword", &symbol_error_msg);
    190   if (end_ == nullptr) {
    191     *error_msg = StringPrintf("Failed to find oatlastword symbol in '%s' %s",
    192                               file_path.c_str(),
    193                               symbol_error_msg.c_str());
    194     return false;
    195   }
    196   // Readjust to be non-inclusive upper bound.
    197   end_ += sizeof(uint32_t);
    198 
    199   bss_begin_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbss", &symbol_error_msg));
    200   if (bss_begin_ == nullptr) {
    201     // No .bss section.
    202     bss_end_ = nullptr;
    203   } else {
    204     bss_end_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbsslastword", &symbol_error_msg));
    205     if (bss_end_ == nullptr) {
    206       *error_msg = StringPrintf("Failed to find oatbasslastword symbol in '%s'", file_path.c_str());
    207       return false;
    208     }
    209     // Readjust to be non-inclusive upper bound.
    210     bss_end_ += sizeof(uint32_t);
    211   }
    212 
    213   return true;
    214 }
    215 
    216 // Read an unaligned entry from the OatDexFile data in OatFile and advance the read
    217 // position by the number of bytes read, i.e. sizeof(T).
    218 // Return true on success, false if the read would go beyond the end of the OatFile.
    219 template <typename T>
    220 inline static bool ReadOatDexFileData(const OatFile& oat_file,
    221                                       /*inout*/const uint8_t** oat,
    222                                       /*out*/T* value) {
    223   DCHECK(oat != nullptr);
    224   DCHECK(value != nullptr);
    225   DCHECK_LE(*oat, oat_file.End());
    226   if (UNLIKELY(static_cast<size_t>(oat_file.End() - *oat) < sizeof(T))) {
    227     return false;
    228   }
    229   static_assert(std::is_trivial<T>::value, "T must be a trivial type");
    230   typedef __attribute__((__aligned__(1))) T unaligned_type;
    231   *value = *reinterpret_cast<const unaligned_type*>(*oat);
    232   *oat += sizeof(T);
    233   return true;
    234 }
    235 
    236 bool OatFileBase::Setup(const char* abs_dex_location, std::string* error_msg) {
    237   if (!GetOatHeader().IsValid()) {
    238     std::string cause = GetOatHeader().GetValidationErrorMessage();
    239     *error_msg = StringPrintf("Invalid oat header for '%s': %s",
    240                               GetLocation().c_str(),
    241                               cause.c_str());
    242     return false;
    243   }
    244   const uint8_t* oat = Begin();
    245   oat += sizeof(OatHeader);
    246   if (oat > End()) {
    247     *error_msg = StringPrintf("In oat file '%s' found truncated OatHeader", GetLocation().c_str());
    248     return false;
    249   }
    250 
    251   oat += GetOatHeader().GetKeyValueStoreSize();
    252   if (oat > End()) {
    253     *error_msg = StringPrintf("In oat file '%s' found truncated variable-size data: "
    254                                   "%p + %zu + %u <= %p",
    255                               GetLocation().c_str(),
    256                               Begin(),
    257                               sizeof(OatHeader),
    258                               GetOatHeader().GetKeyValueStoreSize(),
    259                               End());
    260     return false;
    261   }
    262 
    263   size_t pointer_size = GetInstructionSetPointerSize(GetOatHeader().GetInstructionSet());
    264   uint8_t* dex_cache_arrays = bss_begin_;
    265   uint32_t dex_file_count = GetOatHeader().GetDexFileCount();
    266   oat_dex_files_storage_.reserve(dex_file_count);
    267   for (size_t i = 0; i < dex_file_count; i++) {
    268     uint32_t dex_file_location_size;
    269     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_location_size))) {
    270       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu truncated after dex file "
    271                                     "location size",
    272                                 GetLocation().c_str(),
    273                                 i);
    274       return false;
    275     }
    276     if (UNLIKELY(dex_file_location_size == 0U)) {
    277       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with empty location name",
    278                                 GetLocation().c_str(),
    279                                 i);
    280       return false;
    281     }
    282     if (UNLIKELY(static_cast<size_t>(End() - oat) < dex_file_location_size)) {
    283       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with truncated dex file "
    284                                     "location",
    285                                 GetLocation().c_str(),
    286                                 i);
    287       return false;
    288     }
    289     const char* dex_file_location_data = reinterpret_cast<const char*>(oat);
    290     oat += dex_file_location_size;
    291 
    292     std::string dex_file_location = ResolveRelativeEncodedDexLocation(
    293         abs_dex_location,
    294         std::string(dex_file_location_data, dex_file_location_size));
    295 
    296     uint32_t dex_file_checksum;
    297     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_checksum))) {
    298       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated after "
    299                                     "dex file checksum",
    300                                 GetLocation().c_str(),
    301                                 i,
    302                                 dex_file_location.c_str());
    303       return false;
    304     }
    305 
    306     uint32_t dex_file_offset;
    307     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_offset))) {
    308       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated "
    309                                     "after dex file offsets",
    310                                 GetLocation().c_str(),
    311                                 i,
    312                                 dex_file_location.c_str());
    313       return false;
    314     }
    315     if (UNLIKELY(dex_file_offset == 0U)) {
    316       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with zero dex "
    317                                     "file offset",
    318                                 GetLocation().c_str(),
    319                                 i,
    320                                 dex_file_location.c_str());
    321       return false;
    322     }
    323     if (UNLIKELY(dex_file_offset > Size())) {
    324       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
    325                                     "offset %u > %zu",
    326                                 GetLocation().c_str(),
    327                                 i,
    328                                 dex_file_location.c_str(),
    329                                 dex_file_offset,
    330                                 Size());
    331       return false;
    332     }
    333     if (UNLIKELY(Size() - dex_file_offset < sizeof(DexFile::Header))) {
    334       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
    335                                     "offset %u of %zu but the size of dex file header is %zu",
    336                                 GetLocation().c_str(),
    337                                 i,
    338                                 dex_file_location.c_str(),
    339                                 dex_file_offset,
    340                                 Size(),
    341                                 sizeof(DexFile::Header));
    342       return false;
    343     }
    344 
    345     const uint8_t* dex_file_pointer = Begin() + dex_file_offset;
    346     if (UNLIKELY(!DexFile::IsMagicValid(dex_file_pointer))) {
    347       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
    348                                     "dex file magic '%s'",
    349                                 GetLocation().c_str(),
    350                                 i,
    351                                 dex_file_location.c_str(),
    352                                 dex_file_pointer);
    353       return false;
    354     }
    355     if (UNLIKELY(!DexFile::IsVersionValid(dex_file_pointer))) {
    356       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
    357                                     "dex file version '%s'",
    358                                 GetLocation().c_str(),
    359                                 i,
    360                                 dex_file_location.c_str(),
    361                                 dex_file_pointer);
    362       return false;
    363     }
    364     const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer);
    365     if (Size() - dex_file_offset < header->file_size_) {
    366       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
    367                                     "offset %u and size %u truncated at %zu",
    368                                 GetLocation().c_str(),
    369                                 i,
    370                                 dex_file_location.c_str(),
    371                                 dex_file_offset,
    372                                 header->file_size_,
    373                                 Size());
    374       return false;
    375     }
    376 
    377     uint32_t class_offsets_offset;
    378     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &class_offsets_offset))) {
    379       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated "
    380                                     "after class offsets offset",
    381                                 GetLocation().c_str(),
    382                                 i,
    383                                 dex_file_location.c_str());
    384       return false;
    385     }
    386     if (UNLIKELY(class_offsets_offset > Size()) ||
    387         UNLIKELY((Size() - class_offsets_offset) / sizeof(uint32_t) < header->class_defs_size_)) {
    388       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated "
    389                                     "class offsets, offset %u of %zu, class defs %u",
    390                                 GetLocation().c_str(),
    391                                 i,
    392                                 dex_file_location.c_str(),
    393                                 class_offsets_offset,
    394                                 Size(),
    395                                 header->class_defs_size_);
    396       return false;
    397     }
    398     if (UNLIKELY(!IsAligned<alignof(uint32_t)>(class_offsets_offset))) {
    399       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with unaligned "
    400                                     "class offsets, offset %u",
    401                                 GetLocation().c_str(),
    402                                 i,
    403                                 dex_file_location.c_str(),
    404                                 class_offsets_offset);
    405       return false;
    406     }
    407     const uint32_t* class_offsets_pointer =
    408         reinterpret_cast<const uint32_t*>(Begin() + class_offsets_offset);
    409 
    410     uint32_t lookup_table_offset;
    411     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &lookup_table_offset))) {
    412       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
    413                                     "after lookup table offset",
    414                                 GetLocation().c_str(),
    415                                 i,
    416                                 dex_file_location.c_str());
    417       return false;
    418     }
    419     const uint8_t* lookup_table_data = lookup_table_offset != 0u
    420         ? Begin() + lookup_table_offset
    421         : nullptr;
    422     if (lookup_table_offset != 0u &&
    423         (UNLIKELY(lookup_table_offset > Size()) ||
    424             UNLIKELY(Size() - lookup_table_offset <
    425                      TypeLookupTable::RawDataLength(header->class_defs_size_)))) {
    426       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated "
    427                                     "type lookup table, offset %u of %zu, class defs %u",
    428                                 GetLocation().c_str(),
    429                                 i,
    430                                 dex_file_location.c_str(),
    431                                 lookup_table_offset,
    432                                 Size(),
    433                                 header->class_defs_size_);
    434       return false;
    435     }
    436 
    437     uint8_t* current_dex_cache_arrays = nullptr;
    438     if (dex_cache_arrays != nullptr) {
    439       DexCacheArraysLayout layout(pointer_size, *header);
    440       if (layout.Size() != 0u) {
    441         if (static_cast<size_t>(bss_end_ - dex_cache_arrays) < layout.Size()) {
    442           *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with "
    443                                         "truncated dex cache arrays, %zu < %zu.",
    444                                     GetLocation().c_str(),
    445                                     i,
    446                                     dex_file_location.c_str(),
    447                                     static_cast<size_t>(bss_end_ - dex_cache_arrays),
    448                                     layout.Size());
    449           return false;
    450         }
    451         current_dex_cache_arrays = dex_cache_arrays;
    452         dex_cache_arrays += layout.Size();
    453       }
    454     }
    455 
    456     std::string canonical_location = DexFile::GetDexCanonicalLocation(dex_file_location.c_str());
    457 
    458     // Create the OatDexFile and add it to the owning container.
    459     OatDexFile* oat_dex_file = new OatDexFile(this,
    460                                               dex_file_location,
    461                                               canonical_location,
    462                                               dex_file_checksum,
    463                                               dex_file_pointer,
    464                                               lookup_table_data,
    465                                               class_offsets_pointer,
    466                                               current_dex_cache_arrays);
    467     oat_dex_files_storage_.push_back(oat_dex_file);
    468 
    469     // Add the location and canonical location (if different) to the oat_dex_files_ table.
    470     StringPiece key(oat_dex_file->GetDexFileLocation());
    471     oat_dex_files_.Put(key, oat_dex_file);
    472     if (canonical_location != dex_file_location) {
    473       StringPiece canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
    474       oat_dex_files_.Put(canonical_key, oat_dex_file);
    475     }
    476   }
    477 
    478   if (dex_cache_arrays != bss_end_) {
    479     // We expect the bss section to be either empty (dex_cache_arrays and bss_end_
    480     // both null) or contain just the dex cache arrays and nothing else.
    481     *error_msg = StringPrintf("In oat file '%s' found unexpected bss size bigger by %zu bytes.",
    482                               GetLocation().c_str(),
    483                               static_cast<size_t>(bss_end_ - dex_cache_arrays));
    484     return false;
    485   }
    486   return true;
    487 }
    488 
    489 ////////////////////////
    490 // OatFile via dlopen //
    491 ////////////////////////
    492 
    493 class DlOpenOatFile FINAL : public OatFileBase {
    494  public:
    495   DlOpenOatFile(const std::string& filename, bool executable)
    496       : OatFileBase(filename, executable),
    497         dlopen_handle_(nullptr),
    498         shared_objects_before_(0) {
    499   }
    500 
    501   ~DlOpenOatFile() {
    502     if (dlopen_handle_ != nullptr) {
    503       if (!kIsTargetBuild) {
    504         MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
    505         host_dlopen_handles_.erase(dlopen_handle_);
    506         dlclose(dlopen_handle_);
    507       } else {
    508         dlclose(dlopen_handle_);
    509       }
    510     }
    511   }
    512 
    513  protected:
    514   const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
    515                                           std::string* error_msg) const OVERRIDE {
    516     const uint8_t* ptr =
    517         reinterpret_cast<const uint8_t*>(dlsym(dlopen_handle_, symbol_name.c_str()));
    518     if (ptr == nullptr) {
    519       *error_msg = dlerror();
    520     }
    521     return ptr;
    522   }
    523 
    524   void PreLoad() OVERRIDE;
    525 
    526   bool Load(const std::string& elf_filename,
    527             uint8_t* oat_file_begin,
    528             bool writable,
    529             bool executable,
    530             bool low_4gb,
    531             std::string* error_msg) OVERRIDE;
    532 
    533   // Ask the linker where it mmaped the file and notify our mmap wrapper of the regions.
    534   void PreSetup(const std::string& elf_filename) OVERRIDE;
    535 
    536  private:
    537   bool Dlopen(const std::string& elf_filename,
    538               uint8_t* oat_file_begin,
    539               std::string* error_msg);
    540 
    541   // On the host, if the same library is loaded again with dlopen the same
    542   // file handle is returned. This differs from the behavior of dlopen on the
    543   // target, where dlopen reloads the library at a different address every
    544   // time you load it. The runtime relies on the target behavior to ensure
    545   // each instance of the loaded library has a unique dex cache. To avoid
    546   // problems, we fall back to our own linker in the case when the same
    547   // library is opened multiple times on host. dlopen_handles_ is used to
    548   // detect that case.
    549   // Guarded by host_dlopen_handles_lock_;
    550   static std::unordered_set<void*> host_dlopen_handles_;
    551 
    552   // dlopen handle during runtime.
    553   void* dlopen_handle_;  // TODO: Unique_ptr with custom deleter.
    554 
    555   // Dummy memory map objects corresponding to the regions mapped by dlopen.
    556   std::vector<std::unique_ptr<MemMap>> dlopen_mmaps_;
    557 
    558   // The number of shared objects the linker told us about before loading. Used to
    559   // (optimistically) optimize the PreSetup stage (see comment there).
    560   size_t shared_objects_before_;
    561 
    562   DISALLOW_COPY_AND_ASSIGN(DlOpenOatFile);
    563 };
    564 
    565 std::unordered_set<void*> DlOpenOatFile::host_dlopen_handles_;
    566 
    567 void DlOpenOatFile::PreLoad() {
    568 #ifdef __APPLE__
    569   UNUSED(shared_objects_before_);
    570   LOG(FATAL) << "Should not reach here.";
    571   UNREACHABLE();
    572 #else
    573   // Count the entries in dl_iterate_phdr we get at this point in time.
    574   struct dl_iterate_context {
    575     static int callback(struct dl_phdr_info *info ATTRIBUTE_UNUSED,
    576                         size_t size ATTRIBUTE_UNUSED,
    577                         void *data) {
    578       reinterpret_cast<dl_iterate_context*>(data)->count++;
    579       return 0;  // Continue iteration.
    580     }
    581     size_t count = 0;
    582   } context;
    583 
    584   dl_iterate_phdr(dl_iterate_context::callback, &context);
    585   shared_objects_before_ = context.count;
    586 #endif
    587 }
    588 
    589 bool DlOpenOatFile::Load(const std::string& elf_filename,
    590                          uint8_t* oat_file_begin,
    591                          bool writable,
    592                          bool executable,
    593                          bool low_4gb,
    594                          std::string* error_msg) {
    595   // Use dlopen only when flagged to do so, and when it's OK to load things executable.
    596   // TODO: Also try when not executable? The issue here could be re-mapping as writable (as
    597   //       !executable is a sign that we may want to patch), which may not be allowed for
    598   //       various reasons.
    599   if (!kUseDlopen) {
    600     *error_msg = "DlOpen is disabled.";
    601     return false;
    602   }
    603   if (low_4gb) {
    604     *error_msg = "DlOpen does not support low 4gb loading.";
    605     return false;
    606   }
    607   if (writable) {
    608     *error_msg = "DlOpen does not support writable loading.";
    609     return false;
    610   }
    611   if (!executable) {
    612     *error_msg = "DlOpen does not support non-executable loading.";
    613     return false;
    614   }
    615 
    616   // dlopen always returns the same library if it is already opened on the host. For this reason
    617   // we only use dlopen if we are the target or we do not already have the dex file opened. Having
    618   // the same library loaded multiple times at different addresses is required for class unloading
    619   // and for having dex caches arrays in the .bss section.
    620   if (!kIsTargetBuild) {
    621     if (!kUseDlopenOnHost) {
    622       *error_msg = "DlOpen disabled for host.";
    623       return false;
    624     }
    625   }
    626 
    627   bool success = Dlopen(elf_filename, oat_file_begin, error_msg);
    628   DCHECK(dlopen_handle_ != nullptr || !success);
    629 
    630   return success;
    631 }
    632 
    633 bool DlOpenOatFile::Dlopen(const std::string& elf_filename,
    634                            uint8_t* oat_file_begin,
    635                            std::string* error_msg) {
    636 #ifdef __APPLE__
    637   // The dl_iterate_phdr syscall is missing.  There is similar API on OSX,
    638   // but let's fallback to the custom loading code for the time being.
    639   UNUSED(elf_filename, oat_file_begin);
    640   *error_msg = "Dlopen unsupported on Mac.";
    641   return false;
    642 #else
    643   {
    644     UniqueCPtr<char> absolute_path(realpath(elf_filename.c_str(), nullptr));
    645     if (absolute_path == nullptr) {
    646       *error_msg = StringPrintf("Failed to find absolute path for '%s'", elf_filename.c_str());
    647       return false;
    648     }
    649 #ifdef __ANDROID__
    650     android_dlextinfo extinfo;
    651     extinfo.flags = ANDROID_DLEXT_FORCE_LOAD |                  // Force-load, don't reuse handle
    652                                                                 //   (open oat files multiple
    653                                                                 //    times).
    654                     ANDROID_DLEXT_FORCE_FIXED_VADDR;            // Take a non-zero vaddr as absolute
    655                                                                 //   (non-pic boot image).
    656     if (oat_file_begin != nullptr) {                            //
    657       extinfo.flags |= ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS;     // Use the requested addr if
    658       extinfo.reserved_addr = oat_file_begin;                   // vaddr = 0.
    659     }                                                           //   (pic boot image).
    660     dlopen_handle_ = android_dlopen_ext(absolute_path.get(), RTLD_NOW, &extinfo);
    661 #else
    662     UNUSED(oat_file_begin);
    663     static_assert(!kIsTargetBuild, "host_dlopen_handles_ will leak handles");
    664     MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
    665     dlopen_handle_ = dlopen(absolute_path.get(), RTLD_NOW);
    666     if (dlopen_handle_ != nullptr) {
    667       if (!host_dlopen_handles_.insert(dlopen_handle_).second) {
    668         dlclose(dlopen_handle_);
    669         dlopen_handle_ = nullptr;
    670         *error_msg = StringPrintf("host dlopen re-opened '%s'", elf_filename.c_str());
    671         return false;
    672       }
    673     }
    674 #endif
    675   }
    676   if (dlopen_handle_ == nullptr) {
    677     *error_msg = StringPrintf("Failed to dlopen '%s': %s", elf_filename.c_str(), dlerror());
    678     return false;
    679   }
    680   return true;
    681 #endif
    682 }
    683 
    684 void DlOpenOatFile::PreSetup(const std::string& elf_filename) {
    685 #ifdef __APPLE__
    686   UNUSED(elf_filename);
    687   LOG(FATAL) << "Should not reach here.";
    688   UNREACHABLE();
    689 #else
    690   struct dl_iterate_context {
    691     static int callback(struct dl_phdr_info *info, size_t /* size */, void *data) {
    692       auto* context = reinterpret_cast<dl_iterate_context*>(data);
    693       context->shared_objects_seen++;
    694       if (context->shared_objects_seen < context->shared_objects_before) {
    695         // We haven't been called yet for anything we haven't seen before. Just continue.
    696         // Note: this is aggressively optimistic. If another thread was unloading a library,
    697         //       we may miss out here. However, this does not happen often in practice.
    698         return 0;
    699       }
    700 
    701       // See whether this callback corresponds to the file which we have just loaded.
    702       bool contains_begin = false;
    703       for (int i = 0; i < info->dlpi_phnum; i++) {
    704         if (info->dlpi_phdr[i].p_type == PT_LOAD) {
    705           uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
    706               info->dlpi_phdr[i].p_vaddr);
    707           size_t memsz = info->dlpi_phdr[i].p_memsz;
    708           if (vaddr <= context->begin_ && context->begin_ < vaddr + memsz) {
    709             contains_begin = true;
    710             break;
    711           }
    712         }
    713       }
    714       // Add dummy mmaps for this file.
    715       if (contains_begin) {
    716         for (int i = 0; i < info->dlpi_phnum; i++) {
    717           if (info->dlpi_phdr[i].p_type == PT_LOAD) {
    718             uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
    719                 info->dlpi_phdr[i].p_vaddr);
    720             size_t memsz = info->dlpi_phdr[i].p_memsz;
    721             MemMap* mmap = MemMap::MapDummy(info->dlpi_name, vaddr, memsz);
    722             context->dlopen_mmaps_->push_back(std::unique_ptr<MemMap>(mmap));
    723           }
    724         }
    725         return 1;  // Stop iteration and return 1 from dl_iterate_phdr.
    726       }
    727       return 0;  // Continue iteration and return 0 from dl_iterate_phdr when finished.
    728     }
    729     const uint8_t* const begin_;
    730     std::vector<std::unique_ptr<MemMap>>* const dlopen_mmaps_;
    731     const size_t shared_objects_before;
    732     size_t shared_objects_seen;
    733   };
    734   dl_iterate_context context = { Begin(), &dlopen_mmaps_, shared_objects_before_, 0};
    735 
    736   if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
    737     // Hm. Maybe our optimization went wrong. Try another time with shared_objects_before == 0
    738     // before giving up. This should be unusual.
    739     VLOG(oat) << "Need a second run in PreSetup, didn't find with shared_objects_before="
    740               << shared_objects_before_;
    741     dl_iterate_context context0 = { Begin(), &dlopen_mmaps_, 0, 0};
    742     if (dl_iterate_phdr(dl_iterate_context::callback, &context0) == 0) {
    743       // OK, give up and print an error.
    744       PrintFileToLog("/proc/self/maps", LogSeverity::WARNING);
    745       LOG(ERROR) << "File " << elf_filename << " loaded with dlopen but cannot find its mmaps.";
    746     }
    747   }
    748 #endif
    749 }
    750 
    751 ////////////////////////////////////////////////
    752 // OatFile via our own ElfFile implementation //
    753 ////////////////////////////////////////////////
    754 
    755 class ElfOatFile FINAL : public OatFileBase {
    756  public:
    757   ElfOatFile(const std::string& filename, bool executable) : OatFileBase(filename, executable) {}
    758 
    759   static ElfOatFile* OpenElfFile(File* file,
    760                                  const std::string& location,
    761                                  uint8_t* requested_base,
    762                                  uint8_t* oat_file_begin,  // Override base if not null
    763                                  bool writable,
    764                                  bool executable,
    765                                  bool low_4gb,
    766                                  const char* abs_dex_location,
    767                                  std::string* error_msg);
    768 
    769   bool InitializeFromElfFile(ElfFile* elf_file,
    770                              const char* abs_dex_location,
    771                              std::string* error_msg);
    772 
    773  protected:
    774   const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
    775                                           std::string* error_msg) const OVERRIDE {
    776     const uint8_t* ptr = elf_file_->FindDynamicSymbolAddress(symbol_name);
    777     if (ptr == nullptr) {
    778       *error_msg = "(Internal implementation could not find symbol)";
    779     }
    780     return ptr;
    781   }
    782 
    783   void PreLoad() OVERRIDE {
    784   }
    785 
    786   bool Load(const std::string& elf_filename,
    787             uint8_t* oat_file_begin,  // Override where the file is loaded to if not null
    788             bool writable,
    789             bool executable,
    790             bool low_4gb,
    791             std::string* error_msg) OVERRIDE;
    792 
    793   void PreSetup(const std::string& elf_filename ATTRIBUTE_UNUSED) OVERRIDE {
    794   }
    795 
    796  private:
    797   bool ElfFileOpen(File* file,
    798                    uint8_t* oat_file_begin,  // Override where the file is loaded to if not null
    799                    bool writable,
    800                    bool executable,
    801                    bool low_4gb,
    802                    std::string* error_msg);
    803 
    804  private:
    805   // Backing memory map for oat file during cross compilation.
    806   std::unique_ptr<ElfFile> elf_file_;
    807 
    808   DISALLOW_COPY_AND_ASSIGN(ElfOatFile);
    809 };
    810 
    811 ElfOatFile* ElfOatFile::OpenElfFile(File* file,
    812                                     const std::string& location,
    813                                     uint8_t* requested_base,
    814                                     uint8_t* oat_file_begin,  // Override base if not null
    815                                     bool writable,
    816                                     bool executable,
    817                                     bool low_4gb,
    818                                     const char* abs_dex_location,
    819                                     std::string* error_msg) {
    820   ScopedTrace trace("Open elf file " + location);
    821   std::unique_ptr<ElfOatFile> oat_file(new ElfOatFile(location, executable));
    822   bool success = oat_file->ElfFileOpen(file,
    823                                        oat_file_begin,
    824                                        writable,
    825                                        low_4gb,
    826                                        executable,
    827                                        error_msg);
    828   if (!success) {
    829     CHECK(!error_msg->empty());
    830     return nullptr;
    831   }
    832 
    833   // Complete the setup.
    834   if (!oat_file->ComputeFields(requested_base, file->GetPath(), error_msg)) {
    835     return nullptr;
    836   }
    837 
    838   if (!oat_file->Setup(abs_dex_location, error_msg)) {
    839     return nullptr;
    840   }
    841 
    842   return oat_file.release();
    843 }
    844 
    845 bool ElfOatFile::InitializeFromElfFile(ElfFile* elf_file,
    846                                        const char* abs_dex_location,
    847                                        std::string* error_msg) {
    848   ScopedTrace trace(__PRETTY_FUNCTION__);
    849   if (IsExecutable()) {
    850     *error_msg = "Cannot initialize from elf file in executable mode.";
    851     return false;
    852   }
    853   elf_file_.reset(elf_file);
    854   uint64_t offset, size;
    855   bool has_section = elf_file->GetSectionOffsetAndSize(".rodata", &offset, &size);
    856   CHECK(has_section);
    857   SetBegin(elf_file->Begin() + offset);
    858   SetEnd(elf_file->Begin() + size + offset);
    859   // Ignore the optional .bss section when opening non-executable.
    860   return Setup(abs_dex_location, error_msg);
    861 }
    862 
    863 bool ElfOatFile::Load(const std::string& elf_filename,
    864                       uint8_t* oat_file_begin,  // Override where the file is loaded to if not null
    865                       bool writable,
    866                       bool executable,
    867                       bool low_4gb,
    868                       std::string* error_msg) {
    869   ScopedTrace trace(__PRETTY_FUNCTION__);
    870   std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str()));
    871   if (file == nullptr) {
    872     *error_msg = StringPrintf("Failed to open oat filename for reading: %s", strerror(errno));
    873     return false;
    874   }
    875   return ElfOatFile::ElfFileOpen(file.get(),
    876                                  oat_file_begin,
    877                                  writable,
    878                                  executable,
    879                                  low_4gb,
    880                                  error_msg);
    881 }
    882 
    883 bool ElfOatFile::ElfFileOpen(File* file,
    884                              uint8_t* oat_file_begin,
    885                              bool writable,
    886                              bool executable,
    887                              bool low_4gb,
    888                              std::string* error_msg) {
    889   ScopedTrace trace(__PRETTY_FUNCTION__);
    890   // TODO: rename requested_base to oat_data_begin
    891   elf_file_.reset(ElfFile::Open(file,
    892                                 writable,
    893                                 /*program_header_only*/true,
    894                                 low_4gb,
    895                                 error_msg,
    896                                 oat_file_begin));
    897   if (elf_file_ == nullptr) {
    898     DCHECK(!error_msg->empty());
    899     return false;
    900   }
    901   bool loaded = elf_file_->Load(executable, low_4gb, error_msg);
    902   DCHECK(loaded || !error_msg->empty());
    903   return loaded;
    904 }
    905 
    906 //////////////////////////
    907 // General OatFile code //
    908 //////////////////////////
    909 
    910 std::string OatFile::ResolveRelativeEncodedDexLocation(
    911       const char* abs_dex_location, const std::string& rel_dex_location) {
    912   if (abs_dex_location != nullptr && rel_dex_location[0] != '/') {
    913     // Strip :classes<N>.dex used for secondary multidex files.
    914     std::string base = DexFile::GetBaseLocation(rel_dex_location);
    915     std::string multidex_suffix = DexFile::GetMultiDexSuffix(rel_dex_location);
    916 
    917     // Check if the base is a suffix of the provided abs_dex_location.
    918     std::string target_suffix = "/" + base;
    919     std::string abs_location(abs_dex_location);
    920     if (abs_location.size() > target_suffix.size()) {
    921       size_t pos = abs_location.size() - target_suffix.size();
    922       if (abs_location.compare(pos, std::string::npos, target_suffix) == 0) {
    923         return abs_location + multidex_suffix;
    924       }
    925     }
    926   }
    927   return rel_dex_location;
    928 }
    929 
    930 static void CheckLocation(const std::string& location) {
    931   CHECK(!location.empty());
    932 }
    933 
    934 OatFile* OatFile::OpenWithElfFile(ElfFile* elf_file,
    935                                   const std::string& location,
    936                                   const char* abs_dex_location,
    937                                   std::string* error_msg) {
    938   std::unique_ptr<ElfOatFile> oat_file(new ElfOatFile(location, false /* executable */));
    939   return oat_file->InitializeFromElfFile(elf_file, abs_dex_location, error_msg)
    940       ? oat_file.release()
    941       : nullptr;
    942 }
    943 
    944 OatFile* OatFile::Open(const std::string& filename,
    945                        const std::string& location,
    946                        uint8_t* requested_base,
    947                        uint8_t* oat_file_begin,
    948                        bool executable,
    949                        bool low_4gb,
    950                        const char* abs_dex_location,
    951                        std::string* error_msg) {
    952   ScopedTrace trace("Open oat file " + location);
    953   CHECK(!filename.empty()) << location;
    954   CheckLocation(location);
    955 
    956   // Check that the file even exists, fast-fail.
    957   if (!OS::FileExists(filename.c_str())) {
    958     *error_msg = StringPrintf("File %s does not exist.", filename.c_str());
    959     return nullptr;
    960   }
    961 
    962   // Try dlopen first, as it is required for native debuggability. This will fail fast if dlopen is
    963   // disabled.
    964   OatFile* with_dlopen = OatFileBase::OpenOatFile<DlOpenOatFile>(filename,
    965                                                                  location,
    966                                                                  requested_base,
    967                                                                  oat_file_begin,
    968                                                                  false,
    969                                                                  executable,
    970                                                                  low_4gb,
    971                                                                  abs_dex_location,
    972                                                                  error_msg);
    973   if (with_dlopen != nullptr) {
    974     return with_dlopen;
    975   }
    976   if (kPrintDlOpenErrorMessage) {
    977     LOG(ERROR) << "Failed to dlopen: " << filename << " with error " << *error_msg;
    978   }
    979   // If we aren't trying to execute, we just use our own ElfFile loader for a couple reasons:
    980   //
    981   // On target, dlopen may fail when compiling due to selinux restrictions on installd.
    982   //
    983   // We use our own ELF loader for Quick to deal with legacy apps that
    984   // open a generated dex file by name, remove the file, then open
    985   // another generated dex file with the same name. http://b/10614658
    986   //
    987   // On host, dlopen is expected to fail when cross compiling, so fall back to OpenElfFile.
    988   //
    989   //
    990   // Another independent reason is the absolute placement of boot.oat. dlopen on the host usually
    991   // does honor the virtual address encoded in the ELF file only for ET_EXEC files, not ET_DYN.
    992   OatFile* with_internal = OatFileBase::OpenOatFile<ElfOatFile>(filename,
    993                                                                 location,
    994                                                                 requested_base,
    995                                                                 oat_file_begin,
    996                                                                 false,
    997                                                                 executable,
    998                                                                 low_4gb,
    999                                                                 abs_dex_location,
   1000                                                                 error_msg);
   1001   return with_internal;
   1002 }
   1003 
   1004 OatFile* OatFile::OpenWritable(File* file,
   1005                                const std::string& location,
   1006                                const char* abs_dex_location,
   1007                                std::string* error_msg) {
   1008   CheckLocation(location);
   1009   return ElfOatFile::OpenElfFile(file,
   1010                                  location,
   1011                                  nullptr,
   1012                                  nullptr,
   1013                                  true,
   1014                                  false,
   1015                                  /*low_4gb*/false,
   1016                                  abs_dex_location,
   1017                                  error_msg);
   1018 }
   1019 
   1020 OatFile* OatFile::OpenReadable(File* file,
   1021                                const std::string& location,
   1022                                const char* abs_dex_location,
   1023                                std::string* error_msg) {
   1024   CheckLocation(location);
   1025   return ElfOatFile::OpenElfFile(file,
   1026                                  location,
   1027                                  nullptr,
   1028                                  nullptr,
   1029                                  false,
   1030                                  false,
   1031                                  /*low_4gb*/false,
   1032                                  abs_dex_location,
   1033                                  error_msg);
   1034 }
   1035 
   1036 OatFile::OatFile(const std::string& location, bool is_executable)
   1037     : location_(location),
   1038       begin_(nullptr),
   1039       end_(nullptr),
   1040       bss_begin_(nullptr),
   1041       bss_end_(nullptr),
   1042       is_executable_(is_executable),
   1043       secondary_lookup_lock_("OatFile secondary lookup lock", kOatFileSecondaryLookupLock) {
   1044   CHECK(!location_.empty());
   1045 }
   1046 
   1047 OatFile::~OatFile() {
   1048   STLDeleteElements(&oat_dex_files_storage_);
   1049 }
   1050 
   1051 const OatHeader& OatFile::GetOatHeader() const {
   1052   return *reinterpret_cast<const OatHeader*>(Begin());
   1053 }
   1054 
   1055 const uint8_t* OatFile::Begin() const {
   1056   CHECK(begin_ != nullptr);
   1057   return begin_;
   1058 }
   1059 
   1060 const uint8_t* OatFile::End() const {
   1061   CHECK(end_ != nullptr);
   1062   return end_;
   1063 }
   1064 
   1065 const uint8_t* OatFile::BssBegin() const {
   1066   return bss_begin_;
   1067 }
   1068 
   1069 const uint8_t* OatFile::BssEnd() const {
   1070   return bss_end_;
   1071 }
   1072 
   1073 const OatFile::OatDexFile* OatFile::GetOatDexFile(const char* dex_location,
   1074                                                   const uint32_t* dex_location_checksum,
   1075                                                   bool warn_if_not_found) const {
   1076   // NOTE: We assume here that the canonical location for a given dex_location never
   1077   // changes. If it does (i.e. some symlink used by the filename changes) we may return
   1078   // an incorrect OatDexFile. As long as we have a checksum to check, we shall return
   1079   // an identical file or fail; otherwise we may see some unpredictable failures.
   1080 
   1081   // TODO: Additional analysis of usage patterns to see if this can be simplified
   1082   // without any performance loss, for example by not doing the first lock-free lookup.
   1083 
   1084   const OatFile::OatDexFile* oat_dex_file = nullptr;
   1085   StringPiece key(dex_location);
   1086   // Try to find the key cheaply in the oat_dex_files_ map which holds dex locations
   1087   // directly mentioned in the oat file and doesn't require locking.
   1088   auto primary_it = oat_dex_files_.find(key);
   1089   if (primary_it != oat_dex_files_.end()) {
   1090     oat_dex_file = primary_it->second;
   1091     DCHECK(oat_dex_file != nullptr);
   1092   } else {
   1093     // This dex_location is not one of the dex locations directly mentioned in the
   1094     // oat file. The correct lookup is via the canonical location but first see in
   1095     // the secondary_oat_dex_files_ whether we've looked up this location before.
   1096     MutexLock mu(Thread::Current(), secondary_lookup_lock_);
   1097     auto secondary_lb = secondary_oat_dex_files_.lower_bound(key);
   1098     if (secondary_lb != secondary_oat_dex_files_.end() && key == secondary_lb->first) {
   1099       oat_dex_file = secondary_lb->second;  // May be null.
   1100     } else {
   1101       // We haven't seen this dex_location before, we must check the canonical location.
   1102       std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location);
   1103       if (dex_canonical_location != dex_location) {
   1104         StringPiece canonical_key(dex_canonical_location);
   1105         auto canonical_it = oat_dex_files_.find(canonical_key);
   1106         if (canonical_it != oat_dex_files_.end()) {
   1107           oat_dex_file = canonical_it->second;
   1108         }  // else keep null.
   1109       }  // else keep null.
   1110 
   1111       // Copy the key to the string_cache_ and store the result in secondary map.
   1112       string_cache_.emplace_back(key.data(), key.length());
   1113       StringPiece key_copy(string_cache_.back());
   1114       secondary_oat_dex_files_.PutBefore(secondary_lb, key_copy, oat_dex_file);
   1115     }
   1116   }
   1117   if (oat_dex_file != nullptr &&
   1118       (dex_location_checksum == nullptr ||
   1119        oat_dex_file->GetDexFileLocationChecksum() == *dex_location_checksum)) {
   1120     return oat_dex_file;
   1121   }
   1122 
   1123   if (warn_if_not_found) {
   1124     std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location);
   1125     std::string checksum("<unspecified>");
   1126     if (dex_location_checksum != nullptr) {
   1127       checksum = StringPrintf("0x%08x", *dex_location_checksum);
   1128     }
   1129     LOG(WARNING) << "Failed to find OatDexFile for DexFile " << dex_location
   1130                  << " ( canonical path " << dex_canonical_location << ")"
   1131                  << " with checksum " << checksum << " in OatFile " << GetLocation();
   1132     if (kIsDebugBuild) {
   1133       for (const OatDexFile* odf : oat_dex_files_storage_) {
   1134         LOG(WARNING) << "OatFile " << GetLocation()
   1135                      << " contains OatDexFile " << odf->GetDexFileLocation()
   1136                      << " (canonical path " << odf->GetCanonicalDexFileLocation() << ")"
   1137                      << " with checksum 0x" << std::hex << odf->GetDexFileLocationChecksum();
   1138       }
   1139     }
   1140   }
   1141 
   1142   return nullptr;
   1143 }
   1144 
   1145 OatFile::OatDexFile::OatDexFile(const OatFile* oat_file,
   1146                                 const std::string& dex_file_location,
   1147                                 const std::string& canonical_dex_file_location,
   1148                                 uint32_t dex_file_location_checksum,
   1149                                 const uint8_t* dex_file_pointer,
   1150                                 const uint8_t* lookup_table_data,
   1151                                 const uint32_t* oat_class_offsets_pointer,
   1152                                 uint8_t* dex_cache_arrays)
   1153     : oat_file_(oat_file),
   1154       dex_file_location_(dex_file_location),
   1155       canonical_dex_file_location_(canonical_dex_file_location),
   1156       dex_file_location_checksum_(dex_file_location_checksum),
   1157       dex_file_pointer_(dex_file_pointer),
   1158       lookup_table_data_(lookup_table_data),
   1159       oat_class_offsets_pointer_(oat_class_offsets_pointer),
   1160       dex_cache_arrays_(dex_cache_arrays) {}
   1161 
   1162 OatFile::OatDexFile::~OatDexFile() {}
   1163 
   1164 size_t OatFile::OatDexFile::FileSize() const {
   1165   return reinterpret_cast<const DexFile::Header*>(dex_file_pointer_)->file_size_;
   1166 }
   1167 
   1168 std::unique_ptr<const DexFile> OatFile::OatDexFile::OpenDexFile(std::string* error_msg) const {
   1169   ScopedTrace trace(__PRETTY_FUNCTION__);
   1170   return DexFile::Open(dex_file_pointer_,
   1171                        FileSize(),
   1172                        dex_file_location_,
   1173                        dex_file_location_checksum_,
   1174                        this,
   1175                        false /* verify */,
   1176                        error_msg);
   1177 }
   1178 
   1179 uint32_t OatFile::OatDexFile::GetOatClassOffset(uint16_t class_def_index) const {
   1180   return oat_class_offsets_pointer_[class_def_index];
   1181 }
   1182 
   1183 OatFile::OatClass OatFile::OatDexFile::GetOatClass(uint16_t class_def_index) const {
   1184   uint32_t oat_class_offset = GetOatClassOffset(class_def_index);
   1185 
   1186   const uint8_t* oat_class_pointer = oat_file_->Begin() + oat_class_offset;
   1187   CHECK_LT(oat_class_pointer, oat_file_->End()) << oat_file_->GetLocation();
   1188 
   1189   const uint8_t* status_pointer = oat_class_pointer;
   1190   CHECK_LT(status_pointer, oat_file_->End()) << oat_file_->GetLocation();
   1191   mirror::Class::Status status =
   1192       static_cast<mirror::Class::Status>(*reinterpret_cast<const int16_t*>(status_pointer));
   1193   CHECK_LT(status, mirror::Class::kStatusMax);
   1194 
   1195   const uint8_t* type_pointer = status_pointer + sizeof(uint16_t);
   1196   CHECK_LT(type_pointer, oat_file_->End()) << oat_file_->GetLocation();
   1197   OatClassType type = static_cast<OatClassType>(*reinterpret_cast<const uint16_t*>(type_pointer));
   1198   CHECK_LT(type, kOatClassMax);
   1199 
   1200   const uint8_t* after_type_pointer = type_pointer + sizeof(int16_t);
   1201   CHECK_LE(after_type_pointer, oat_file_->End()) << oat_file_->GetLocation();
   1202 
   1203   uint32_t bitmap_size = 0;
   1204   const uint8_t* bitmap_pointer = nullptr;
   1205   const uint8_t* methods_pointer = nullptr;
   1206   if (type != kOatClassNoneCompiled) {
   1207     if (type == kOatClassSomeCompiled) {
   1208       bitmap_size = static_cast<uint32_t>(*reinterpret_cast<const uint32_t*>(after_type_pointer));
   1209       bitmap_pointer = after_type_pointer + sizeof(bitmap_size);
   1210       CHECK_LE(bitmap_pointer, oat_file_->End()) << oat_file_->GetLocation();
   1211       methods_pointer = bitmap_pointer + bitmap_size;
   1212     } else {
   1213       methods_pointer = after_type_pointer;
   1214     }
   1215     CHECK_LE(methods_pointer, oat_file_->End()) << oat_file_->GetLocation();
   1216   }
   1217 
   1218   return OatFile::OatClass(oat_file_,
   1219                            status,
   1220                            type,
   1221                            bitmap_size,
   1222                            reinterpret_cast<const uint32_t*>(bitmap_pointer),
   1223                            reinterpret_cast<const OatMethodOffsets*>(methods_pointer));
   1224 }
   1225 
   1226 OatFile::OatClass::OatClass(const OatFile* oat_file,
   1227                             mirror::Class::Status status,
   1228                             OatClassType type,
   1229                             uint32_t bitmap_size,
   1230                             const uint32_t* bitmap_pointer,
   1231                             const OatMethodOffsets* methods_pointer)
   1232     : oat_file_(oat_file), status_(status), type_(type),
   1233       bitmap_(bitmap_pointer), methods_pointer_(methods_pointer) {
   1234     switch (type_) {
   1235       case kOatClassAllCompiled: {
   1236         CHECK_EQ(0U, bitmap_size);
   1237         CHECK(bitmap_pointer == nullptr);
   1238         CHECK(methods_pointer != nullptr);
   1239         break;
   1240       }
   1241       case kOatClassSomeCompiled: {
   1242         CHECK_NE(0U, bitmap_size);
   1243         CHECK(bitmap_pointer != nullptr);
   1244         CHECK(methods_pointer != nullptr);
   1245         break;
   1246       }
   1247       case kOatClassNoneCompiled: {
   1248         CHECK_EQ(0U, bitmap_size);
   1249         CHECK(bitmap_pointer == nullptr);
   1250         CHECK(methods_pointer_ == nullptr);
   1251         break;
   1252       }
   1253       case kOatClassMax: {
   1254         LOG(FATAL) << "Invalid OatClassType " << type_;
   1255         break;
   1256       }
   1257     }
   1258 }
   1259 
   1260 uint32_t OatFile::OatClass::GetOatMethodOffsetsOffset(uint32_t method_index) const {
   1261   const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
   1262   if (oat_method_offsets == nullptr) {
   1263     return 0u;
   1264   }
   1265   return reinterpret_cast<const uint8_t*>(oat_method_offsets) - oat_file_->Begin();
   1266 }
   1267 
   1268 const OatMethodOffsets* OatFile::OatClass::GetOatMethodOffsets(uint32_t method_index) const {
   1269   // NOTE: We don't keep the number of methods and cannot do a bounds check for method_index.
   1270   if (methods_pointer_ == nullptr) {
   1271     CHECK_EQ(kOatClassNoneCompiled, type_);
   1272     return nullptr;
   1273   }
   1274   size_t methods_pointer_index;
   1275   if (bitmap_ == nullptr) {
   1276     CHECK_EQ(kOatClassAllCompiled, type_);
   1277     methods_pointer_index = method_index;
   1278   } else {
   1279     CHECK_EQ(kOatClassSomeCompiled, type_);
   1280     if (!BitVector::IsBitSet(bitmap_, method_index)) {
   1281       return nullptr;
   1282     }
   1283     size_t num_set_bits = BitVector::NumSetBits(bitmap_, method_index);
   1284     methods_pointer_index = num_set_bits;
   1285   }
   1286   const OatMethodOffsets& oat_method_offsets = methods_pointer_[methods_pointer_index];
   1287   return &oat_method_offsets;
   1288 }
   1289 
   1290 const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) const {
   1291   const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
   1292   if (oat_method_offsets == nullptr) {
   1293     return OatMethod(nullptr, 0);
   1294   }
   1295   if (oat_file_->IsExecutable() ||
   1296       Runtime::Current() == nullptr ||        // This case applies for oatdump.
   1297       Runtime::Current()->IsAotCompiler()) {
   1298     return OatMethod(oat_file_->Begin(), oat_method_offsets->code_offset_);
   1299   }
   1300   // We aren't allowed to use the compiled code. We just force it down the interpreted / jit
   1301   // version.
   1302   return OatMethod(oat_file_->Begin(), 0);
   1303 }
   1304 
   1305 void OatFile::OatMethod::LinkMethod(ArtMethod* method) const {
   1306   CHECK(method != nullptr);
   1307   method->SetEntryPointFromQuickCompiledCode(GetQuickCode());
   1308 }
   1309 
   1310 bool OatFile::HasPatchInfo() const {
   1311   return GetOatHeader().HasPatchInfo();
   1312 }
   1313 
   1314 bool OatFile::IsPic() const {
   1315   return GetOatHeader().IsPic();
   1316   // TODO: Check against oat_patches. b/18144996
   1317 }
   1318 
   1319 bool OatFile::IsDebuggable() const {
   1320   return GetOatHeader().IsDebuggable();
   1321 }
   1322 
   1323 CompilerFilter::Filter OatFile::GetCompilerFilter() const {
   1324   return GetOatHeader().GetCompilerFilter();
   1325 }
   1326 
   1327 static constexpr char kDexClassPathEncodingSeparator = '*';
   1328 
   1329 std::string OatFile::EncodeDexFileDependencies(const std::vector<const DexFile*>& dex_files) {
   1330   std::ostringstream out;
   1331 
   1332   for (const DexFile* dex_file : dex_files) {
   1333     out << dex_file->GetLocation().c_str();
   1334     out << kDexClassPathEncodingSeparator;
   1335     out << dex_file->GetLocationChecksum();
   1336     out << kDexClassPathEncodingSeparator;
   1337   }
   1338 
   1339   return out.str();
   1340 }
   1341 
   1342 bool OatFile::CheckStaticDexFileDependencies(const char* dex_dependencies, std::string* msg) {
   1343   if (dex_dependencies == nullptr || dex_dependencies[0] == 0) {
   1344     // No dependencies.
   1345     return true;
   1346   }
   1347 
   1348   // Assumption: this is not performance-critical. So it's OK to do this with a std::string and
   1349   //             Split() instead of manual parsing of the combined char*.
   1350   std::vector<std::string> split;
   1351   Split(dex_dependencies, kDexClassPathEncodingSeparator, &split);
   1352   if (split.size() % 2 != 0) {
   1353     // Expected pairs of location and checksum.
   1354     *msg = StringPrintf("Odd number of elements in dependency list %s", dex_dependencies);
   1355     return false;
   1356   }
   1357 
   1358   for (auto it = split.begin(), end = split.end(); it != end; it += 2) {
   1359     std::string& location = *it;
   1360     std::string& checksum = *(it + 1);
   1361     int64_t converted = strtoll(checksum.c_str(), nullptr, 10);
   1362     if (converted == 0) {
   1363       // Conversion error.
   1364       *msg = StringPrintf("Conversion error for %s", checksum.c_str());
   1365       return false;
   1366     }
   1367 
   1368     uint32_t dex_checksum;
   1369     std::string error_msg;
   1370     if (DexFile::GetChecksum(DexFile::GetDexCanonicalLocation(location.c_str()).c_str(),
   1371                              &dex_checksum,
   1372                              &error_msg)) {
   1373       if (converted != dex_checksum) {
   1374         *msg = StringPrintf("Checksums don't match for %s: %" PRId64 " vs %u",
   1375                             location.c_str(), converted, dex_checksum);
   1376         return false;
   1377       }
   1378     } else {
   1379       // Problem retrieving checksum.
   1380       // TODO: odex files?
   1381       *msg = StringPrintf("Could not retrieve checksum for %s: %s", location.c_str(),
   1382                           error_msg.c_str());
   1383       return false;
   1384     }
   1385   }
   1386 
   1387   return true;
   1388 }
   1389 
   1390 bool OatFile::GetDexLocationsFromDependencies(const char* dex_dependencies,
   1391                                               std::vector<std::string>* locations) {
   1392   DCHECK(locations != nullptr);
   1393   if (dex_dependencies == nullptr || dex_dependencies[0] == 0) {
   1394     return true;
   1395   }
   1396 
   1397   // Assumption: this is not performance-critical. So it's OK to do this with a std::string and
   1398   //             Split() instead of manual parsing of the combined char*.
   1399   std::vector<std::string> split;
   1400   Split(dex_dependencies, kDexClassPathEncodingSeparator, &split);
   1401   if (split.size() % 2 != 0) {
   1402     // Expected pairs of location and checksum.
   1403     return false;
   1404   }
   1405 
   1406   for (auto it = split.begin(), end = split.end(); it != end; it += 2) {
   1407     locations->push_back(*it);
   1408   }
   1409 
   1410   return true;
   1411 }
   1412 
   1413 }  // namespace art
   1414