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