• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef __APPLE__
21 #include <link.h>  // for dl_iterate_phdr.
22 #endif
23 #include <unistd.h>
24 
25 #include <cstdlib>
26 #include <cstring>
27 #include <sstream>
28 #include <type_traits>
29 #include <sys/stat.h>
30 
31 // dlopen_ext support from bionic.
32 #ifdef ART_TARGET_ANDROID
33 #include "android/dlext.h"
34 #include "nativeloader/dlext_namespaces.h"
35 #endif
36 
37 #include <android-base/logging.h>
38 #include "android-base/stringprintf.h"
39 
40 #include "arch/instruction_set_features.h"
41 #include "art_method.h"
42 #include "base/bit_vector.h"
43 #include "base/enums.h"
44 #include "base/file_utils.h"
45 #include "base/logging.h"  // For VLOG_IS_ON.
46 #include "base/mem_map.h"
47 #include "base/os.h"
48 #include "base/stl_util.h"
49 #include "base/string_view_cpp20.h"
50 #include "base/systrace.h"
51 #include "base/unix_file/fd_file.h"
52 #include "base/utils.h"
53 #include "class_loader_context.h"
54 #include "dex/art_dex_file_loader.h"
55 #include "dex/dex_file.h"
56 #include "dex/dex_file_loader.h"
57 #include "dex/dex_file_structs.h"
58 #include "dex/dex_file_types.h"
59 #include "dex/standard_dex_file.h"
60 #include "dex/type_lookup_table.h"
61 #include "dex/utf-inl.h"
62 #include "elf/elf_utils.h"
63 #include "elf_file.h"
64 #include "gc_root.h"
65 #include "gc/heap.h"
66 #include "gc/space/image_space.h"
67 #include "mirror/class.h"
68 #include "mirror/object-inl.h"
69 #include "oat.h"
70 #include "oat_file-inl.h"
71 #include "oat_file_manager.h"
72 #include "runtime-inl.h"
73 #include "vdex_file.h"
74 #include "verifier/verifier_deps.h"
75 
76 namespace art {
77 
78 using android::base::StringPrintf;
79 
80 // Whether OatFile::Open will try dlopen. Fallback is our own ELF loader.
81 static constexpr bool kUseDlopen = true;
82 
83 // Whether OatFile::Open will try dlopen on the host. On the host we're not linking against
84 // bionic, so cannot take advantage of the support for changed semantics (loading the same soname
85 // multiple times). However, if/when we switch the above, we likely want to switch this, too,
86 // to get test coverage of the code paths.
87 static constexpr bool kUseDlopenOnHost = true;
88 
89 // For debugging, Open will print DlOpen error message if set to true.
90 static constexpr bool kPrintDlOpenErrorMessage = false;
91 
92 // Note for OatFileBase and descendents:
93 //
94 // These are used in OatFile::Open to try all our loaders.
95 //
96 // The process is simple:
97 //
98 // 1) Allocate an instance through the standard constructor (location, executable)
99 // 2) Load() to try to open the file.
100 // 3) ComputeFields() to populate the OatFile fields like begin_, using FindDynamicSymbolAddress.
101 // 4) PreSetup() for any steps that should be done before the final setup.
102 // 5) Setup() to complete the procedure.
103 
104 class OatFileBase : public OatFile {
105  public:
~OatFileBase()106   virtual ~OatFileBase() {}
107 
108   template <typename kOatFileBaseSubType>
109   static OatFileBase* OpenOatFile(int zip_fd,
110                                   const std::string& vdex_filename,
111                                   const std::string& elf_filename,
112                                   const std::string& location,
113                                   bool writable,
114                                   bool executable,
115                                   bool low_4gb,
116                                   ArrayRef<const std::string> dex_filenames,
117                                   ArrayRef<const int> dex_fds,
118                                   /*inout*/MemMap* reservation,  // Where to load if not null.
119                                   /*out*/std::string* error_msg);
120 
121   template <typename kOatFileBaseSubType>
122   static OatFileBase* OpenOatFile(int zip_fd,
123                                   int vdex_fd,
124                                   int oat_fd,
125                                   const std::string& vdex_filename,
126                                   const std::string& oat_filename,
127                                   bool writable,
128                                   bool executable,
129                                   bool low_4gb,
130                                   ArrayRef<const std::string> dex_filenames,
131                                   ArrayRef<const int> dex_fds,
132                                   /*inout*/MemMap* reservation,  // Where to load if not null.
133                                   /*out*/std::string* error_msg);
134 
135  protected:
OatFileBase(const std::string & filename,bool executable)136   OatFileBase(const std::string& filename, bool executable) : OatFile(filename, executable) {}
137 
138   virtual const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
139                                                   std::string* error_msg) const = 0;
140 
141   virtual void PreLoad() = 0;
142 
143   bool LoadVdex(const std::string& vdex_filename,
144                 bool writable,
145                 bool low_4gb,
146                 std::string* error_msg);
147 
148   bool LoadVdex(int vdex_fd,
149                 const std::string& vdex_filename,
150                 bool writable,
151                 bool low_4gb,
152                 std::string* error_msg);
153 
154   virtual bool Load(const std::string& elf_filename,
155                     bool writable,
156                     bool executable,
157                     bool low_4gb,
158                     /*inout*/MemMap* reservation,  // Where to load if not null.
159                     /*out*/std::string* error_msg) = 0;
160 
161   virtual bool Load(int oat_fd,
162                     bool writable,
163                     bool executable,
164                     bool low_4gb,
165                     /*inout*/MemMap* reservation,  // Where to load if not null.
166                     /*out*/std::string* error_msg) = 0;
167 
168   bool ComputeFields(const std::string& file_path, std::string* error_msg);
169 
170   virtual void PreSetup(const std::string& elf_filename) = 0;
171 
172   bool Setup(int zip_fd,
173              ArrayRef<const std::string> dex_filenames,
174              ArrayRef<const int> dex_fds,
175              std::string* error_msg);
176 
177   bool Setup(const std::vector<const DexFile*>& dex_files, std::string* error_msg);
178 
179   // Setters exposed for ElfOatFile.
180 
SetBegin(const uint8_t * begin)181   void SetBegin(const uint8_t* begin) {
182     begin_ = begin;
183   }
184 
SetEnd(const uint8_t * end)185   void SetEnd(const uint8_t* end) {
186     end_ = end;
187   }
188 
SetVdex(VdexFile * vdex)189   void SetVdex(VdexFile* vdex) {
190     vdex_.reset(vdex);
191   }
192 
193  private:
194   DISALLOW_COPY_AND_ASSIGN(OatFileBase);
195 };
196 
197 template <typename kOatFileBaseSubType>
OpenOatFile(int zip_fd,const std::string & vdex_filename,const std::string & elf_filename,const std::string & location,bool writable,bool executable,bool low_4gb,ArrayRef<const std::string> dex_filenames,ArrayRef<const int> dex_fds,MemMap * reservation,std::string * error_msg)198 OatFileBase* OatFileBase::OpenOatFile(int zip_fd,
199                                       const std::string& vdex_filename,
200                                       const std::string& elf_filename,
201                                       const std::string& location,
202                                       bool writable,
203                                       bool executable,
204                                       bool low_4gb,
205                                       ArrayRef<const std::string> dex_filenames,
206                                       ArrayRef<const int> dex_fds,
207                                       /*inout*/MemMap* reservation,
208                                       /*out*/std::string* error_msg) {
209   std::unique_ptr<OatFileBase> ret(new kOatFileBaseSubType(location, executable));
210 
211   ret->PreLoad();
212 
213   if (!ret->Load(elf_filename,
214                  writable,
215                  executable,
216                  low_4gb,
217                  reservation,
218                  error_msg)) {
219     return nullptr;
220   }
221 
222   if (!ret->ComputeFields(elf_filename, error_msg)) {
223     return nullptr;
224   }
225 
226   ret->PreSetup(elf_filename);
227 
228   if (!ret->LoadVdex(vdex_filename, writable, low_4gb, error_msg)) {
229     return nullptr;
230   }
231 
232   if (!ret->Setup(zip_fd, dex_filenames, dex_fds, error_msg)) {
233     return nullptr;
234   }
235 
236   return ret.release();
237 }
238 
239 template <typename kOatFileBaseSubType>
OpenOatFile(int zip_fd,int vdex_fd,int oat_fd,const std::string & vdex_location,const std::string & oat_location,bool writable,bool executable,bool low_4gb,ArrayRef<const std::string> dex_filenames,ArrayRef<const int> dex_fds,MemMap * reservation,std::string * error_msg)240 OatFileBase* OatFileBase::OpenOatFile(int zip_fd,
241                                       int vdex_fd,
242                                       int oat_fd,
243                                       const std::string& vdex_location,
244                                       const std::string& oat_location,
245                                       bool writable,
246                                       bool executable,
247                                       bool low_4gb,
248                                       ArrayRef<const std::string> dex_filenames,
249                                       ArrayRef<const int> dex_fds,
250                                       /*inout*/MemMap* reservation,
251                                       /*out*/std::string* error_msg) {
252   std::unique_ptr<OatFileBase> ret(new kOatFileBaseSubType(oat_location, executable));
253 
254   if (!ret->Load(oat_fd,
255                  writable,
256                  executable,
257                  low_4gb,
258                  reservation,
259                  error_msg)) {
260     return nullptr;
261   }
262 
263   if (!ret->ComputeFields(oat_location, error_msg)) {
264     return nullptr;
265   }
266 
267   ret->PreSetup(oat_location);
268 
269   if (!ret->LoadVdex(vdex_fd, vdex_location, writable, low_4gb, error_msg)) {
270     return nullptr;
271   }
272 
273   if (!ret->Setup(zip_fd, dex_filenames, dex_fds, error_msg)) {
274     return nullptr;
275   }
276 
277   return ret.release();
278 }
279 
LoadVdex(const std::string & vdex_filename,bool writable,bool low_4gb,std::string * error_msg)280 bool OatFileBase::LoadVdex(const std::string& vdex_filename,
281                            bool writable,
282                            bool low_4gb,
283                            std::string* error_msg) {
284   vdex_ = VdexFile::OpenAtAddress(vdex_begin_,
285                                   vdex_end_ - vdex_begin_,
286                                   /*mmap_reuse=*/vdex_begin_ != nullptr,
287                                   vdex_filename,
288                                   writable,
289                                   low_4gb,
290                                   error_msg);
291   if (vdex_.get() == nullptr) {
292     *error_msg = StringPrintf("Failed to load vdex file '%s' %s",
293                               vdex_filename.c_str(),
294                               error_msg->c_str());
295     return false;
296   }
297   return true;
298 }
299 
LoadVdex(int vdex_fd,const std::string & vdex_filename,bool writable,bool low_4gb,std::string * error_msg)300 bool OatFileBase::LoadVdex(int vdex_fd,
301                            const std::string& vdex_filename,
302                            bool writable,
303                            bool low_4gb,
304                            std::string* error_msg) {
305   if (vdex_fd != -1) {
306     struct stat s;
307     int rc = TEMP_FAILURE_RETRY(fstat(vdex_fd, &s));
308     if (rc == -1) {
309       PLOG(WARNING) << "Failed getting length of vdex file";
310     } else {
311       vdex_ = VdexFile::OpenAtAddress(vdex_begin_,
312                                       vdex_end_ - vdex_begin_,
313                                       /*mmap_reuse=*/vdex_begin_ != nullptr,
314                                       vdex_fd,
315                                       s.st_size,
316                                       vdex_filename,
317                                       writable,
318                                       low_4gb,
319                                       error_msg);
320       if (vdex_.get() == nullptr) {
321         *error_msg = "Failed opening vdex file.";
322         return false;
323       }
324     }
325   }
326   return true;
327 }
328 
ComputeFields(const std::string & file_path,std::string * error_msg)329 bool OatFileBase::ComputeFields(const std::string& file_path, std::string* error_msg) {
330   std::string symbol_error_msg;
331   begin_ = FindDynamicSymbolAddress("oatdata", &symbol_error_msg);
332   if (begin_ == nullptr) {
333     *error_msg = StringPrintf("Failed to find oatdata symbol in '%s' %s",
334                               file_path.c_str(),
335                               symbol_error_msg.c_str());
336     return false;
337   }
338   end_ = FindDynamicSymbolAddress("oatlastword", &symbol_error_msg);
339   if (end_ == nullptr) {
340     *error_msg = StringPrintf("Failed to find oatlastword symbol in '%s' %s",
341                               file_path.c_str(),
342                               symbol_error_msg.c_str());
343     return false;
344   }
345   // Readjust to be non-inclusive upper bound.
346   end_ += sizeof(uint32_t);
347 
348   data_bimg_rel_ro_begin_ = FindDynamicSymbolAddress("oatdatabimgrelro", &symbol_error_msg);
349   if (data_bimg_rel_ro_begin_ != nullptr) {
350     data_bimg_rel_ro_end_ =
351         FindDynamicSymbolAddress("oatdatabimgrelrolastword", &symbol_error_msg);
352     if (data_bimg_rel_ro_end_ == nullptr) {
353       *error_msg =
354           StringPrintf("Failed to find oatdatabimgrelrolastword symbol in '%s'", file_path.c_str());
355       return false;
356     }
357     // Readjust to be non-inclusive upper bound.
358     data_bimg_rel_ro_end_ += sizeof(uint32_t);
359   }
360 
361   bss_begin_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbss", &symbol_error_msg));
362   if (bss_begin_ == nullptr) {
363     // No .bss section.
364     bss_end_ = nullptr;
365   } else {
366     bss_end_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbsslastword", &symbol_error_msg));
367     if (bss_end_ == nullptr) {
368       *error_msg = StringPrintf("Failed to find oatbsslastword symbol in '%s'", file_path.c_str());
369       return false;
370     }
371     // Readjust to be non-inclusive upper bound.
372     bss_end_ += sizeof(uint32_t);
373     // Find bss methods if present.
374     bss_methods_ =
375         const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbssmethods", &symbol_error_msg));
376     // Find bss roots if present.
377     bss_roots_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbssroots", &symbol_error_msg));
378   }
379 
380   vdex_begin_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatdex", &symbol_error_msg));
381   if (vdex_begin_ == nullptr) {
382     // No .vdex section.
383     vdex_end_ = nullptr;
384   } else {
385     vdex_end_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatdexlastword", &symbol_error_msg));
386     if (vdex_end_ == nullptr) {
387       *error_msg = StringPrintf("Failed to find oatdexlastword symbol in '%s'", file_path.c_str());
388       return false;
389     }
390     // Readjust to be non-inclusive upper bound.
391     vdex_end_ += sizeof(uint32_t);
392   }
393 
394   return true;
395 }
396 
397 // Read an unaligned entry from the OatDexFile data in OatFile and advance the read
398 // position by the number of bytes read, i.e. sizeof(T).
399 // Return true on success, false if the read would go beyond the end of the OatFile.
400 template <typename T>
ReadOatDexFileData(const OatFile & oat_file,const uint8_t ** oat,T * value)401 inline static bool ReadOatDexFileData(const OatFile& oat_file,
402                                       /*inout*/const uint8_t** oat,
403                                       /*out*/T* value) {
404   DCHECK(oat != nullptr);
405   DCHECK(value != nullptr);
406   DCHECK_LE(*oat, oat_file.End());
407   if (UNLIKELY(static_cast<size_t>(oat_file.End() - *oat) < sizeof(T))) {
408     return false;
409   }
410   static_assert(std::is_trivial<T>::value, "T must be a trivial type");
411   using unaligned_type __attribute__((__aligned__(1))) = T;
412   *value = *reinterpret_cast<const unaligned_type*>(*oat);
413   *oat += sizeof(T);
414   return true;
415 }
416 
ReadIndexBssMapping(OatFile * oat_file,const uint8_t ** oat,size_t dex_file_index,const std::string & dex_file_location,const char * tag,const IndexBssMapping ** mapping,std::string * error_msg)417 static bool ReadIndexBssMapping(OatFile* oat_file,
418                                 /*inout*/const uint8_t** oat,
419                                 size_t dex_file_index,
420                                 const std::string& dex_file_location,
421                                 const char* tag,
422                                 /*out*/const IndexBssMapping** mapping,
423                                 std::string* error_msg) {
424   uint32_t index_bss_mapping_offset;
425   if (UNLIKELY(!ReadOatDexFileData(*oat_file, oat, &index_bss_mapping_offset))) {
426     *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
427                                   "after %s bss mapping offset",
428                               oat_file->GetLocation().c_str(),
429                               dex_file_index,
430                               dex_file_location.c_str(),
431                               tag);
432     return false;
433   }
434   const bool readable_index_bss_mapping_size =
435       index_bss_mapping_offset != 0u &&
436       index_bss_mapping_offset <= oat_file->Size() &&
437       IsAligned<alignof(IndexBssMapping)>(index_bss_mapping_offset) &&
438       oat_file->Size() - index_bss_mapping_offset >= IndexBssMapping::ComputeSize(0);
439   const IndexBssMapping* index_bss_mapping = readable_index_bss_mapping_size
440       ? reinterpret_cast<const IndexBssMapping*>(oat_file->Begin() + index_bss_mapping_offset)
441       : nullptr;
442   if (index_bss_mapping_offset != 0u &&
443       (UNLIKELY(index_bss_mapping == nullptr) ||
444           UNLIKELY(index_bss_mapping->size() == 0u) ||
445           UNLIKELY(oat_file->Size() - index_bss_mapping_offset <
446                    IndexBssMapping::ComputeSize(index_bss_mapping->size())))) {
447     *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with unaligned or "
448                                   "truncated %s bss mapping, offset %u of %zu, length %zu",
449                               oat_file->GetLocation().c_str(),
450                               dex_file_index,
451                               dex_file_location.c_str(),
452                               tag,
453                               index_bss_mapping_offset,
454                               oat_file->Size(),
455                               index_bss_mapping != nullptr ? index_bss_mapping->size() : 0u);
456     return false;
457   }
458 
459   *mapping = index_bss_mapping;
460   return true;
461 }
462 
ComputeAndCheckTypeLookupTableData(const DexFile::Header & header,const uint8_t * type_lookup_table_start,const VdexFile * vdex_file,const uint8_t ** type_lookup_table_data,std::string * error_msg)463 static bool ComputeAndCheckTypeLookupTableData(const DexFile::Header& header,
464                                                const uint8_t* type_lookup_table_start,
465                                                const VdexFile* vdex_file,
466                                                const uint8_t** type_lookup_table_data,
467                                                std::string* error_msg) {
468   if (type_lookup_table_start == nullptr) {
469     *type_lookup_table_data = nullptr;
470     return true;
471   }
472 
473   if (UNLIKELY(!vdex_file->Contains(type_lookup_table_start, sizeof(uint32_t)))) {
474     *error_msg =
475         StringPrintf("In vdex file '%s' found invalid type lookup table start %p of size %zu "
476                          "not in [%p, %p]",
477                      vdex_file->GetName().c_str(),
478                      type_lookup_table_start,
479                      sizeof(uint32_t),
480                      vdex_file->Begin(),
481                      vdex_file->End());
482     return false;
483   }
484 
485   size_t found_size = reinterpret_cast<const uint32_t*>(type_lookup_table_start)[0];
486   size_t expected_table_size = TypeLookupTable::RawDataLength(header.class_defs_size_);
487   if (UNLIKELY(found_size != expected_table_size)) {
488     *error_msg =
489         StringPrintf("In vdex file '%s' unexpected type lookup table size: found %zu, expected %zu",
490                      vdex_file->GetName().c_str(),
491                      found_size,
492                      expected_table_size);
493     return false;
494   }
495 
496   if (found_size == 0) {
497     *type_lookup_table_data = nullptr;
498     return true;
499   }
500 
501   *type_lookup_table_data = type_lookup_table_start + sizeof(uint32_t);
502   if (UNLIKELY(!vdex_file->Contains(*type_lookup_table_data, found_size))) {
503     *error_msg =
504         StringPrintf("In vdex file '%s' found invalid type lookup table data %p of size %zu "
505                          "not in [%p, %p]",
506                      vdex_file->GetName().c_str(),
507                      type_lookup_table_data,
508                      found_size,
509                      vdex_file->Begin(),
510                      vdex_file->End());
511     return false;
512   }
513   if (UNLIKELY(!IsAligned<4>(type_lookup_table_start))) {
514     *error_msg =
515         StringPrintf("In vdex file '%s' found invalid type lookup table alignment %p",
516                      vdex_file->GetName().c_str(),
517                      type_lookup_table_start);
518     return false;
519   }
520   return true;
521 }
522 
Setup(const std::vector<const DexFile * > & dex_files,std::string * error_msg)523 bool OatFileBase::Setup(const std::vector<const DexFile*>& dex_files, std::string* error_msg) {
524   uint32_t i = 0;
525   const uint8_t* type_lookup_table_start = nullptr;
526   for (const DexFile* dex_file : dex_files) {
527     // Defensively verify external dex file checksum. `OatFileAssistant`
528     // expects this check to happen during oat file setup when the oat file
529     // does not contain dex code.
530     if (dex_file->GetLocationChecksum() != vdex_->GetLocationChecksum(i)) {
531       *error_msg = StringPrintf("Dex checksum does not match for %s, dex has %d, vdex has %d",
532                                 dex_file->GetLocation().c_str(),
533                                 dex_file->GetLocationChecksum(),
534                                 vdex_->GetLocationChecksum(i));
535       return false;
536     }
537     std::string dex_location = dex_file->GetLocation();
538     std::string canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location.c_str());
539 
540     type_lookup_table_start = vdex_->GetNextTypeLookupTableData(type_lookup_table_start, i++);
541     const uint8_t* type_lookup_table_data = nullptr;
542     if (!ComputeAndCheckTypeLookupTableData(dex_file->GetHeader(),
543                                             type_lookup_table_start,
544                                             vdex_.get(),
545                                             &type_lookup_table_data,
546                                             error_msg)) {
547       return false;
548     }
549     // Create an OatDexFile and add it to the owning container.
550     OatDexFile* oat_dex_file = new OatDexFile(
551         this,
552         dex_file->Begin(),
553         dex_file->GetLocationChecksum(),
554         dex_location,
555         canonical_location,
556         type_lookup_table_data);
557     oat_dex_files_storage_.push_back(oat_dex_file);
558 
559     // Add the location and canonical location (if different) to the oat_dex_files_ table.
560     std::string_view key(oat_dex_file->GetDexFileLocation());
561     oat_dex_files_.Put(key, oat_dex_file);
562     if (canonical_location != dex_location) {
563       std::string_view canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
564       oat_dex_files_.Put(canonical_key, oat_dex_file);
565     }
566   }
567   // Now that we've created all the OatDexFile, update the dex files.
568   for (i = 0; i < dex_files.size(); ++i) {
569     dex_files[i]->SetOatDexFile(oat_dex_files_storage_[i]);
570   }
571   return true;
572 }
573 
Setup(int zip_fd,ArrayRef<const std::string> dex_filenames,ArrayRef<const int> dex_fds,std::string * error_msg)574 bool OatFileBase::Setup(int zip_fd,
575                         ArrayRef<const std::string> dex_filenames,
576                         ArrayRef<const int> dex_fds,
577                         std::string* error_msg) {
578   if (!GetOatHeader().IsValid()) {
579     std::string cause = GetOatHeader().GetValidationErrorMessage();
580     *error_msg = StringPrintf("Invalid oat header for '%s': %s",
581                               GetLocation().c_str(),
582                               cause.c_str());
583     return false;
584   }
585   PointerSize pointer_size = GetInstructionSetPointerSize(GetOatHeader().GetInstructionSet());
586   size_t key_value_store_size =
587       (Size() >= sizeof(OatHeader)) ? GetOatHeader().GetKeyValueStoreSize() : 0u;
588   if (Size() < sizeof(OatHeader) + key_value_store_size) {
589     *error_msg = StringPrintf("In oat file '%s' found truncated OatHeader, "
590                                   "size = %zu < %zu + %zu",
591                               GetLocation().c_str(),
592                               Size(),
593                               sizeof(OatHeader),
594                               key_value_store_size);
595     return false;
596   }
597 
598   size_t oat_dex_files_offset = GetOatHeader().GetOatDexFilesOffset();
599   if (oat_dex_files_offset < GetOatHeader().GetHeaderSize() || oat_dex_files_offset > Size()) {
600     *error_msg = StringPrintf("In oat file '%s' found invalid oat dex files offset: "
601                                   "%zu is not in [%zu, %zu]",
602                               GetLocation().c_str(),
603                               oat_dex_files_offset,
604                               GetOatHeader().GetHeaderSize(),
605                               Size());
606     return false;
607   }
608   const uint8_t* oat = Begin() + oat_dex_files_offset;  // Jump to the OatDexFile records.
609 
610   if (!IsAligned<sizeof(uint32_t)>(data_bimg_rel_ro_begin_) ||
611       !IsAligned<sizeof(uint32_t)>(data_bimg_rel_ro_end_) ||
612       data_bimg_rel_ro_begin_ > data_bimg_rel_ro_end_) {
613     *error_msg = StringPrintf("In oat file '%s' found unaligned or unordered databimgrelro "
614                                   "symbol(s): begin = %p, end = %p",
615                               GetLocation().c_str(),
616                               data_bimg_rel_ro_begin_,
617                               data_bimg_rel_ro_end_);
618     return false;
619   }
620 
621   DCHECK_GE(static_cast<size_t>(pointer_size), alignof(GcRoot<mirror::Object>));
622   if (!IsAligned<kPageSize>(bss_begin_) ||
623       !IsAlignedParam(bss_methods_, static_cast<size_t>(pointer_size)) ||
624       !IsAlignedParam(bss_roots_, static_cast<size_t>(pointer_size)) ||
625       !IsAligned<alignof(GcRoot<mirror::Object>)>(bss_end_)) {
626     *error_msg = StringPrintf("In oat file '%s' found unaligned bss symbol(s): "
627                                   "begin = %p, methods_ = %p, roots = %p, end = %p",
628                               GetLocation().c_str(),
629                               bss_begin_,
630                               bss_methods_,
631                               bss_roots_,
632                               bss_end_);
633     return false;
634   }
635 
636   if ((bss_methods_ != nullptr && (bss_methods_ < bss_begin_ || bss_methods_ > bss_end_)) ||
637       (bss_roots_ != nullptr && (bss_roots_ < bss_begin_ || bss_roots_ > bss_end_)) ||
638       (bss_methods_ != nullptr && bss_roots_ != nullptr && bss_methods_ > bss_roots_)) {
639     *error_msg = StringPrintf("In oat file '%s' found bss symbol(s) outside .bss or unordered: "
640                                   "begin = %p, methods = %p, roots = %p, end = %p",
641                               GetLocation().c_str(),
642                               bss_begin_,
643                               bss_methods_,
644                               bss_roots_,
645                               bss_end_);
646     return false;
647   }
648 
649   if (bss_methods_ != nullptr && bss_methods_ != bss_begin_) {
650     *error_msg = StringPrintf("In oat file '%s' found unexpected .bss gap before 'oatbssmethods': "
651                                   "begin = %p, methods = %p",
652                               GetLocation().c_str(),
653                               bss_begin_,
654                               bss_methods_);
655     return false;
656   }
657 
658   std::string_view primary_location;
659   std::string_view primary_location_replacement;
660   int dex_fd = -1;
661   size_t dex_filenames_pos = 0u;
662   uint32_t dex_file_count = GetOatHeader().GetDexFileCount();
663   oat_dex_files_storage_.reserve(dex_file_count);
664   for (size_t i = 0; i < dex_file_count; i++) {
665     uint32_t dex_file_location_size;
666     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_location_size))) {
667       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu truncated after dex file "
668                                     "location size",
669                                 GetLocation().c_str(),
670                                 i);
671       return false;
672     }
673     if (UNLIKELY(dex_file_location_size == 0U)) {
674       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with empty location name",
675                                 GetLocation().c_str(),
676                                 i);
677       return false;
678     }
679     if (UNLIKELY(static_cast<size_t>(End() - oat) < dex_file_location_size)) {
680       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with truncated dex file "
681                                     "location",
682                                 GetLocation().c_str(),
683                                 i);
684       return false;
685     }
686     const char* dex_file_location_data = reinterpret_cast<const char*>(oat);
687     oat += dex_file_location_size;
688 
689     // Location encoded in the oat file. We will use this for multidex naming.
690     std::string_view oat_dex_file_location(dex_file_location_data, dex_file_location_size);
691     std::string dex_file_location(oat_dex_file_location);
692     bool is_multidex = DexFileLoader::IsMultiDexLocation(dex_file_location.c_str());
693     // Check that `is_multidex` does not clash with other indicators. The first dex location
694     // must be primary location and, if we're opening external dex files, the location must
695     // be multi-dex if and only if we already have a dex file opened for it.
696     if ((i == 0 && is_multidex) ||
697         (!external_dex_files_.empty() && (is_multidex != (i < external_dex_files_.size())))) {
698       *error_msg = StringPrintf("In oat file '%s' found unexpected %s location '%s'",
699                                 GetLocation().c_str(),
700                                 is_multidex ? "multi-dex" : "primary",
701                                 dex_file_location.c_str());
702       return false;
703     }
704     // Remember the primary location and, if provided, the replacement from `dex_filenames`.
705     if (!is_multidex) {
706       primary_location = oat_dex_file_location;
707       if (!dex_filenames.empty()) {
708         if (dex_filenames_pos == dex_filenames.size()) {
709           *error_msg = StringPrintf("In oat file '%s' found excessive primary location '%s'"
710                                         ", expected only %zu primary locations",
711                                     GetLocation().c_str(),
712                                     dex_file_location.c_str(),
713                                     dex_filenames.size());
714           return false;
715         }
716         primary_location_replacement = dex_filenames[dex_filenames_pos];
717         dex_fd = dex_filenames_pos < dex_fds.size() ? dex_fds[dex_filenames_pos] : -1;
718         ++dex_filenames_pos;
719       }
720     }
721     // Check that the base location of a multidex location matches the last seen primary location.
722     if (is_multidex &&
723         (!StartsWith(dex_file_location, primary_location) ||
724              dex_file_location[primary_location.size()] != DexFileLoader::kMultiDexSeparator)) {
725       *error_msg = StringPrintf("In oat file '%s' found unexpected multidex location '%s',"
726                                     " unrelated to '%s'",
727                                 GetLocation().c_str(),
728                                 dex_file_location.c_str(),
729                                 std::string(primary_location).c_str());
730       return false;
731     }
732     std::string dex_file_name = dex_file_location;
733     if (!dex_filenames.empty()) {
734       dex_file_name.replace(/*pos*/ 0u, primary_location.size(), primary_location_replacement);
735       // If the location does not contain path and matches the file name component,
736       // use the provided file name also as the location.
737       // TODO: Do we need this for anything other than tests?
738       if (dex_file_location.find('/') == std::string::npos &&
739           dex_file_name.size() > dex_file_location.size() &&
740           dex_file_name[dex_file_name.size() - dex_file_location.size() - 1u] == '/' &&
741           EndsWith(dex_file_name, dex_file_location)) {
742         dex_file_location = dex_file_name;
743       }
744     }
745 
746     uint32_t dex_file_checksum;
747     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_checksum))) {
748       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated after "
749                                     "dex file checksum",
750                                 GetLocation().c_str(),
751                                 i,
752                                 dex_file_location.c_str());
753       return false;
754     }
755 
756     uint32_t dex_file_offset;
757     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_offset))) {
758       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated "
759                                     "after dex file offsets",
760                                 GetLocation().c_str(),
761                                 i,
762                                 dex_file_location.c_str());
763       return false;
764     }
765     if (UNLIKELY(dex_file_offset > DexSize())) {
766       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
767                                     "offset %u > %zu",
768                                 GetLocation().c_str(),
769                                 i,
770                                 dex_file_location.c_str(),
771                                 dex_file_offset,
772                                 DexSize());
773       return false;
774     }
775     const uint8_t* dex_file_pointer = nullptr;
776     if (UNLIKELY(dex_file_offset == 0U)) {
777       // Do not support mixed-mode oat files.
778       if (i != 0u && external_dex_files_.empty()) {
779         *error_msg = StringPrintf("In oat file '%s', unsupported uncompressed-dex-file for dex "
780                                       "file %zu (%s)",
781                                   GetLocation().c_str(),
782                                   i,
783                                   dex_file_location.c_str());
784         return false;
785       }
786       DCHECK_LE(i, external_dex_files_.size());
787       if (i == external_dex_files_.size()) {
788         std::vector<std::unique_ptr<const DexFile>> new_dex_files;
789         // No dex files, load it from location.
790         bool loaded = false;
791         CHECK(zip_fd == -1 || dex_fds.empty());  // Allow only the supported combinations.
792         if (zip_fd != -1) {
793           ArtDexFileLoader dex_file_loader(zip_fd, dex_file_location);
794           loaded = dex_file_loader.Open(/*verify=*/false,
795                                         /*verify_checksum=*/false,
796                                         error_msg,
797                                         &new_dex_files);
798         } else if (dex_fd != -1) {
799           // Note that we assume dex_fds are backing by jars.
800           ArtDexFileLoader dex_file_loader(DupCloexec(dex_fd), dex_file_location);
801           loaded = dex_file_loader.Open(/*verify=*/false,
802                                         /*verify_checksum=*/false,
803                                         error_msg,
804                                         &new_dex_files);
805         } else {
806           ArtDexFileLoader dex_file_loader(dex_file_name.c_str(), dex_file_location);
807           loaded = dex_file_loader.Open(/*verify=*/false,
808                                         /*verify_checksum=*/false,
809                                         error_msg,
810                                         &new_dex_files);
811         }
812         if (!loaded) {
813           if (Runtime::Current() == nullptr) {
814             // If there's no runtime, we're running oatdump, so return
815             // a half constructed oat file that oatdump knows how to deal with.
816             LOG(WARNING) << "Could not find associated dex files of oat file. "
817                          << "Oatdump will only dump the header.";
818             return true;
819           } else {
820             return false;
821           }
822         }
823         // The oat file may be out of date wrt/ the dex-file location. We need to be defensive
824         // here and ensure that at least the number of dex files still matches.
825         // If we have a zip_fd, or reached the end of provided `dex_filenames`, we must
826         // load all dex files from that file, otherwise we may open multiple files.
827         // Note: actual checksum comparisons are the duty of the OatFileAssistant and will be
828         //       done after loading the OatFile.
829         size_t max_dex_files = dex_file_count - external_dex_files_.size();
830         bool expect_all =
831             (zip_fd != -1) || (!dex_filenames.empty() && dex_filenames_pos == dex_filenames.size());
832         if (expect_all ? new_dex_files.size() != max_dex_files
833                        : new_dex_files.size() > max_dex_files) {
834           *error_msg = StringPrintf("In oat file '%s', expected %s%zu uncompressed dex files, but "
835                                         "found %zu in '%s'",
836                                     GetLocation().c_str(),
837                                     (expect_all ? "" : "<="),
838                                     max_dex_files,
839                                     new_dex_files.size(),
840                                     dex_file_location.c_str());
841           return false;
842         }
843         for (std::unique_ptr<const DexFile>& dex_file : new_dex_files) {
844           external_dex_files_.push_back(std::move(dex_file));
845         }
846       }
847       // Defensively verify external dex file checksum. `OatFileAssistant`
848       // expects this check to happen during oat file setup when the oat file
849       // does not contain dex code.
850       if (dex_file_checksum != external_dex_files_[i]->GetLocationChecksum()) {
851         *error_msg = StringPrintf("In oat file '%s', dex file checksum 0x%08x does not match"
852                                       " checksum 0x%08x of external dex file '%s'",
853                                   GetLocation().c_str(),
854                                   dex_file_checksum,
855                                   external_dex_files_[i]->GetLocationChecksum(),
856                                   external_dex_files_[i]->GetLocation().c_str());
857         return false;
858       }
859       dex_file_pointer = external_dex_files_[i]->Begin();
860     } else {
861       // Do not support mixed-mode oat files.
862       if (!external_dex_files_.empty()) {
863         *error_msg = StringPrintf("In oat file '%s', unsupported embedded dex-file for dex file "
864                                       "%zu (%s)",
865                                   GetLocation().c_str(),
866                                   i,
867                                   dex_file_location.c_str());
868         return false;
869       }
870       if (UNLIKELY(DexSize() - dex_file_offset < sizeof(DexFile::Header))) {
871         *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
872                                       "offset %u of %zu but the size of dex file header is %zu",
873                                   GetLocation().c_str(),
874                                   i,
875                                   dex_file_location.c_str(),
876                                   dex_file_offset,
877                                   DexSize(),
878                                   sizeof(DexFile::Header));
879         return false;
880       }
881       dex_file_pointer = DexBegin() + dex_file_offset;
882     }
883 
884     const bool valid_magic = DexFileLoader::IsMagicValid(dex_file_pointer);
885     if (UNLIKELY(!valid_magic)) {
886       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
887                                     "dex file magic",
888                                 GetLocation().c_str(),
889                                 i,
890                                 dex_file_location.c_str());
891       return false;
892     }
893     if (UNLIKELY(!DexFileLoader::IsVersionAndMagicValid(dex_file_pointer))) {
894       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
895                                     "dex file version",
896                                 GetLocation().c_str(),
897                                 i,
898                                 dex_file_location.c_str());
899       return false;
900     }
901     const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer);
902     if (dex_file_offset != 0 && (DexSize() - dex_file_offset < header->file_size_)) {
903       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
904                                     "offset %u and size %u truncated at %zu",
905                                 GetLocation().c_str(),
906                                 i,
907                                 dex_file_location.c_str(),
908                                 dex_file_offset,
909                                 header->file_size_,
910                                 DexSize());
911       return false;
912     }
913 
914     uint32_t class_offsets_offset;
915     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &class_offsets_offset))) {
916       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated "
917                                     "after class offsets offset",
918                                 GetLocation().c_str(),
919                                 i,
920                                 dex_file_location.c_str());
921       return false;
922     }
923     if (UNLIKELY(class_offsets_offset > Size()) ||
924         UNLIKELY((Size() - class_offsets_offset) / sizeof(uint32_t) < header->class_defs_size_)) {
925       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated "
926                                     "class offsets, offset %u of %zu, class defs %u",
927                                 GetLocation().c_str(),
928                                 i,
929                                 dex_file_location.c_str(),
930                                 class_offsets_offset,
931                                 Size(),
932                                 header->class_defs_size_);
933       return false;
934     }
935     if (UNLIKELY(!IsAligned<alignof(uint32_t)>(class_offsets_offset))) {
936       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with unaligned "
937                                     "class offsets, offset %u",
938                                 GetLocation().c_str(),
939                                 i,
940                                 dex_file_location.c_str(),
941                                 class_offsets_offset);
942       return false;
943     }
944     const uint32_t* class_offsets_pointer =
945         reinterpret_cast<const uint32_t*>(Begin() + class_offsets_offset);
946 
947     uint32_t lookup_table_offset;
948     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &lookup_table_offset))) {
949       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
950                                     "after lookup table offset",
951                                 GetLocation().c_str(),
952                                 i,
953                                 dex_file_location.c_str());
954       return false;
955     }
956     const uint8_t* lookup_table_data = lookup_table_offset != 0u
957         ? DexBegin() + lookup_table_offset
958         : nullptr;
959     if (lookup_table_offset != 0u &&
960         (UNLIKELY(lookup_table_offset > DexSize()) ||
961             UNLIKELY(DexSize() - lookup_table_offset <
962                      TypeLookupTable::RawDataLength(header->class_defs_size_)))) {
963       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated "
964                                     "type lookup table, offset %u of %zu, class defs %u",
965                                 GetLocation().c_str(),
966                                 i,
967                                 dex_file_location.c_str(),
968                                 lookup_table_offset,
969                                 Size(),
970                                 header->class_defs_size_);
971       return false;
972     }
973 
974     uint32_t dex_layout_sections_offset;
975     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_layout_sections_offset))) {
976       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
977                                     "after dex layout sections offset",
978                                 GetLocation().c_str(),
979                                 i,
980                                 dex_file_location.c_str());
981       return false;
982     }
983     const DexLayoutSections* const dex_layout_sections = dex_layout_sections_offset != 0
984         ? reinterpret_cast<const DexLayoutSections*>(Begin() + dex_layout_sections_offset)
985         : nullptr;
986 
987     const IndexBssMapping* method_bss_mapping;
988     const IndexBssMapping* type_bss_mapping;
989     const IndexBssMapping* public_type_bss_mapping;
990     const IndexBssMapping* package_type_bss_mapping;
991     const IndexBssMapping* string_bss_mapping;
992     auto read_index_bss_mapping = [&](const char* tag, /*out*/const IndexBssMapping** mapping) {
993       return ReadIndexBssMapping(this, &oat, i, dex_file_location, tag, mapping, error_msg);
994     };
995     if (!read_index_bss_mapping("method", &method_bss_mapping) ||
996         !read_index_bss_mapping("type", &type_bss_mapping) ||
997         !read_index_bss_mapping("public type", &public_type_bss_mapping) ||
998         !read_index_bss_mapping("package type", &package_type_bss_mapping) ||
999         !read_index_bss_mapping("string", &string_bss_mapping)) {
1000       return false;
1001     }
1002 
1003     // Create the OatDexFile and add it to the owning container.
1004     OatDexFile* oat_dex_file = new OatDexFile(
1005         this,
1006         dex_file_location,
1007         DexFileLoader::GetDexCanonicalLocation(dex_file_name.c_str()),
1008         dex_file_checksum,
1009         dex_file_pointer,
1010         lookup_table_data,
1011         method_bss_mapping,
1012         type_bss_mapping,
1013         public_type_bss_mapping,
1014         package_type_bss_mapping,
1015         string_bss_mapping,
1016         class_offsets_pointer,
1017         dex_layout_sections);
1018     oat_dex_files_storage_.push_back(oat_dex_file);
1019 
1020     // Add the location and canonical location (if different) to the oat_dex_files_ table.
1021     // Note: We do not add the non-canonical `dex_file_name`. If it is different from both
1022     // the location and canonical location, GetOatDexFile() shall canonicalize it when
1023     // requested and match the canonical path.
1024     std::string_view key = oat_dex_file_location;  // References oat file data.
1025     std::string_view canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
1026     oat_dex_files_.Put(key, oat_dex_file);
1027     if (canonical_key != key) {
1028       oat_dex_files_.Put(canonical_key, oat_dex_file);
1029     }
1030   }
1031 
1032   size_t bcp_info_offset = GetOatHeader().GetBcpBssInfoOffset();
1033   // `bcp_info_offset` will be 0 for multi-image, or for the case of no mappings.
1034   if (bcp_info_offset != 0) {
1035     // Consistency check.
1036     if (bcp_info_offset < GetOatHeader().GetHeaderSize() || bcp_info_offset > Size()) {
1037       *error_msg = StringPrintf(
1038           "In oat file '%s' found invalid bcp info offset: "
1039           "%zu is not in [%zu, %zu]",
1040           GetLocation().c_str(),
1041           bcp_info_offset,
1042           GetOatHeader().GetHeaderSize(),
1043           Size());
1044       return false;
1045     }
1046     const uint8_t* bcp_info_begin = Begin() + bcp_info_offset;  // Jump to the BCP_info records.
1047 
1048     uint32_t number_of_bcp_dexfiles;
1049     if (UNLIKELY(!ReadOatDexFileData(*this, &bcp_info_begin, &number_of_bcp_dexfiles))) {
1050       *error_msg = StringPrintf("Failed to read the number of BCP dex files");
1051       return false;
1052     }
1053     Runtime* const runtime = Runtime::Current();
1054     ClassLinker* const linker = runtime != nullptr ? runtime->GetClassLinker() : nullptr;
1055     if (linker != nullptr && UNLIKELY(number_of_bcp_dexfiles > linker->GetBootClassPath().size())) {
1056       // If we compiled with more DexFiles than what we have at runtime, we expect to discard this
1057       // OatFile after verifying its checksum in OatFileAssistant. Therefore, we set
1058       // `number_of_bcp_dexfiles` to 0 to avoid reading data that will ultimately be discarded.
1059       number_of_bcp_dexfiles = 0;
1060     }
1061 
1062     DCHECK(bcp_bss_info_.empty());
1063     bcp_bss_info_.resize(number_of_bcp_dexfiles);
1064     // At runtime, there might be more DexFiles added to the BCP that we didn't compile with.
1065     // We only care about the ones in [0..number_of_bcp_dexfiles).
1066     for (size_t i = 0, size = number_of_bcp_dexfiles; i != size; ++i) {
1067       const std::string& dex_file_location = linker != nullptr ?
1068                                                  linker->GetBootClassPath()[i]->GetLocation() :
1069                                                  "No runtime/linker therefore no DexFile location";
1070       auto read_index_bss_mapping = [&](const char* tag, /*out*/const IndexBssMapping** mapping) {
1071         return ReadIndexBssMapping(
1072             this, &bcp_info_begin, i, dex_file_location, tag, mapping, error_msg);
1073       };
1074       if (!read_index_bss_mapping("method", &bcp_bss_info_[i].method_bss_mapping) ||
1075           !read_index_bss_mapping("type", &bcp_bss_info_[i].type_bss_mapping) ||
1076           !read_index_bss_mapping("public type", &bcp_bss_info_[i].public_type_bss_mapping) ||
1077           !read_index_bss_mapping("package type", &bcp_bss_info_[i].package_type_bss_mapping) ||
1078           !read_index_bss_mapping("string", &bcp_bss_info_[i].string_bss_mapping)) {
1079         return false;
1080       }
1081     }
1082   }
1083 
1084   if (!dex_filenames.empty() && dex_filenames_pos != dex_filenames.size()) {
1085     *error_msg = StringPrintf("Oat file '%s' contains only %zu primary dex locations, expected %zu",
1086                               GetLocation().c_str(),
1087                               dex_filenames_pos,
1088                               dex_filenames.size());
1089     return false;
1090   }
1091 
1092   if (DataBimgRelRoBegin() != nullptr) {
1093     // Make .data.bimg.rel.ro read only. ClassLinker shall temporarily make it writable for
1094     // relocation when we register a dex file from this oat file. We do not do the relocation
1095     // here to avoid dirtying the pages if the code is never actually ready to be executed.
1096     uint8_t* reloc_begin = const_cast<uint8_t*>(DataBimgRelRoBegin());
1097     CheckedCall(mprotect, "protect relocations", reloc_begin, DataBimgRelRoSize(), PROT_READ);
1098     // Make sure the file lists a boot image dependency, otherwise the .data.bimg.rel.ro
1099     // section is bogus. The full dependency is checked before the code is executed.
1100     // We cannot do this check if we do not have a key-value store, i.e. for secondary
1101     // oat files for boot image extensions.
1102     if (GetOatHeader().GetKeyValueStoreSize() != 0u) {
1103       const char* boot_class_path_checksum =
1104           GetOatHeader().GetStoreValueByKey(OatHeader::kBootClassPathChecksumsKey);
1105       if (boot_class_path_checksum == nullptr ||
1106           boot_class_path_checksum[0] != gc::space::ImageSpace::kImageChecksumPrefix) {
1107         *error_msg = StringPrintf("Oat file '%s' contains .data.bimg.rel.ro section "
1108                                       "without boot image dependency.",
1109                                   GetLocation().c_str());
1110         return false;
1111       }
1112     }
1113   }
1114 
1115   return true;
1116 }
1117 
1118 ////////////////////////
1119 // OatFile via dlopen //
1120 ////////////////////////
1121 
1122 class DlOpenOatFile final : public OatFileBase {
1123  public:
DlOpenOatFile(const std::string & filename,bool executable)1124   DlOpenOatFile(const std::string& filename, bool executable)
1125       : OatFileBase(filename, executable),
1126         dlopen_handle_(nullptr),
1127         shared_objects_before_(0) {
1128   }
1129 
~DlOpenOatFile()1130   ~DlOpenOatFile() {
1131     if (dlopen_handle_ != nullptr) {
1132       if (!kIsTargetBuild) {
1133         MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
1134         host_dlopen_handles_.erase(dlopen_handle_);
1135         dlclose(dlopen_handle_);
1136       } else {
1137         dlclose(dlopen_handle_);
1138       }
1139     }
1140   }
1141 
1142  protected:
FindDynamicSymbolAddress(const std::string & symbol_name,std::string * error_msg) const1143   const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
1144                                           std::string* error_msg) const override {
1145     const uint8_t* ptr =
1146         reinterpret_cast<const uint8_t*>(dlsym(dlopen_handle_, symbol_name.c_str()));
1147     if (ptr == nullptr) {
1148       *error_msg = dlerror();
1149     }
1150     return ptr;
1151   }
1152 
1153   void PreLoad() override;
1154 
1155   bool Load(const std::string& elf_filename,
1156             bool writable,
1157             bool executable,
1158             bool low_4gb,
1159             /*inout*/MemMap* reservation,  // Where to load if not null.
1160             /*out*/std::string* error_msg) override;
1161 
Load(int oat_fd ATTRIBUTE_UNUSED,bool writable ATTRIBUTE_UNUSED,bool executable ATTRIBUTE_UNUSED,bool low_4gb ATTRIBUTE_UNUSED,MemMap * reservation ATTRIBUTE_UNUSED,std::string * error_msg ATTRIBUTE_UNUSED)1162   bool Load(int oat_fd ATTRIBUTE_UNUSED,
1163             bool writable ATTRIBUTE_UNUSED,
1164             bool executable ATTRIBUTE_UNUSED,
1165             bool low_4gb ATTRIBUTE_UNUSED,
1166             /*inout*/MemMap* reservation ATTRIBUTE_UNUSED,
1167             /*out*/std::string* error_msg ATTRIBUTE_UNUSED) override {
1168     return false;
1169   }
1170 
1171   // Ask the linker where it mmaped the file and notify our mmap wrapper of the regions.
1172   void PreSetup(const std::string& elf_filename) override;
1173 
1174  private:
1175   bool Dlopen(const std::string& elf_filename,
1176               /*inout*/MemMap* reservation,  // Where to load if not null.
1177               /*out*/std::string* error_msg);
1178 
1179   // On the host, if the same library is loaded again with dlopen the same
1180   // file handle is returned. This differs from the behavior of dlopen on the
1181   // target, where dlopen reloads the library at a different address every
1182   // time you load it. The runtime relies on the target behavior to ensure
1183   // each instance of the loaded library has a unique dex cache. To avoid
1184   // problems, we fall back to our own linker in the case when the same
1185   // library is opened multiple times on host. dlopen_handles_ is used to
1186   // detect that case.
1187   // Guarded by host_dlopen_handles_lock_;
1188   static std::unordered_set<void*> host_dlopen_handles_;
1189 
1190   // Reservation and placeholder memory map objects corresponding to the regions mapped by dlopen.
1191   // Note: Must be destroyed after dlclose() as it can hold the owning reservation.
1192   std::vector<MemMap> dlopen_mmaps_;
1193 
1194   // dlopen handle during runtime.
1195   void* dlopen_handle_;  // TODO: Unique_ptr with custom deleter.
1196 
1197   // The number of shared objects the linker told us about before loading. Used to
1198   // (optimistically) optimize the PreSetup stage (see comment there).
1199   size_t shared_objects_before_;
1200 
1201   DISALLOW_COPY_AND_ASSIGN(DlOpenOatFile);
1202 };
1203 
1204 std::unordered_set<void*> DlOpenOatFile::host_dlopen_handles_;
1205 
PreLoad()1206 void DlOpenOatFile::PreLoad() {
1207 #ifdef __APPLE__
1208   UNUSED(shared_objects_before_);
1209   LOG(FATAL) << "Should not reach here.";
1210   UNREACHABLE();
1211 #else
1212   // Count the entries in dl_iterate_phdr we get at this point in time.
1213   struct dl_iterate_context {
1214     static int callback(dl_phdr_info* info ATTRIBUTE_UNUSED,
1215                         size_t size ATTRIBUTE_UNUSED,
1216                         void* data) {
1217       reinterpret_cast<dl_iterate_context*>(data)->count++;
1218       return 0;  // Continue iteration.
1219     }
1220     size_t count = 0;
1221   } context;
1222 
1223   dl_iterate_phdr(dl_iterate_context::callback, &context);
1224   shared_objects_before_ = context.count;
1225 #endif
1226 }
1227 
Load(const std::string & elf_filename,bool writable,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1228 bool DlOpenOatFile::Load(const std::string& elf_filename,
1229                          bool writable,
1230                          bool executable,
1231                          bool low_4gb,
1232                          /*inout*/MemMap* reservation,  // Where to load if not null.
1233                          /*out*/std::string* error_msg) {
1234   // Use dlopen only when flagged to do so, and when it's OK to load things executable.
1235   // TODO: Also try when not executable? The issue here could be re-mapping as writable (as
1236   //       !executable is a sign that we may want to patch), which may not be allowed for
1237   //       various reasons.
1238   if (!kUseDlopen) {
1239     *error_msg = "DlOpen is disabled.";
1240     return false;
1241   }
1242   if (low_4gb) {
1243     *error_msg = "DlOpen does not support low 4gb loading.";
1244     return false;
1245   }
1246   if (writable) {
1247     *error_msg = "DlOpen does not support writable loading.";
1248     return false;
1249   }
1250   if (!executable) {
1251     *error_msg = "DlOpen does not support non-executable loading.";
1252     return false;
1253   }
1254 
1255   // dlopen always returns the same library if it is already opened on the host. For this reason
1256   // we only use dlopen if we are the target or we do not already have the dex file opened. Having
1257   // the same library loaded multiple times at different addresses is required for class unloading
1258   // and for having dex caches arrays in the .bss section.
1259   if (!kIsTargetBuild) {
1260     if (!kUseDlopenOnHost) {
1261       *error_msg = "DlOpen disabled for host.";
1262       return false;
1263     }
1264   }
1265 
1266   bool success = Dlopen(elf_filename, reservation, error_msg);
1267   DCHECK_IMPLIES(dlopen_handle_ == nullptr, !success);
1268 
1269   return success;
1270 }
1271 
1272 #ifdef ART_TARGET_ANDROID
GetSystemLinkerNamespace()1273 static struct android_namespace_t* GetSystemLinkerNamespace() {
1274   static struct android_namespace_t* system_ns = []() {
1275     // The system namespace is called "default" for binaries in /system and
1276     // "system" for those in the ART APEX. Try "system" first since "default"
1277     // always exists.
1278     // TODO(b/185587109): Get rid of this error prone logic.
1279     struct android_namespace_t* ns = android_get_exported_namespace("system");
1280     if (ns == nullptr) {
1281       ns = android_get_exported_namespace("default");
1282       if (ns == nullptr) {
1283         LOG(FATAL) << "Failed to get system namespace for loading OAT files";
1284       }
1285     }
1286     return ns;
1287   }();
1288   return system_ns;
1289 }
1290 #endif  // ART_TARGET_ANDROID
1291 
Dlopen(const std::string & elf_filename,MemMap * reservation,std::string * error_msg)1292 bool DlOpenOatFile::Dlopen(const std::string& elf_filename,
1293                            /*inout*/MemMap* reservation,
1294                            /*out*/std::string* error_msg) {
1295 #ifdef __APPLE__
1296   // The dl_iterate_phdr syscall is missing.  There is similar API on OSX,
1297   // but let's fallback to the custom loading code for the time being.
1298   UNUSED(elf_filename, reservation);
1299   *error_msg = "Dlopen unsupported on Mac.";
1300   return false;
1301 #else
1302   {
1303     UniqueCPtr<char> absolute_path(realpath(elf_filename.c_str(), nullptr));
1304     if (absolute_path == nullptr) {
1305       *error_msg = StringPrintf("Failed to find absolute path for '%s'", elf_filename.c_str());
1306       return false;
1307     }
1308 #ifdef ART_TARGET_ANDROID
1309     android_dlextinfo extinfo = {};
1310     extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;   // Force-load, don't reuse handle
1311                                                 //   (open oat files multiple times).
1312     if (reservation != nullptr) {
1313       if (!reservation->IsValid()) {
1314         *error_msg = StringPrintf("Invalid reservation for %s", elf_filename.c_str());
1315         return false;
1316       }
1317       extinfo.flags |= ANDROID_DLEXT_RESERVED_ADDRESS;          // Use the reserved memory range.
1318       extinfo.reserved_addr = reservation->Begin();
1319       extinfo.reserved_size = reservation->Size();
1320     }
1321 
1322     if (strncmp(kAndroidArtApexDefaultPath,
1323                 absolute_path.get(),
1324                 sizeof(kAndroidArtApexDefaultPath) - 1) != 0 ||
1325         absolute_path.get()[sizeof(kAndroidArtApexDefaultPath) - 1] != '/') {
1326       // Use the system namespace for OAT files outside the ART APEX. Search
1327       // paths and links don't matter here, but permitted paths do, and the
1328       // system namespace is configured to allow loading from all appropriate
1329       // locations.
1330       extinfo.flags |= ANDROID_DLEXT_USE_NAMESPACE;
1331       extinfo.library_namespace = GetSystemLinkerNamespace();
1332     }
1333 
1334     dlopen_handle_ = android_dlopen_ext(absolute_path.get(), RTLD_NOW, &extinfo);
1335     if (reservation != nullptr && dlopen_handle_ != nullptr) {
1336       // Find used pages from the reservation.
1337       struct dl_iterate_context {
1338         static int callback(dl_phdr_info* info, size_t size ATTRIBUTE_UNUSED, void* data) {
1339           auto* context = reinterpret_cast<dl_iterate_context*>(data);
1340           static_assert(std::is_same<Elf32_Half, Elf64_Half>::value, "Half must match");
1341           using Elf_Half = Elf64_Half;
1342 
1343           // See whether this callback corresponds to the file which we have just loaded.
1344           uint8_t* reservation_begin = context->reservation->Begin();
1345           bool contained_in_reservation = false;
1346           for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
1347             if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1348               uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1349                   info->dlpi_phdr[i].p_vaddr);
1350               size_t memsz = info->dlpi_phdr[i].p_memsz;
1351               size_t offset = static_cast<size_t>(vaddr - reservation_begin);
1352               if (offset < context->reservation->Size()) {
1353                 contained_in_reservation = true;
1354                 DCHECK_LE(memsz, context->reservation->Size() - offset);
1355               } else if (vaddr < reservation_begin) {
1356                 // Check that there's no overlap with the reservation.
1357                 DCHECK_LE(memsz, static_cast<size_t>(reservation_begin - vaddr));
1358               }
1359               break;  // It is sufficient to check the first PT_LOAD header.
1360             }
1361           }
1362 
1363           if (contained_in_reservation) {
1364             for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
1365               if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1366                 uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1367                     info->dlpi_phdr[i].p_vaddr);
1368                 size_t memsz = info->dlpi_phdr[i].p_memsz;
1369                 size_t offset = static_cast<size_t>(vaddr - reservation_begin);
1370                 DCHECK_LT(offset, context->reservation->Size());
1371                 DCHECK_LE(memsz, context->reservation->Size() - offset);
1372                 context->max_size = std::max(context->max_size, offset + memsz);
1373               }
1374             }
1375 
1376             return 1;  // Stop iteration and return 1 from dl_iterate_phdr.
1377           }
1378           return 0;  // Continue iteration and return 0 from dl_iterate_phdr when finished.
1379         }
1380 
1381         const MemMap* const reservation;
1382         size_t max_size = 0u;
1383       };
1384       dl_iterate_context context = { reservation };
1385 
1386       if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
1387         LOG(FATAL) << "Could not find the shared object mmapped to the reservation.";
1388         UNREACHABLE();
1389       }
1390 
1391       // Take ownership of the memory used by the shared object. dlopen() does not assume
1392       // full ownership of this memory and dlclose() shall just remap it as zero pages with
1393       // PROT_NONE. We need to unmap the memory when destroying this oat file.
1394       dlopen_mmaps_.push_back(reservation->TakeReservedMemory(context.max_size));
1395     }
1396 #else
1397     static_assert(!kIsTargetBuild || kIsTargetLinux || kIsTargetFuchsia,
1398                   "host_dlopen_handles_ will leak handles");
1399     if (reservation != nullptr) {
1400       *error_msg = StringPrintf("dlopen() into reserved memory is unsupported on host for '%s'.",
1401                                 elf_filename.c_str());
1402       return false;
1403     }
1404     MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
1405     dlopen_handle_ = dlopen(absolute_path.get(), RTLD_NOW);
1406     if (dlopen_handle_ != nullptr) {
1407       if (!host_dlopen_handles_.insert(dlopen_handle_).second) {
1408         dlclose(dlopen_handle_);
1409         dlopen_handle_ = nullptr;
1410         *error_msg = StringPrintf("host dlopen re-opened '%s'", elf_filename.c_str());
1411         return false;
1412       }
1413     }
1414 #endif  // ART_TARGET_ANDROID
1415   }
1416   if (dlopen_handle_ == nullptr) {
1417     *error_msg = StringPrintf("Failed to dlopen '%s': %s", elf_filename.c_str(), dlerror());
1418     return false;
1419   }
1420   return true;
1421 #endif
1422 }
1423 
PreSetup(const std::string & elf_filename)1424 void DlOpenOatFile::PreSetup(const std::string& elf_filename) {
1425 #ifdef __APPLE__
1426   UNUSED(elf_filename);
1427   LOG(FATAL) << "Should not reach here.";
1428   UNREACHABLE();
1429 #else
1430   struct PlaceholderMapData {
1431     const char* name;
1432     uint8_t* vaddr;
1433     size_t memsz;
1434   };
1435   struct dl_iterate_context {
1436     static int callback(dl_phdr_info* info, size_t size ATTRIBUTE_UNUSED, void* data) {
1437       auto* context = reinterpret_cast<dl_iterate_context*>(data);
1438       static_assert(std::is_same<Elf32_Half, Elf64_Half>::value, "Half must match");
1439       using Elf_Half = Elf64_Half;
1440 
1441       context->shared_objects_seen++;
1442       if (context->shared_objects_seen < context->shared_objects_before) {
1443         // We haven't been called yet for anything we haven't seen before. Just continue.
1444         // Note: this is aggressively optimistic. If another thread was unloading a library,
1445         //       we may miss out here. However, this does not happen often in practice.
1446         return 0;
1447       }
1448 
1449       // See whether this callback corresponds to the file which we have just loaded.
1450       bool contains_begin = false;
1451       for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
1452         if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1453           uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1454               info->dlpi_phdr[i].p_vaddr);
1455           size_t memsz = info->dlpi_phdr[i].p_memsz;
1456           if (vaddr <= context->begin_ && context->begin_ < vaddr + memsz) {
1457             contains_begin = true;
1458             break;
1459           }
1460         }
1461       }
1462       // Add placeholder mmaps for this file.
1463       if (contains_begin) {
1464         for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
1465           if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1466             uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1467                 info->dlpi_phdr[i].p_vaddr);
1468             size_t memsz = info->dlpi_phdr[i].p_memsz;
1469             size_t name_size = strlen(info->dlpi_name) + 1u;
1470             std::vector<char>* placeholder_maps_names = context->placeholder_maps_names_;
1471             // We must not allocate any memory in the callback, see b/156312036 .
1472             if (name_size < placeholder_maps_names->capacity() - placeholder_maps_names->size() &&
1473                 context->placeholder_maps_data_->size() <
1474                     context->placeholder_maps_data_->capacity()) {
1475               placeholder_maps_names->insert(
1476                   placeholder_maps_names->end(), info->dlpi_name, info->dlpi_name + name_size);
1477               const char* name =
1478                   &(*placeholder_maps_names)[placeholder_maps_names->size() - name_size];
1479               context->placeholder_maps_data_->push_back({ name, vaddr, memsz });
1480             }
1481             context->num_placeholder_maps_ += 1u;
1482             context->placeholder_maps_names_size_ += name_size;
1483           }
1484         }
1485         return 1;  // Stop iteration and return 1 from dl_iterate_phdr.
1486       }
1487       return 0;  // Continue iteration and return 0 from dl_iterate_phdr when finished.
1488     }
1489     const uint8_t* const begin_;
1490     std::vector<PlaceholderMapData>* placeholder_maps_data_;
1491     size_t num_placeholder_maps_;
1492     std::vector<char>* placeholder_maps_names_;
1493     size_t placeholder_maps_names_size_;
1494     size_t shared_objects_before;
1495     size_t shared_objects_seen;
1496   };
1497 
1498   // We must not allocate any memory in the callback, see b/156312036 .
1499   // Therefore we pre-allocate storage for the data we need for creating the placeholder maps.
1500   std::vector<PlaceholderMapData> placeholder_maps_data;
1501   placeholder_maps_data.reserve(32);  // 32 should be enough. If not, we'll retry.
1502   std::vector<char> placeholder_maps_names;
1503   placeholder_maps_names.reserve(4 * KB);  // 4KiB should be enough. If not, we'll retry.
1504 
1505   dl_iterate_context context = {
1506       Begin(),
1507       &placeholder_maps_data,
1508       /*num_placeholder_maps_*/ 0u,
1509       &placeholder_maps_names,
1510       /*placeholder_maps_names_size_*/ 0u,
1511       shared_objects_before_,
1512       /*shared_objects_seen*/ 0u
1513   };
1514 
1515   if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
1516     // Hm. Maybe our optimization went wrong. Try another time with shared_objects_before == 0
1517     // before giving up. This should be unusual.
1518     VLOG(oat) << "Need a second run in PreSetup, didn't find with shared_objects_before="
1519               << shared_objects_before_;
1520     DCHECK(placeholder_maps_data.empty());
1521     DCHECK_EQ(context.num_placeholder_maps_, 0u);
1522     DCHECK(placeholder_maps_names.empty());
1523     DCHECK_EQ(context.placeholder_maps_names_size_, 0u);
1524     context.shared_objects_before = 0u;
1525     context.shared_objects_seen = 0u;
1526     if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
1527       // OK, give up and print an error.
1528       PrintFileToLog("/proc/self/maps", android::base::LogSeverity::WARNING);
1529       LOG(ERROR) << "File " << elf_filename << " loaded with dlopen but cannot find its mmaps.";
1530     }
1531   }
1532 
1533   if (placeholder_maps_data.size() < context.num_placeholder_maps_) {
1534     // Insufficient capacity. Reserve more space and retry.
1535     placeholder_maps_data.clear();
1536     placeholder_maps_data.reserve(context.num_placeholder_maps_);
1537     context.num_placeholder_maps_ = 0u;
1538     placeholder_maps_names.clear();
1539     placeholder_maps_names.reserve(context.placeholder_maps_names_size_);
1540     context.placeholder_maps_names_size_ = 0u;
1541     context.shared_objects_before = 0u;
1542     context.shared_objects_seen = 0u;
1543     bool success = (dl_iterate_phdr(dl_iterate_context::callback, &context) != 0);
1544     CHECK(success);
1545   }
1546 
1547   CHECK_EQ(placeholder_maps_data.size(), context.num_placeholder_maps_);
1548   CHECK_EQ(placeholder_maps_names.size(), context.placeholder_maps_names_size_);
1549   DCHECK_EQ(static_cast<size_t>(std::count(placeholder_maps_names.begin(),
1550                                            placeholder_maps_names.end(), '\0')),
1551             context.num_placeholder_maps_);
1552   for (const PlaceholderMapData& data : placeholder_maps_data) {
1553     MemMap mmap = MemMap::MapPlaceholder(data.name, data.vaddr, data.memsz);
1554     dlopen_mmaps_.push_back(std::move(mmap));
1555   }
1556 #endif
1557 }
1558 
1559 ////////////////////////////////////////////////
1560 // OatFile via our own ElfFile implementation //
1561 ////////////////////////////////////////////////
1562 
1563 class ElfOatFile final : public OatFileBase {
1564  public:
ElfOatFile(const std::string & filename,bool executable)1565   ElfOatFile(const std::string& filename, bool executable) : OatFileBase(filename, executable) {}
1566 
1567   bool InitializeFromElfFile(int zip_fd,
1568                              ElfFile* elf_file,
1569                              VdexFile* vdex_file,
1570                              ArrayRef<const std::string> dex_filenames,
1571                              std::string* error_msg);
1572 
1573  protected:
FindDynamicSymbolAddress(const std::string & symbol_name,std::string * error_msg) const1574   const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
1575                                           std::string* error_msg) const override {
1576     const uint8_t* ptr = elf_file_->FindDynamicSymbolAddress(symbol_name);
1577     if (ptr == nullptr) {
1578       *error_msg = "(Internal implementation could not find symbol)";
1579     }
1580     return ptr;
1581   }
1582 
PreLoad()1583   void PreLoad() override {
1584   }
1585 
1586   bool Load(const std::string& elf_filename,
1587             bool writable,
1588             bool executable,
1589             bool low_4gb,
1590             /*inout*/MemMap* reservation,  // Where to load if not null.
1591             /*out*/std::string* error_msg) override;
1592 
1593   bool Load(int oat_fd,
1594             bool writable,
1595             bool executable,
1596             bool low_4gb,
1597             /*inout*/MemMap* reservation,  // Where to load if not null.
1598             /*out*/std::string* error_msg) override;
1599 
PreSetup(const std::string & elf_filename ATTRIBUTE_UNUSED)1600   void PreSetup(const std::string& elf_filename ATTRIBUTE_UNUSED) override {
1601   }
1602 
1603  private:
1604   bool ElfFileOpen(File* file,
1605                    bool writable,
1606                    bool executable,
1607                    bool low_4gb,
1608                    /*inout*/MemMap* reservation,  // Where to load if not null.
1609                    /*out*/std::string* error_msg);
1610 
1611  private:
1612   // Backing memory map for oat file during cross compilation.
1613   std::unique_ptr<ElfFile> elf_file_;
1614 
1615   DISALLOW_COPY_AND_ASSIGN(ElfOatFile);
1616 };
1617 
InitializeFromElfFile(int zip_fd,ElfFile * elf_file,VdexFile * vdex_file,ArrayRef<const std::string> dex_filenames,std::string * error_msg)1618 bool ElfOatFile::InitializeFromElfFile(int zip_fd,
1619                                        ElfFile* elf_file,
1620                                        VdexFile* vdex_file,
1621                                        ArrayRef<const std::string> dex_filenames,
1622                                        std::string* error_msg) {
1623   ScopedTrace trace(__PRETTY_FUNCTION__);
1624   if (IsExecutable()) {
1625     *error_msg = "Cannot initialize from elf file in executable mode.";
1626     return false;
1627   }
1628   elf_file_.reset(elf_file);
1629   SetVdex(vdex_file);
1630   uint64_t offset, size;
1631   bool has_section = elf_file->GetSectionOffsetAndSize(".rodata", &offset, &size);
1632   CHECK(has_section);
1633   SetBegin(elf_file->Begin() + offset);
1634   SetEnd(elf_file->Begin() + size + offset);
1635   // Ignore the optional .bss section when opening non-executable.
1636   return Setup(zip_fd, dex_filenames, /*dex_fds=*/ArrayRef<const int>(), error_msg);
1637 }
1638 
Load(const std::string & elf_filename,bool writable,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1639 bool ElfOatFile::Load(const std::string& elf_filename,
1640                       bool writable,
1641                       bool executable,
1642                       bool low_4gb,
1643                       /*inout*/MemMap* reservation,
1644                       /*out*/std::string* error_msg) {
1645   ScopedTrace trace(__PRETTY_FUNCTION__);
1646   std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str()));
1647   if (file == nullptr) {
1648     *error_msg = StringPrintf("Failed to open oat filename for reading: %s", strerror(errno));
1649     return false;
1650   }
1651   return ElfOatFile::ElfFileOpen(file.get(),
1652                                  writable,
1653                                  executable,
1654                                  low_4gb,
1655                                  reservation,
1656                                  error_msg);
1657 }
1658 
Load(int oat_fd,bool writable,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1659 bool ElfOatFile::Load(int oat_fd,
1660                       bool writable,
1661                       bool executable,
1662                       bool low_4gb,
1663                       /*inout*/MemMap* reservation,
1664                       /*out*/std::string* error_msg) {
1665   ScopedTrace trace(__PRETTY_FUNCTION__);
1666   if (oat_fd != -1) {
1667     int duped_fd = DupCloexec(oat_fd);
1668     std::unique_ptr<File> file = std::make_unique<File>(duped_fd, false);
1669     if (file == nullptr) {
1670       *error_msg = StringPrintf("Failed to open oat filename for reading: %s",
1671                                 strerror(errno));
1672       return false;
1673     }
1674     return ElfOatFile::ElfFileOpen(file.get(),
1675                                    writable,
1676                                    executable,
1677                                    low_4gb,
1678                                    reservation,
1679                                    error_msg);
1680   }
1681   return false;
1682 }
1683 
ElfFileOpen(File * file,bool writable,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1684 bool ElfOatFile::ElfFileOpen(File* file,
1685                              bool writable,
1686                              bool executable,
1687                              bool low_4gb,
1688                              /*inout*/MemMap* reservation,
1689                              /*out*/std::string* error_msg) {
1690   ScopedTrace trace(__PRETTY_FUNCTION__);
1691   elf_file_.reset(ElfFile::Open(file,
1692                                 writable,
1693                                 /*program_header_only=*/true,
1694                                 low_4gb,
1695                                 error_msg));
1696   if (elf_file_ == nullptr) {
1697     DCHECK(!error_msg->empty());
1698     return false;
1699   }
1700   bool loaded = elf_file_->Load(file, executable, low_4gb, reservation, error_msg);
1701   DCHECK(loaded || !error_msg->empty());
1702   return loaded;
1703 }
1704 
1705 class OatFileBackedByVdex final : public OatFileBase {
1706  public:
OatFileBackedByVdex(const std::string & filename)1707   explicit OatFileBackedByVdex(const std::string& filename)
1708       : OatFileBase(filename, /*executable=*/false) {}
1709 
Open(const std::vector<const DexFile * > & dex_files,std::unique_ptr<VdexFile> && vdex_file,const std::string & location,ClassLoaderContext * context)1710   static OatFileBackedByVdex* Open(const std::vector<const DexFile*>& dex_files,
1711                                    std::unique_ptr<VdexFile>&& vdex_file,
1712                                    const std::string& location,
1713                                    ClassLoaderContext* context) {
1714     std::unique_ptr<OatFileBackedByVdex> oat_file(new OatFileBackedByVdex(location));
1715     // SetVdex will take ownership of the VdexFile.
1716     oat_file->SetVdex(vdex_file.release());
1717     oat_file->SetupHeader(dex_files.size(), context);
1718     // Initialize OatDexFiles.
1719     std::string error_msg;
1720     if (!oat_file->Setup(dex_files, &error_msg)) {
1721       LOG(WARNING) << "Could not create in-memory vdex file: " << error_msg;
1722       return nullptr;
1723     }
1724     return oat_file.release();
1725   }
1726 
Open(int zip_fd,std::unique_ptr<VdexFile> && unique_vdex_file,const std::string & dex_location,ClassLoaderContext * context,std::string * error_msg)1727   static OatFileBackedByVdex* Open(int zip_fd,
1728                                    std::unique_ptr<VdexFile>&& unique_vdex_file,
1729                                    const std::string& dex_location,
1730                                    ClassLoaderContext* context,
1731                                    std::string* error_msg) {
1732     VdexFile* vdex_file = unique_vdex_file.get();
1733     std::unique_ptr<OatFileBackedByVdex> oat_file(new OatFileBackedByVdex(vdex_file->GetName()));
1734     // SetVdex will take ownership of the VdexFile.
1735     oat_file->SetVdex(unique_vdex_file.release());
1736     if (vdex_file->HasDexSection()) {
1737       uint32_t i = 0;
1738       const uint8_t* type_lookup_table_start = nullptr;
1739       for (const uint8_t* dex_file_start = vdex_file->GetNextDexFileData(nullptr, i);
1740            dex_file_start != nullptr;
1741            dex_file_start = vdex_file->GetNextDexFileData(dex_file_start, ++i)) {
1742         if (UNLIKELY(!vdex_file->Contains(dex_file_start, sizeof(DexFile::Header)))) {
1743           *error_msg =
1744               StringPrintf("In vdex file '%s' found invalid dex header %p of size %zu "
1745                                "not in [%p, %p]",
1746                            dex_location.c_str(),
1747                            dex_file_start,
1748                            sizeof(DexFile::Header),
1749                            vdex_file->Begin(),
1750                            vdex_file->End());
1751           return nullptr;
1752         }
1753         const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_start);
1754         if (UNLIKELY(!vdex_file->Contains(dex_file_start, header->file_size_))) {
1755           *error_msg =
1756               StringPrintf("In vdex file '%s' found invalid dex file pointer %p of size %d "
1757                                "not in [%p, %p]",
1758                            dex_location.c_str(),
1759                            dex_file_start,
1760                            header->file_size_,
1761                            vdex_file->Begin(),
1762                            vdex_file->End());
1763           return nullptr;
1764         }
1765         if (UNLIKELY(!DexFileLoader::IsVersionAndMagicValid(dex_file_start))) {
1766           *error_msg =
1767               StringPrintf("In vdex file '%s' found dex file with invalid dex file version",
1768                            dex_location.c_str());
1769           return nullptr;
1770         }
1771         // Create the OatDexFile and add it to the owning container.
1772         std::string location = DexFileLoader::GetMultiDexLocation(i, dex_location.c_str());
1773         std::string canonical_location = DexFileLoader::GetDexCanonicalLocation(location.c_str());
1774         type_lookup_table_start = vdex_file->GetNextTypeLookupTableData(type_lookup_table_start, i);
1775         const uint8_t* type_lookup_table_data = nullptr;
1776         if (!ComputeAndCheckTypeLookupTableData(*header,
1777                                                 type_lookup_table_start,
1778                                                 vdex_file,
1779                                                 &type_lookup_table_data,
1780                                                 error_msg)) {
1781           return nullptr;
1782         }
1783 
1784         OatDexFile* oat_dex_file = new OatDexFile(oat_file.get(),
1785                                                   dex_file_start,
1786                                                   vdex_file->GetLocationChecksum(i),
1787                                                   location,
1788                                                   canonical_location,
1789                                                   type_lookup_table_data);
1790         oat_file->oat_dex_files_storage_.push_back(oat_dex_file);
1791 
1792         std::string_view key(oat_dex_file->GetDexFileLocation());
1793         oat_file->oat_dex_files_.Put(key, oat_dex_file);
1794         if (canonical_location != location) {
1795           std::string_view canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
1796           oat_file->oat_dex_files_.Put(canonical_key, oat_dex_file);
1797         }
1798       }
1799       oat_file->SetupHeader(oat_file->oat_dex_files_storage_.size(), context);
1800     } else {
1801       // No need for any verification when loading dex files as we already have
1802       // a vdex file.
1803       bool loaded = false;
1804       if (zip_fd != -1) {
1805         ArtDexFileLoader dex_file_loader(zip_fd, dex_location);
1806         loaded = dex_file_loader.Open(/*verify=*/false,
1807                                       /*verify_checksum=*/false,
1808                                       error_msg,
1809                                       &oat_file->external_dex_files_);
1810       } else {
1811         ArtDexFileLoader dex_file_loader(dex_location);
1812         loaded = dex_file_loader.Open(/*verify=*/false,
1813                                       /*verify_checksum=*/false,
1814                                       error_msg,
1815                                       &oat_file->external_dex_files_);
1816       }
1817       if (!loaded) {
1818         return nullptr;
1819       }
1820       oat_file->SetupHeader(oat_file->external_dex_files_.size(), context);
1821       if (!oat_file->Setup(MakeNonOwningPointerVector(oat_file->external_dex_files_), error_msg)) {
1822         return nullptr;
1823       }
1824     }
1825 
1826     return oat_file.release();
1827   }
1828 
SetupHeader(size_t number_of_dex_files,ClassLoaderContext * context)1829   void SetupHeader(size_t number_of_dex_files, ClassLoaderContext* context) {
1830     DCHECK(!IsExecutable());
1831 
1832     // Create a fake OatHeader with a key store to help debugging.
1833     std::unique_ptr<const InstructionSetFeatures> isa_features =
1834         InstructionSetFeatures::FromCppDefines();
1835     SafeMap<std::string, std::string> store;
1836     store.Put(OatHeader::kCompilerFilter, CompilerFilter::NameOfFilter(CompilerFilter::kVerify));
1837     store.Put(OatHeader::kCompilationReasonKey, kReasonVdex);
1838     store.Put(OatHeader::kConcurrentCopying,
1839               gUseReadBarrier ? OatHeader::kTrueValue : OatHeader::kFalseValue);
1840     if (context != nullptr) {
1841       store.Put(OatHeader::kClassPathKey, context->EncodeContextForOatFile(""));
1842     }
1843 
1844     oat_header_.reset(OatHeader::Create(kRuntimeISA,
1845                                         isa_features.get(),
1846                                         number_of_dex_files,
1847                                         &store));
1848     const uint8_t* begin = reinterpret_cast<const uint8_t*>(oat_header_.get());
1849     SetBegin(begin);
1850     SetEnd(begin + oat_header_->GetHeaderSize());
1851   }
1852 
1853  protected:
PreLoad()1854   void PreLoad() override {}
1855 
Load(const std::string & elf_filename ATTRIBUTE_UNUSED,bool writable ATTRIBUTE_UNUSED,bool executable ATTRIBUTE_UNUSED,bool low_4gb ATTRIBUTE_UNUSED,MemMap * reservation ATTRIBUTE_UNUSED,std::string * error_msg ATTRIBUTE_UNUSED)1856   bool Load(const std::string& elf_filename ATTRIBUTE_UNUSED,
1857             bool writable ATTRIBUTE_UNUSED,
1858             bool executable ATTRIBUTE_UNUSED,
1859             bool low_4gb ATTRIBUTE_UNUSED,
1860             MemMap* reservation ATTRIBUTE_UNUSED,
1861             std::string* error_msg ATTRIBUTE_UNUSED) override {
1862     LOG(FATAL) << "Unsupported";
1863     UNREACHABLE();
1864   }
1865 
Load(int oat_fd ATTRIBUTE_UNUSED,bool writable ATTRIBUTE_UNUSED,bool executable ATTRIBUTE_UNUSED,bool low_4gb ATTRIBUTE_UNUSED,MemMap * reservation ATTRIBUTE_UNUSED,std::string * error_msg ATTRIBUTE_UNUSED)1866   bool Load(int oat_fd ATTRIBUTE_UNUSED,
1867             bool writable ATTRIBUTE_UNUSED,
1868             bool executable ATTRIBUTE_UNUSED,
1869             bool low_4gb ATTRIBUTE_UNUSED,
1870             MemMap* reservation ATTRIBUTE_UNUSED,
1871             std::string* error_msg ATTRIBUTE_UNUSED) override {
1872     LOG(FATAL) << "Unsupported";
1873     UNREACHABLE();
1874   }
1875 
PreSetup(const std::string & elf_filename ATTRIBUTE_UNUSED)1876   void PreSetup(const std::string& elf_filename ATTRIBUTE_UNUSED) override {}
1877 
FindDynamicSymbolAddress(const std::string & symbol_name ATTRIBUTE_UNUSED,std::string * error_msg) const1878   const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name ATTRIBUTE_UNUSED,
1879                                           std::string* error_msg) const override {
1880     *error_msg = "Unsupported";
1881     return nullptr;
1882   }
1883 
1884  private:
1885   std::unique_ptr<OatHeader> oat_header_;
1886 
1887   DISALLOW_COPY_AND_ASSIGN(OatFileBackedByVdex);
1888 };
1889 
1890 //////////////////////////
1891 // General OatFile code //
1892 //////////////////////////
1893 
CheckLocation(const std::string & location)1894 static void CheckLocation(const std::string& location) {
1895   CHECK(!location.empty());
1896 }
1897 
Open(int zip_fd,const std::string & oat_filename,const std::string & oat_location,bool executable,bool low_4gb,ArrayRef<const std::string> dex_filenames,ArrayRef<const int> dex_fds,MemMap * reservation,std::string * error_msg)1898 OatFile* OatFile::Open(int zip_fd,
1899                        const std::string& oat_filename,
1900                        const std::string& oat_location,
1901                        bool executable,
1902                        bool low_4gb,
1903                        ArrayRef<const std::string> dex_filenames,
1904                        ArrayRef<const int> dex_fds,
1905                        /*inout*/MemMap* reservation,
1906                        /*out*/std::string* error_msg) {
1907   ScopedTrace trace("Open oat file " + oat_location);
1908   CHECK(!oat_filename.empty()) << oat_location;
1909   CheckLocation(oat_location);
1910 
1911   std::string vdex_filename = GetVdexFilename(oat_filename);
1912 
1913   // Check that the vdex file even exists, fast-fail. We don't check the odex
1914   // file as we use the absence of an odex file for test the functionality of
1915   // vdex-only.
1916   if (!OS::FileExists(vdex_filename.c_str())) {
1917     *error_msg = StringPrintf("File %s does not exist.", vdex_filename.c_str());
1918     return nullptr;
1919   }
1920 
1921   // Try dlopen first, as it is required for native debuggability. This will fail fast if dlopen is
1922   // disabled.
1923   OatFile* with_dlopen = OatFileBase::OpenOatFile<DlOpenOatFile>(zip_fd,
1924                                                                  vdex_filename,
1925                                                                  oat_filename,
1926                                                                  oat_location,
1927                                                                  /*writable=*/false,
1928                                                                  executable,
1929                                                                  low_4gb,
1930                                                                  dex_filenames,
1931                                                                  dex_fds,
1932                                                                  reservation,
1933                                                                  error_msg);
1934   if (with_dlopen != nullptr) {
1935     return with_dlopen;
1936   }
1937   if (kPrintDlOpenErrorMessage) {
1938     LOG(ERROR) << "Failed to dlopen: " << oat_filename << " with error " << *error_msg;
1939   }
1940   // If we aren't trying to execute, we just use our own ElfFile loader for a couple reasons:
1941   //
1942   // On target, dlopen may fail when compiling due to selinux restrictions on installd.
1943   //
1944   // We use our own ELF loader for Quick to deal with legacy apps that
1945   // open a generated dex file by name, remove the file, then open
1946   // another generated dex file with the same name. http://b/10614658
1947   //
1948   // On host, dlopen is expected to fail when cross compiling, so fall back to ElfOatFile.
1949   //
1950   //
1951   // Another independent reason is the absolute placement of boot.oat. dlopen on the host usually
1952   // does honor the virtual address encoded in the ELF file only for ET_EXEC files, not ET_DYN.
1953   OatFile* with_internal = OatFileBase::OpenOatFile<ElfOatFile>(zip_fd,
1954                                                                 vdex_filename,
1955                                                                 oat_filename,
1956                                                                 oat_location,
1957                                                                 /*writable=*/false,
1958                                                                 executable,
1959                                                                 low_4gb,
1960                                                                 dex_filenames,
1961                                                                 dex_fds,
1962                                                                 reservation,
1963                                                                 error_msg);
1964   return with_internal;
1965 }
1966 
Open(int zip_fd,int vdex_fd,int oat_fd,const std::string & oat_location,bool executable,bool low_4gb,ArrayRef<const std::string> dex_filenames,ArrayRef<const int> dex_fds,MemMap * reservation,std::string * error_msg)1967 OatFile* OatFile::Open(int zip_fd,
1968                        int vdex_fd,
1969                        int oat_fd,
1970                        const std::string& oat_location,
1971                        bool executable,
1972                        bool low_4gb,
1973                        ArrayRef<const std::string> dex_filenames,
1974                        ArrayRef<const int> dex_fds,
1975                        /*inout*/MemMap* reservation,
1976                        /*out*/std::string* error_msg) {
1977   CHECK(!oat_location.empty()) << oat_location;
1978 
1979   std::string vdex_location = GetVdexFilename(oat_location);
1980 
1981   OatFile* with_internal = OatFileBase::OpenOatFile<ElfOatFile>(zip_fd,
1982                                                                 vdex_fd,
1983                                                                 oat_fd,
1984                                                                 vdex_location,
1985                                                                 oat_location,
1986                                                                 /*writable=*/false,
1987                                                                 executable,
1988                                                                 low_4gb,
1989                                                                 dex_filenames,
1990                                                                 dex_fds,
1991                                                                 reservation,
1992                                                                 error_msg);
1993   return with_internal;
1994 }
1995 
OpenFromVdex(const std::vector<const DexFile * > & dex_files,std::unique_ptr<VdexFile> && vdex_file,const std::string & location,ClassLoaderContext * context)1996 OatFile* OatFile::OpenFromVdex(const std::vector<const DexFile*>& dex_files,
1997                                std::unique_ptr<VdexFile>&& vdex_file,
1998                                const std::string& location,
1999                                ClassLoaderContext* context) {
2000   CheckLocation(location);
2001   return OatFileBackedByVdex::Open(dex_files, std::move(vdex_file), location, context);
2002 }
2003 
OpenFromVdex(int zip_fd,std::unique_ptr<VdexFile> && vdex_file,const std::string & location,ClassLoaderContext * context,std::string * error_msg)2004 OatFile* OatFile::OpenFromVdex(int zip_fd,
2005                                std::unique_ptr<VdexFile>&& vdex_file,
2006                                const std::string& location,
2007                                ClassLoaderContext* context,
2008                                std::string* error_msg) {
2009   CheckLocation(location);
2010   return OatFileBackedByVdex::Open(zip_fd, std::move(vdex_file), location, context, error_msg);
2011 }
2012 
OatFile(const std::string & location,bool is_executable)2013 OatFile::OatFile(const std::string& location, bool is_executable)
2014     : location_(location),
2015       vdex_(nullptr),
2016       begin_(nullptr),
2017       end_(nullptr),
2018       data_bimg_rel_ro_begin_(nullptr),
2019       data_bimg_rel_ro_end_(nullptr),
2020       bss_begin_(nullptr),
2021       bss_end_(nullptr),
2022       bss_methods_(nullptr),
2023       bss_roots_(nullptr),
2024       is_executable_(is_executable),
2025       vdex_begin_(nullptr),
2026       vdex_end_(nullptr),
2027       secondary_lookup_lock_("OatFile secondary lookup lock", kOatFileSecondaryLookupLock) {
2028   CHECK(!location_.empty());
2029 }
2030 
~OatFile()2031 OatFile::~OatFile() {
2032   STLDeleteElements(&oat_dex_files_storage_);
2033 }
2034 
GetOatHeader() const2035 const OatHeader& OatFile::GetOatHeader() const {
2036   return *reinterpret_cast<const OatHeader*>(Begin());
2037 }
2038 
Begin() const2039 const uint8_t* OatFile::Begin() const {
2040   CHECK(begin_ != nullptr);
2041   return begin_;
2042 }
2043 
End() const2044 const uint8_t* OatFile::End() const {
2045   CHECK(end_ != nullptr);
2046   return end_;
2047 }
2048 
DexBegin() const2049 const uint8_t* OatFile::DexBegin() const {
2050   return vdex_->Begin();
2051 }
2052 
DexEnd() const2053 const uint8_t* OatFile::DexEnd() const {
2054   return vdex_->End();
2055 }
2056 
GetBootImageRelocations() const2057 ArrayRef<const uint32_t> OatFile::GetBootImageRelocations() const {
2058   if (data_bimg_rel_ro_begin_ != nullptr) {
2059     const uint32_t* relocations = reinterpret_cast<const uint32_t*>(data_bimg_rel_ro_begin_);
2060     const uint32_t* relocations_end = reinterpret_cast<const uint32_t*>(data_bimg_rel_ro_end_);
2061     return ArrayRef<const uint32_t>(relocations, relocations_end - relocations);
2062   } else {
2063     return ArrayRef<const uint32_t>();
2064   }
2065 }
2066 
GetBssMethods() const2067 ArrayRef<ArtMethod*> OatFile::GetBssMethods() const {
2068   if (bss_methods_ != nullptr) {
2069     ArtMethod** methods = reinterpret_cast<ArtMethod**>(bss_methods_);
2070     ArtMethod** methods_end =
2071         reinterpret_cast<ArtMethod**>(bss_roots_ != nullptr ? bss_roots_ : bss_end_);
2072     return ArrayRef<ArtMethod*>(methods, methods_end - methods);
2073   } else {
2074     return ArrayRef<ArtMethod*>();
2075   }
2076 }
2077 
GetBssGcRoots() const2078 ArrayRef<GcRoot<mirror::Object>> OatFile::GetBssGcRoots() const {
2079   if (bss_roots_ != nullptr) {
2080     auto* roots = reinterpret_cast<GcRoot<mirror::Object>*>(bss_roots_);
2081     auto* roots_end = reinterpret_cast<GcRoot<mirror::Object>*>(bss_end_);
2082     return ArrayRef<GcRoot<mirror::Object>>(roots, roots_end - roots);
2083   } else {
2084     return ArrayRef<GcRoot<mirror::Object>>();
2085   }
2086 }
2087 
GetOatDexFile(const char * dex_location,const uint32_t * dex_location_checksum,std::string * error_msg) const2088 const OatDexFile* OatFile::GetOatDexFile(const char* dex_location,
2089                                          const uint32_t* dex_location_checksum,
2090                                          std::string* error_msg) const {
2091   // NOTE: We assume here that the canonical location for a given dex_location never
2092   // changes. If it does (i.e. some symlink used by the filename changes) we may return
2093   // an incorrect OatDexFile. As long as we have a checksum to check, we shall return
2094   // an identical file or fail; otherwise we may see some unpredictable failures.
2095 
2096   // TODO: Additional analysis of usage patterns to see if this can be simplified
2097   // without any performance loss, for example by not doing the first lock-free lookup.
2098 
2099   const OatDexFile* oat_dex_file = nullptr;
2100   std::string_view key(dex_location);
2101   // Try to find the key cheaply in the oat_dex_files_ map which holds dex locations
2102   // directly mentioned in the oat file and doesn't require locking.
2103   auto primary_it = oat_dex_files_.find(key);
2104   if (primary_it != oat_dex_files_.end()) {
2105     oat_dex_file = primary_it->second;
2106     DCHECK(oat_dex_file != nullptr);
2107   } else {
2108     // This dex_location is not one of the dex locations directly mentioned in the
2109     // oat file. The correct lookup is via the canonical location but first see in
2110     // the secondary_oat_dex_files_ whether we've looked up this location before.
2111     MutexLock mu(Thread::Current(), secondary_lookup_lock_);
2112     auto secondary_lb = secondary_oat_dex_files_.lower_bound(key);
2113     if (secondary_lb != secondary_oat_dex_files_.end() && key == secondary_lb->first) {
2114       oat_dex_file = secondary_lb->second;  // May be null.
2115     } else {
2116       // We haven't seen this dex_location before, we must check the canonical location.
2117       std::string dex_canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location);
2118       if (dex_canonical_location != dex_location) {
2119         std::string_view canonical_key(dex_canonical_location);
2120         auto canonical_it = oat_dex_files_.find(canonical_key);
2121         if (canonical_it != oat_dex_files_.end()) {
2122           oat_dex_file = canonical_it->second;
2123         }  // else keep null.
2124       }  // else keep null.
2125 
2126       // Copy the key to the string_cache_ and store the result in secondary map.
2127       string_cache_.emplace_back(key.data(), key.length());
2128       std::string_view key_copy(string_cache_.back());
2129       secondary_oat_dex_files_.PutBefore(secondary_lb, key_copy, oat_dex_file);
2130     }
2131   }
2132 
2133   if (oat_dex_file == nullptr) {
2134     if (error_msg != nullptr) {
2135       std::string dex_canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location);
2136       *error_msg = "Failed to find OatDexFile for DexFile " + std::string(dex_location)
2137           + " (canonical path " + dex_canonical_location + ") in OatFile " + GetLocation();
2138     }
2139     return nullptr;
2140   }
2141 
2142   if (dex_location_checksum != nullptr &&
2143       oat_dex_file->GetDexFileLocationChecksum() != *dex_location_checksum) {
2144     if (error_msg != nullptr) {
2145       std::string dex_canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location);
2146       std::string checksum = StringPrintf("0x%08x", oat_dex_file->GetDexFileLocationChecksum());
2147       std::string required_checksum = StringPrintf("0x%08x", *dex_location_checksum);
2148       *error_msg = "OatDexFile for DexFile " + std::string(dex_location)
2149           + " (canonical path " + dex_canonical_location + ") in OatFile " + GetLocation()
2150           + " has checksum " + checksum + " but " + required_checksum + " was required";
2151     }
2152     return nullptr;
2153   }
2154   return oat_dex_file;
2155 }
2156 
OatDexFile(const OatFile * oat_file,const std::string & dex_file_location,const std::string & canonical_dex_file_location,uint32_t dex_file_location_checksum,const uint8_t * dex_file_pointer,const uint8_t * lookup_table_data,const IndexBssMapping * method_bss_mapping_data,const IndexBssMapping * type_bss_mapping_data,const IndexBssMapping * public_type_bss_mapping_data,const IndexBssMapping * package_type_bss_mapping_data,const IndexBssMapping * string_bss_mapping_data,const uint32_t * oat_class_offsets_pointer,const DexLayoutSections * dex_layout_sections)2157 OatDexFile::OatDexFile(const OatFile* oat_file,
2158                        const std::string& dex_file_location,
2159                        const std::string& canonical_dex_file_location,
2160                        uint32_t dex_file_location_checksum,
2161                        const uint8_t* dex_file_pointer,
2162                        const uint8_t* lookup_table_data,
2163                        const IndexBssMapping* method_bss_mapping_data,
2164                        const IndexBssMapping* type_bss_mapping_data,
2165                        const IndexBssMapping* public_type_bss_mapping_data,
2166                        const IndexBssMapping* package_type_bss_mapping_data,
2167                        const IndexBssMapping* string_bss_mapping_data,
2168                        const uint32_t* oat_class_offsets_pointer,
2169                        const DexLayoutSections* dex_layout_sections)
2170     : oat_file_(oat_file),
2171       dex_file_location_(dex_file_location),
2172       canonical_dex_file_location_(canonical_dex_file_location),
2173       dex_file_location_checksum_(dex_file_location_checksum),
2174       dex_file_pointer_(dex_file_pointer),
2175       lookup_table_data_(lookup_table_data),
2176       method_bss_mapping_(method_bss_mapping_data),
2177       type_bss_mapping_(type_bss_mapping_data),
2178       public_type_bss_mapping_(public_type_bss_mapping_data),
2179       package_type_bss_mapping_(package_type_bss_mapping_data),
2180       string_bss_mapping_(string_bss_mapping_data),
2181       oat_class_offsets_pointer_(oat_class_offsets_pointer),
2182       lookup_table_(),
2183       dex_layout_sections_(dex_layout_sections) {
2184   InitializeTypeLookupTable();
2185   DCHECK(!IsBackedByVdexOnly());
2186 }
2187 
InitializeTypeLookupTable()2188 void OatDexFile::InitializeTypeLookupTable() {
2189   // Initialize TypeLookupTable.
2190   if (lookup_table_data_ != nullptr) {
2191     // Peek the number of classes from the DexFile.
2192     const DexFile::Header* dex_header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer_);
2193     const uint32_t num_class_defs = dex_header->class_defs_size_;
2194     if (lookup_table_data_ + TypeLookupTable::RawDataLength(num_class_defs) >
2195             GetOatFile()->DexEnd()) {
2196       LOG(WARNING) << "found truncated lookup table in " << dex_file_location_;
2197     } else {
2198       const uint8_t* dex_data = dex_file_pointer_;
2199       // TODO: Clean this up to create the type lookup table after the dex file has been created?
2200       if (CompactDexFile::IsMagicValid(dex_header->magic_)) {
2201         dex_data += dex_header->data_off_;
2202       }
2203       lookup_table_ = TypeLookupTable::Open(dex_data, lookup_table_data_, num_class_defs);
2204     }
2205   }
2206 }
2207 
OatDexFile(const OatFile * oat_file,const uint8_t * dex_file_pointer,uint32_t dex_file_location_checksum,const std::string & dex_file_location,const std::string & canonical_dex_file_location,const uint8_t * lookup_table_data)2208 OatDexFile::OatDexFile(const OatFile* oat_file,
2209                        const uint8_t* dex_file_pointer,
2210                        uint32_t dex_file_location_checksum,
2211                        const std::string& dex_file_location,
2212                        const std::string& canonical_dex_file_location,
2213                        const uint8_t* lookup_table_data)
2214     : oat_file_(oat_file),
2215       dex_file_location_(dex_file_location),
2216       canonical_dex_file_location_(canonical_dex_file_location),
2217       dex_file_location_checksum_(dex_file_location_checksum),
2218       dex_file_pointer_(dex_file_pointer),
2219       lookup_table_data_(lookup_table_data) {
2220   InitializeTypeLookupTable();
2221   DCHECK(IsBackedByVdexOnly());
2222 }
2223 
OatDexFile(TypeLookupTable && lookup_table)2224 OatDexFile::OatDexFile(TypeLookupTable&& lookup_table) : lookup_table_(std::move(lookup_table)) {
2225   // Stripped-down OatDexFile only allowed in the compiler, the zygote, or the system server.
2226   CHECK(Runtime::Current() == nullptr ||
2227         Runtime::Current()->IsAotCompiler() ||
2228         Runtime::Current()->IsZygote() ||
2229         Runtime::Current()->IsSystemServer());
2230 }
2231 
~OatDexFile()2232 OatDexFile::~OatDexFile() {}
2233 
FileSize() const2234 size_t OatDexFile::FileSize() const {
2235   DCHECK(dex_file_pointer_ != nullptr);
2236   return reinterpret_cast<const DexFile::Header*>(dex_file_pointer_)->file_size_;
2237 }
2238 
OpenDexFile(std::string * error_msg) const2239 std::unique_ptr<const DexFile> OatDexFile::OpenDexFile(std::string* error_msg) const {
2240   ScopedTrace trace(__PRETTY_FUNCTION__);
2241   static constexpr bool kVerify = false;
2242   static constexpr bool kVerifyChecksum = false;
2243   ArtDexFileLoader dex_file_loader(dex_file_pointer_, FileSize(), dex_file_location_);
2244   return dex_file_loader.Open(
2245       dex_file_location_checksum_, this, kVerify, kVerifyChecksum, error_msg);
2246 }
2247 
GetOatClassOffset(uint16_t class_def_index) const2248 uint32_t OatDexFile::GetOatClassOffset(uint16_t class_def_index) const {
2249   DCHECK(oat_class_offsets_pointer_ != nullptr);
2250   return oat_class_offsets_pointer_[class_def_index];
2251 }
2252 
IsBackedByVdexOnly() const2253 bool OatDexFile::IsBackedByVdexOnly() const {
2254   return oat_class_offsets_pointer_ == nullptr;
2255 }
2256 
GetOatClass(uint16_t class_def_index) const2257 OatFile::OatClass OatDexFile::GetOatClass(uint16_t class_def_index) const {
2258   if (IsBackedByVdexOnly()) {
2259     // If there is only a vdex file, return that the class is not ready. The
2260     // caller will have to call `VdexFile::ComputeClassStatus` to compute the
2261     // actual class status, because we need to do the assignability type checks.
2262     return OatFile::OatClass(oat_file_,
2263                              ClassStatus::kNotReady,
2264                              /* type= */ OatClassType::kNoneCompiled,
2265                              /* num_methods= */ 0u,
2266                              /* bitmap_pointer= */ nullptr,
2267                              /* methods_pointer= */ nullptr);
2268   }
2269 
2270   uint32_t oat_class_offset = GetOatClassOffset(class_def_index);
2271   CHECK_GE(oat_class_offset, sizeof(OatHeader)) << oat_file_->GetLocation();
2272   CHECK_LT(oat_class_offset, oat_file_->Size()) << oat_file_->GetLocation();
2273   CHECK_LE(/* status */ sizeof(uint16_t) + /* type */ sizeof(uint16_t),
2274            oat_file_->Size() - oat_class_offset) << oat_file_->GetLocation();
2275   const uint8_t* current_pointer = oat_file_->Begin() + oat_class_offset;
2276 
2277   uint16_t status_value = *reinterpret_cast<const uint16_t*>(current_pointer);
2278   current_pointer += sizeof(uint16_t);
2279   uint16_t type_value = *reinterpret_cast<const uint16_t*>(current_pointer);
2280   current_pointer += sizeof(uint16_t);
2281   CHECK_LE(status_value, enum_cast<uint8_t>(ClassStatus::kLast))
2282       << static_cast<uint32_t>(status_value) << " at " << oat_file_->GetLocation();
2283   CHECK_LT(type_value, enum_cast<uint8_t>(OatClassType::kOatClassMax)) << oat_file_->GetLocation();
2284   ClassStatus status = enum_cast<ClassStatus>(status_value);
2285   OatClassType type = enum_cast<OatClassType>(type_value);
2286 
2287   uint32_t num_methods = 0;
2288   const uint32_t* bitmap_pointer = nullptr;
2289   const OatMethodOffsets* methods_pointer = nullptr;
2290   if (type != OatClassType::kNoneCompiled) {
2291     CHECK_LE(sizeof(uint32_t), static_cast<size_t>(oat_file_->End() - current_pointer))
2292         << oat_file_->GetLocation();
2293     num_methods = *reinterpret_cast<const uint32_t*>(current_pointer);
2294     current_pointer += sizeof(uint32_t);
2295     CHECK_NE(num_methods, 0u) << oat_file_->GetLocation();
2296     uint32_t num_method_offsets;
2297     if (type == OatClassType::kSomeCompiled) {
2298       uint32_t bitmap_size = BitVector::BitsToWords(num_methods) * BitVector::kWordBytes;
2299       CHECK_LE(bitmap_size, static_cast<size_t>(oat_file_->End() - current_pointer))
2300           << oat_file_->GetLocation();
2301       bitmap_pointer = reinterpret_cast<const uint32_t*>(current_pointer);
2302       current_pointer += bitmap_size;
2303       // Note: The bits in range [num_methods, bitmap_size * kBitsPerByte)
2304       // should be zero but we're not verifying that.
2305       num_method_offsets = BitVector::NumSetBits(bitmap_pointer, num_methods);
2306     } else {
2307       num_method_offsets = num_methods;
2308     }
2309     CHECK_LE(num_method_offsets,
2310              static_cast<size_t>(oat_file_->End() - current_pointer) / sizeof(OatMethodOffsets))
2311         << oat_file_->GetLocation();
2312     methods_pointer = reinterpret_cast<const OatMethodOffsets*>(current_pointer);
2313   }
2314 
2315   return OatFile::OatClass(oat_file_, status, type, num_methods, bitmap_pointer, methods_pointer);
2316 }
2317 
FindClassDef(const DexFile & dex_file,const char * descriptor,size_t hash)2318 const dex::ClassDef* OatDexFile::FindClassDef(const DexFile& dex_file,
2319                                               const char* descriptor,
2320                                               size_t hash) {
2321   const OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
2322   DCHECK_EQ(ComputeModifiedUtf8Hash(descriptor), hash);
2323   bool used_lookup_table = false;
2324   const dex::ClassDef* lookup_table_classdef = nullptr;
2325   if (LIKELY((oat_dex_file != nullptr) && oat_dex_file->GetTypeLookupTable().Valid())) {
2326     used_lookup_table = true;
2327     const uint32_t class_def_idx = oat_dex_file->GetTypeLookupTable().Lookup(descriptor, hash);
2328     if (class_def_idx != dex::kDexNoIndex) {
2329       CHECK_LT(class_def_idx, dex_file.NumClassDefs()) << oat_dex_file->GetOatFile()->GetLocation();
2330       lookup_table_classdef = &dex_file.GetClassDef(class_def_idx);
2331     }
2332     if (!kIsDebugBuild) {
2333       return lookup_table_classdef;
2334     }
2335   }
2336   // Fast path for rare no class defs case.
2337   const uint32_t num_class_defs = dex_file.NumClassDefs();
2338   if (num_class_defs == 0) {
2339     DCHECK(!used_lookup_table);
2340     return nullptr;
2341   }
2342   const dex::TypeId* type_id = dex_file.FindTypeId(descriptor);
2343   if (type_id != nullptr) {
2344     dex::TypeIndex type_idx = dex_file.GetIndexForTypeId(*type_id);
2345     const dex::ClassDef* found_class_def = dex_file.FindClassDef(type_idx);
2346     if (kIsDebugBuild && used_lookup_table) {
2347       DCHECK_EQ(found_class_def, lookup_table_classdef);
2348     }
2349     return found_class_def;
2350   }
2351   return nullptr;
2352 }
2353 
OatClass(const OatFile * oat_file,ClassStatus status,OatClassType type,uint32_t num_methods,const uint32_t * bitmap_pointer,const OatMethodOffsets * methods_pointer)2354 OatFile::OatClass::OatClass(const OatFile* oat_file,
2355                             ClassStatus status,
2356                             OatClassType type,
2357                             uint32_t num_methods,
2358                             const uint32_t* bitmap_pointer,
2359                             const OatMethodOffsets* methods_pointer)
2360     : oat_file_(oat_file),
2361       status_(status),
2362       type_(type),
2363       num_methods_(num_methods),
2364       bitmap_(bitmap_pointer),
2365       methods_pointer_(methods_pointer) {
2366   DCHECK_EQ(num_methods != 0u, type != OatClassType::kNoneCompiled);
2367   DCHECK_EQ(bitmap_pointer != nullptr, type == OatClassType::kSomeCompiled);
2368   DCHECK_EQ(methods_pointer != nullptr, type != OatClassType::kNoneCompiled);
2369 }
2370 
GetOatMethodOffsetsOffset(uint32_t method_index) const2371 uint32_t OatFile::OatClass::GetOatMethodOffsetsOffset(uint32_t method_index) const {
2372   const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
2373   if (oat_method_offsets == nullptr) {
2374     return 0u;
2375   }
2376   return reinterpret_cast<const uint8_t*>(oat_method_offsets) - oat_file_->Begin();
2377 }
2378 
GetOatMethodOffsets(uint32_t method_index) const2379 const OatMethodOffsets* OatFile::OatClass::GetOatMethodOffsets(uint32_t method_index) const {
2380   // NOTE: We don't keep the number of methods for `kNoneCompiled` and cannot do
2381   // a bounds check for `method_index` in that case.
2382   if (methods_pointer_ == nullptr) {
2383     CHECK_EQ(OatClassType::kNoneCompiled, type_);
2384     return nullptr;
2385   }
2386   CHECK_LT(method_index, num_methods_) << oat_file_->GetLocation();
2387   size_t methods_pointer_index;
2388   if (bitmap_ == nullptr) {
2389     CHECK_EQ(OatClassType::kAllCompiled, type_);
2390     methods_pointer_index = method_index;
2391   } else {
2392     CHECK_EQ(OatClassType::kSomeCompiled, type_);
2393     if (!BitVector::IsBitSet(bitmap_, method_index)) {
2394       return nullptr;
2395     }
2396     size_t num_set_bits = BitVector::NumSetBits(bitmap_, method_index);
2397     methods_pointer_index = num_set_bits;
2398   }
2399   if (kIsDebugBuild) {
2400     size_t size_until_end = dchecked_integral_cast<size_t>(
2401         oat_file_->End() - reinterpret_cast<const uint8_t*>(methods_pointer_));
2402     CHECK_LE(methods_pointer_index, size_until_end / sizeof(OatMethodOffsets))
2403         << oat_file_->GetLocation();
2404   }
2405   const OatMethodOffsets& oat_method_offsets = methods_pointer_[methods_pointer_index];
2406   return &oat_method_offsets;
2407 }
2408 
GetOatMethod(uint32_t method_index) const2409 const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) const {
2410   const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
2411   if (oat_method_offsets == nullptr) {
2412     return OatMethod(nullptr, 0);
2413   }
2414   if (oat_file_->IsExecutable() ||
2415       Runtime::Current() == nullptr ||        // This case applies for oatdump.
2416       Runtime::Current()->IsAotCompiler()) {
2417     return OatMethod(oat_file_->Begin(), oat_method_offsets->code_offset_);
2418   }
2419   // We aren't allowed to use the compiled code. We just force it down the interpreted / jit
2420   // version.
2421   return OatMethod(oat_file_->Begin(), 0);
2422 }
2423 
IsDebuggable() const2424 bool OatFile::IsDebuggable() const {
2425   return GetOatHeader().IsDebuggable();
2426 }
2427 
GetCompilerFilter() const2428 CompilerFilter::Filter OatFile::GetCompilerFilter() const {
2429   return GetOatHeader().GetCompilerFilter();
2430 }
2431 
GetClassLoaderContext() const2432 std::string OatFile::GetClassLoaderContext() const {
2433   const char* value = GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey);
2434   return (value == nullptr) ? "" : value;
2435 }
2436 
GetCompilationReason() const2437 const char* OatFile::GetCompilationReason() const {
2438   return GetOatHeader().GetStoreValueByKey(OatHeader::kCompilationReasonKey);
2439 }
2440 
FindOatClass(const DexFile & dex_file,uint16_t class_def_idx,bool * found)2441 OatFile::OatClass OatFile::FindOatClass(const DexFile& dex_file,
2442                                         uint16_t class_def_idx,
2443                                         bool* found) {
2444   CHECK_LT(class_def_idx, dex_file.NumClassDefs());
2445   const OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
2446   if (oat_dex_file == nullptr || oat_dex_file->GetOatFile() == nullptr) {
2447     *found = false;
2448     return OatFile::OatClass::Invalid();
2449   }
2450   *found = true;
2451   return oat_dex_file->GetOatClass(class_def_idx);
2452 }
2453 
RequiresImage() const2454 bool OatFile::RequiresImage() const { return GetOatHeader().RequiresImage(); }
2455 
DCheckIndexToBssMapping(const OatFile * oat_file,uint32_t number_of_indexes,size_t slot_size,const IndexBssMapping * index_bss_mapping)2456 static void DCheckIndexToBssMapping(const OatFile* oat_file,
2457                                     uint32_t number_of_indexes,
2458                                     size_t slot_size,
2459                                     const IndexBssMapping* index_bss_mapping) {
2460   if (kIsDebugBuild && index_bss_mapping != nullptr) {
2461     size_t index_bits = IndexBssMappingEntry::IndexBits(number_of_indexes);
2462     const IndexBssMappingEntry* prev_entry = nullptr;
2463     for (const IndexBssMappingEntry& entry : *index_bss_mapping) {
2464       CHECK_ALIGNED_PARAM(entry.bss_offset, slot_size);
2465       CHECK_LT(entry.bss_offset, oat_file->BssSize());
2466       uint32_t mask = entry.GetMask(index_bits);
2467       CHECK_LE(POPCOUNT(mask) * slot_size, entry.bss_offset);
2468       size_t index_mask_span = (mask != 0u) ? 32u - index_bits - CTZ(mask) : 0u;
2469       CHECK_LE(index_mask_span, entry.GetIndex(index_bits));
2470       if (prev_entry != nullptr) {
2471         CHECK_LT(prev_entry->GetIndex(index_bits), entry.GetIndex(index_bits) - index_mask_span);
2472       }
2473       prev_entry = &entry;
2474     }
2475     CHECK(prev_entry != nullptr);
2476     CHECK_LT(prev_entry->GetIndex(index_bits), number_of_indexes);
2477   }
2478 }
2479 
InitializeRelocations() const2480 void OatFile::InitializeRelocations() const {
2481   DCHECK(IsExecutable());
2482 
2483   // Initialize the .data.bimg.rel.ro section.
2484   if (!GetBootImageRelocations().empty()) {
2485     uint8_t* reloc_begin = const_cast<uint8_t*>(DataBimgRelRoBegin());
2486     CheckedCall(mprotect,
2487                 "un-protect boot image relocations",
2488                 reloc_begin,
2489                 DataBimgRelRoSize(),
2490                 PROT_READ | PROT_WRITE);
2491     uint32_t boot_image_begin = Runtime::Current()->GetHeap()->GetBootImagesStartAddress();
2492     for (const uint32_t& relocation : GetBootImageRelocations()) {
2493       const_cast<uint32_t&>(relocation) += boot_image_begin;
2494     }
2495     CheckedCall(mprotect,
2496                 "protect boot image relocations",
2497                 reloc_begin,
2498                 DataBimgRelRoSize(),
2499                 PROT_READ);
2500   }
2501 
2502   // Before initializing .bss, check the .bss mappings in debug mode.
2503   if (kIsDebugBuild) {
2504     PointerSize pointer_size = GetInstructionSetPointerSize(GetOatHeader().GetInstructionSet());
2505     for (const OatDexFile* odf : GetOatDexFiles()) {
2506       const DexFile::Header* header =
2507           reinterpret_cast<const DexFile::Header*>(odf->GetDexFilePointer());
2508       DCheckIndexToBssMapping(this,
2509                               header->method_ids_size_,
2510                               static_cast<size_t>(pointer_size),
2511                               odf->GetMethodBssMapping());
2512       DCheckIndexToBssMapping(this,
2513                               header->type_ids_size_,
2514                               sizeof(GcRoot<mirror::Class>),
2515                               odf->GetTypeBssMapping());
2516       DCheckIndexToBssMapping(this,
2517                               header->string_ids_size_,
2518                               sizeof(GcRoot<mirror::String>),
2519                               odf->GetStringBssMapping());
2520     }
2521   }
2522 
2523   // Initialize the .bss section.
2524   // TODO: Pre-initialize from boot/app image?
2525   ArtMethod* resolution_method = Runtime::Current()->GetResolutionMethod();
2526   for (ArtMethod*& entry : GetBssMethods()) {
2527     entry = resolution_method;
2528   }
2529 }
2530 
AssertAotCompiler()2531 void OatDexFile::AssertAotCompiler() {
2532   CHECK(Runtime::Current()->IsAotCompiler());
2533 }
2534 
IsBackedByVdexOnly() const2535 bool OatFile::IsBackedByVdexOnly() const {
2536   return oat_dex_files_storage_.size() >= 1 && oat_dex_files_storage_[0]->IsBackedByVdexOnly();
2537 }
2538 
2539 }  // namespace art
2540