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